diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs index ffdbf254..99a81e6c 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs @@ -31,7 +31,7 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests { if (state.CurrentBlock is INameAssignable nameAssignableBlock) { - nameAssignableBlock.AssignName(GetMatcherTokens(NameToken)[0]); + nameAssignableBlock.AssignName(NextMatch(NameToken)); } else { diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs index 1b98edf0..9e1e7d17 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs @@ -29,12 +29,12 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { var isTypedef = HasMatcherTokens(TypedefToken); - var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName(); + var name = NextMatch(NameToken) ?? RandomName.GenerateName(); var parentType = DataTypeBaseType.INT; if (HasMatcherTokens(TypenameToken)) { - var typeName = GetMatcherTokens(TypenameToken)[0]; + var typeName = NextMatch(TypenameToken); var type = state.FindType(typeName); if (type == null) diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs index d1608f1b..388b2b7e 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs @@ -34,7 +34,7 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { - var name = GetMatcherTokens(NameToken)[0]; + var name = NextMatch(NameToken); long value; if (!(state.CurrentBlock is BlockEnum _enum)) @@ -42,11 +42,11 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests if (HasMatcherTokens(NumberValueToken)) { - value = long.Parse(GetMatcherTokens(NumberValueToken)[0]); + value = long.Parse(NextMatch(NumberValueToken)); } else if(HasMatcherTokens(EnumMemberValueToken)) { - var stringValue = GetMatcherTokens(EnumMemberValueToken)[0]; + var stringValue = NextMatch(EnumMemberValueToken); var memberWithFittingName = state.FindEnumMember(stringValue); if(memberWithFittingName == null) diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs index c3e42a45..06b132fe 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs @@ -30,7 +30,7 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { - var name = GetMatcherTokens(NameToken)[0]; + var name = NextMatch(NameToken); var _namespace = state.CurrentNamespace.ToString(); if (HasMatcherTokens(EnumToken)) diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs index 3b169bb6..e51f07ae 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs @@ -23,7 +23,7 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { - state.PushBlock(new BlockNamespace(state, GetMatcherTokens(NamespaceNameToken)[0])); + state.PushBlock(new BlockNamespace(state, NextMatch(NamespaceNameToken))); } } } diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs index 12d0295d..0ed4b12f 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs @@ -43,16 +43,16 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { var isTypedef = HasMatcherTokens(TypedefToken); - var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName(); + var name = NextMatch(NameToken) ?? RandomName.GenerateName(); var block = new BlockStruct(state, name, isTypedef); if (HasMatcherTokens(AlignToken)) - block.CustomAlignment = int.Parse(GetMatcherTokens(AlignToken)[0]); + block.CustomAlignment = int.Parse(NextMatch(AlignToken)); if (HasMatcherTokens(ParentToken)) { - var parentDataTypeName = GetMatcherTokens(ParentToken)[0]; + var parentDataTypeName = NextMatch(ParentToken); var parentDataType = state.FindType(parentDataTypeName); if(parentDataType == null) diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs index c4290a83..5429b55a 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs @@ -50,22 +50,22 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { - var name = GetMatcherTokens(NameToken)[0]; - var pointerDepth = GetMatcherTokens(PointerTokens).Count; + var name = NextMatch(NameToken); + var pointerDepth = GetMatcherTokenCount(PointerTokens); - var typeName = string.Join(" ", GetMatcherTokens(TypeNameTokens)); + var typeName = NextMatch(TypeNameTokens); var type = state.FindType(typeName); if (type == null) throw new TestFailedException($"Could not find type '{typeName}' of typedef '{name}'."); - var arrayTokens = GetMatcherTokens(ArrayTokens); - var arraySize = new int[arrayTokens.Count]; - - for(var i = 0; i < arrayTokens.Count; i++) + var arraySize = new int[GetMatcherTokenCount(ArrayTokens)]; + string arrayToken; + var index = 0; + while((arrayToken = NextMatch(ArrayTokens)) != null) { - if (!int.TryParse(arrayTokens[i], out arraySize[i])) - throw new TestFailedException($"Array size '{arrayTokens[i]}' is not numeric."); + if (!int.TryParse(arrayToken, out arraySize[index++])) + throw new TestFailedException($"Array size '{arrayToken}' is not numeric."); } var references = new List(); diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs index 935ae8ec..4ef679a3 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs @@ -43,16 +43,16 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { var isTypedef = HasMatcherTokens(TypedefToken); - var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName(); + var name = NextMatch(NameToken) ?? RandomName.GenerateName(); var block = new BlockUnion(state, name, isTypedef); if (HasMatcherTokens(AlignToken)) - block.CustomAlignment = int.Parse(GetMatcherTokens(AlignToken)[0]); + block.CustomAlignment = int.Parse(NextMatch(AlignToken)); if (HasMatcherTokens(ParentToken)) { - var parentDataTypeName = GetMatcherTokens(ParentToken)[0]; + var parentDataTypeName = NextMatch(ParentToken); var parentDataType = state.FindType(parentDataTypeName); if(parentDataType == null) diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs index 4b8fa6f4..b2ff23ba 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs @@ -55,26 +55,26 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests protected override void ProcessMatch(IHeaderParserState state) { - var name = GetMatcherTokens(NameToken)[0]; - var typeName = GetMatcherTokens(TypeNameToken)[0]; + var name = NextMatch(NameToken); + var typeName = NextMatch(TypeNameToken); var type = state.FindType(typeName); if (type == null) throw new TestFailedException($"Type '{typeName}' not found."); - var pointerDepth = GetMatcherTokens(PointerTokens).Count; - - var arrayTokens = GetMatcherTokens(ArrayTokens); - var arraySize = new int[arrayTokens.Count]; + var pointerDepth = GetMatcherTokenCount(PointerTokens); int? bitSize = null; if (HasMatcherTokens(BitSizeToken)) - bitSize = int.Parse(GetMatcherTokens(BitSizeToken)[0]); + bitSize = int.Parse(NextMatch(BitSizeToken)); - for(var i = 0; i < arrayTokens.Count; i++) + string arrayToken; + var index = 0; + var arraySize = new int[GetMatcherTokenCount(ArrayTokens)]; + while ((arrayToken = NextMatch(ArrayTokens)) != null) { - if (!int.TryParse(arrayTokens[i], out arraySize[i])) - throw new TestFailedException($"Array size '{arrayTokens[i]}' is not numeric."); + if (!int.TryParse(arrayToken, out arraySize[index++])) + throw new TestFailedException($"Array size '{arrayToken}' is not numeric."); } if (state.CurrentBlock is IVariableHolder variableHolder) diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs index f4d0955a..1f247a80 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs @@ -28,7 +28,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests protected override void ProcessMatch(ICommandParserState state) { - var assetTypeName = GetMatcherTokens(AssetTypeNameToken)[0]; + var assetTypeName = NextMatch(AssetTypeNameToken); var assetType = state.Repository.GetDataTypeByName(assetTypeName); if (assetType == null) @@ -47,7 +47,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests throw new LoadingException($"Could not find information for type '{assetTypeName}' to mark it as an asset."); } - var enumEntryName = GetMatcherTokens(AssetEnumEntryToken)[0]; + var enumEntryName = NextMatch(AssetEnumEntryToken); var enumEntry = state.Repository.GetAllEnums() .SelectMany(_enum => _enum.Members) .FirstOrDefault(member => member.Name.Equals(enumEntryName, StringComparison.CurrentCultureIgnoreCase)); diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs index cc55bde5..2c127335 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs @@ -32,10 +32,10 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests protected override void ProcessMatch(ICommandParserState state) { - var blockName = GetMatcherTokens(BlockNameToken)[0]; - var blockNumber = int.Parse(GetMatcherTokens(BlockNumberToken)[0]); + var blockName = NextMatch(BlockNameToken); + var blockNumber = int.Parse(NextMatch(BlockNumberToken)); - var blockTypeInput = GetMatcherTokens(BlockTypeToken)[0]; + var blockTypeInput = NextMatch(BlockTypeToken); if (!Enum.TryParse(blockTypeInput, true, out FastFileBlock.Type blockType)) { var blockTypeValues = Enum.GetValues(typeof(FastFileBlock.Type)).OfType() diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs index 070d6642..38b2a6ab 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs @@ -31,7 +31,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests throw new TestFailedException($"Game has already been set with value '{state.Game}'"); } - state.Game = GetMatcherTokens(GameNameToken)[0]; + state.Game = NextMatch(GameNameToken); } } } diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs index dbf30d74..8fab3a67 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs @@ -22,7 +22,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests protected override void ProcessMatch(ICommandParserState state) { - var typeName = GetMatcherTokens(TypeNameToken)[0]; + var typeName = NextMatch(TypeNameToken); var dataTypeToUse = state.Repository.GetDataTypeByName(typeName); if (dataTypeToUse == null) diff --git a/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs b/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs index ec1a0f4b..c22e2ca6 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs @@ -55,6 +55,7 @@ if (name != null && success) result.AddNamedMatch(name, output); + result.AppendTag(Tag); return result; } diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs index 93123c69..61de793a 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs @@ -13,6 +13,7 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset) { var result = new TokenMatchingResult(true, 0); + result.AppendTag(Tag); foreach(var matcher in Matchers) { @@ -20,8 +21,7 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers if (matcherResult.Successful) { - matcherResult.CopyNamedMatchesTo(result); - result.ConsumedTokenCount += matcherResult.ConsumedTokenCount; + matcherResult.CopyTo(result); } else { diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs index d79052cb..ea42adc0 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs @@ -23,6 +23,8 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset) { var result = new TokenMatchingResult(false, 0); + result.AppendTag(Tag); + var matchedTimes = 0; while (true) @@ -32,8 +34,7 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers if (!matcherResult.Successful) break; - matcherResult.CopyNamedMatchesTo(result); - result.ConsumedTokenCount += matcherResult.ConsumedTokenCount; + matcherResult.CopyTo(result); matchedTimes++; } diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs index 0f71e70a..d2e9e9e3 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs @@ -20,8 +20,10 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers { var matcherResult = matcher.Test(context, tokenOffset); - if (matcherResult.Successful) - return matcherResult; + if (!matcherResult.Successful) continue; + + matcherResult.PrependTag(Tag); + return matcherResult; } return new TokenMatchingResult(false, 0); diff --git a/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs b/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs index ba7e3da1..1bf328a1 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs @@ -1,15 +1,21 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; +using ZoneCodeGenerator.Utils; namespace ZoneCodeGenerator.Parsing.Matching { - class TokenMatchingResult : IEnumerable>> + class TokenMatchingResult { public bool Successful { get; set; } public int ConsumedTokenCount { get; set; } private readonly Dictionary> namedMatches; + public IReadOnlyDictionary> NamedMatches => namedMatches; + + private readonly List matchedTags; + public IReadOnlyList MatchedTags => matchedTags; public TokenMatchingResult(bool success, int consumedTokenCount) { @@ -23,6 +29,7 @@ namespace ZoneCodeGenerator.Parsing.Matching ConsumedTokenCount = consumedTokenCount; namedMatches = new Dictionary>(); + matchedTags = new List(); } public void AddNamedMatch(string name, string value) @@ -33,27 +40,31 @@ namespace ZoneCodeGenerator.Parsing.Matching namedMatches[name].Add(value); } - public IEnumerator>> GetEnumerator() + public void PrependTag(string tag) { - return namedMatches.GetEnumerator(); + if (!string.IsNullOrEmpty(tag)) + matchedTags.Insert(0, tag); } - IEnumerator IEnumerable.GetEnumerator() + public void AppendTag(string tag) { - return namedMatches.GetEnumerator(); + if(!string.IsNullOrEmpty(tag)) + matchedTags.Add(tag); } - public List this[string key] => namedMatches.ContainsKey(key) ? namedMatches[key] : new List(); - - public void CopyNamedMatchesTo(TokenMatchingResult target) + public void CopyTo(TokenMatchingResult target) { - foreach(var namedMatchKey in namedMatches) + foreach(var (matchKey, matchValue) in namedMatches) { - foreach (var namedMatch in namedMatchKey.Value) + foreach (var namedMatch in matchValue) { - target.AddNamedMatch(namedMatchKey.Key, namedMatch); + target.AddNamedMatch(matchKey, namedMatch); } } + + target.matchedTags.AddRange(matchedTags); + + target.ConsumedTokenCount += ConsumedTokenCount; } } } diff --git a/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs b/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs index f9d9d324..3d6b22a6 100644 --- a/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs +++ b/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs @@ -1,25 +1,32 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using ZoneCodeGenerator.Parsing.Matching; +using ZoneCodeGenerator.Parsing.Matching.Matchers; +using ZoneCodeGenerator.Utils; namespace ZoneCodeGenerator.Parsing.Testing { abstract class AbstractTokenTest : ITokenTest where TState : IParserState { - public int ConsumedTokenCount { get; private set; } + private TokenMatchingResult lastResult; + private int tagOffset; + private readonly Dictionary matchOffset; - private readonly TokenMatcher[] matcherEntryPoint; - private readonly Dictionary> matchedEntries; + public int ConsumedTokenCount => lastResult?.ConsumedTokenCount ?? 0; + + private readonly TokenMatcher matcherEntryPoint; private readonly Dictionary taggedMatchers; - private bool tested; protected AbstractTokenTest(TokenMatcher[] matcherEntryPoint) { - this.matcherEntryPoint = matcherEntryPoint; - matchedEntries = new Dictionary>(); + this.matcherEntryPoint = new MatcherGroupAnd(matcherEntryPoint); taggedMatchers = new Dictionary(); - tested = false; + + lastResult = null; + tagOffset = 0; + matchOffset = new Dictionary(); BuildTaggedMatcherList(matcherEntryPoint); } @@ -40,31 +47,81 @@ namespace ZoneCodeGenerator.Parsing.Testing } } + private void Reset() + { + lastResult = null; + tagOffset = 0; + matchOffset.Clear(); + } + protected void AddTaggedMatcher(params TokenMatcher[] taggedMatcher) { BuildTaggedMatcherList(taggedMatcher); } - protected ReadOnlyCollection GetMatcherTokens(string matcherName) + protected string PeekTag() { - return tested && matchedEntries.ContainsKey(matcherName) ? matchedEntries[matcherName].AsReadOnly() : new List().AsReadOnly(); + return lastResult?.MatchedTags.ElementAtOrDefault(tagOffset); + } + + protected string NextTag() + { + return lastResult?.MatchedTags.ElementAtOrDefault(tagOffset++); } protected bool HasMatcherTokens(string matcherName) { - return tested && matchedEntries.ContainsKey(matcherName); + return GetMatcherTokenCount(matcherName) > 0; + } + + protected int GetMatcherTokenCount(string matcherName) + { + if (lastResult == null || !lastResult.NamedMatches.TryGetValue(matcherName, out var matches)) + { + return 0; + } + + return matches.Count; + } + + protected string PeekMatch(string matcherName) + { + if (!lastResult.NamedMatches.TryGetValue(matcherName, out var matches)) + { + return null; + } + + if (!matchOffset.TryGetValue(matcherName, out var offset)) + { + offset = 0; + } + + return matches.ElementAtOrDefault(offset); + } + + protected string NextMatch(string matcherName) + { + if (!lastResult.NamedMatches.TryGetValue(matcherName, out var matches)) + { + return null; + } + + if (!matchOffset.TryGetValue(matcherName, out var offset)) + { + offset = 0; + } + + var result = matches.ElementAtOrDefault(offset++); + + matchOffset[matcherName] = offset; + + return result; } protected abstract void ProcessMatch(TState state); public TokenTestResult PerformTest(TState state, ILexer lexer, bool verbose = false) { - var tokenOffset = 0; - matchedEntries.Clear(); - - ConsumedTokenCount = 0; - tested = true; - var context = new MatchingContext(lexer, taggedMatchers) { Verbose = verbose @@ -75,30 +132,19 @@ namespace ZoneCodeGenerator.Parsing.Testing Console.WriteLine($"Test {GetType().Name} start"); } - foreach(var matcher in matcherEntryPoint) + Reset(); + lastResult = matcherEntryPoint.Test(context, 0); + + if (!lastResult.Successful) { - var result = matcher.Test(context, tokenOffset); - - if (!result.Successful) + if (context.Verbose) { - if (context.Verbose) - { - Console.WriteLine($"Test {GetType().Name} failed"); - } - - return TokenTestResult.NoMatch; + Console.WriteLine($"Test {GetType().Name} failed"); } - tokenOffset += result.ConsumedTokenCount; - - foreach (var entry in result) - { - matchedEntries.Add(entry.Key, entry.Value); - } + return TokenTestResult.NoMatch; } - ConsumedTokenCount = tokenOffset; - ProcessMatch(state); if (context.Verbose) diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherArrayTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherArrayTest.cs index 4c7b0750..123dbf2b 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherArrayTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherArrayTest.cs @@ -152,7 +152,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(3, result.ConsumedTokenCount); - Assert.AreEqual("13", result["array_token"].ElementAtOrDefault(0)); + Assert.AreEqual("13", result.NamedMatches["array_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -168,7 +168,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(3, result.ConsumedTokenCount); - Assert.AreEqual("307", result["array_token"].ElementAtOrDefault(0)); + Assert.AreEqual("307", result.NamedMatches["array_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -184,7 +184,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(3, result.ConsumedTokenCount); - Assert.AreEqual("HELLO_WORLD", result["array_token"].ElementAtOrDefault(0)); + Assert.AreEqual("HELLO_WORLD", result.NamedMatches["array_token"].ElementAtOrDefault(0)); } } } diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherGroupLoopTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherGroupLoopTest.cs index 127569fc..dcb591d5 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherGroupLoopTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherGroupLoopTest.cs @@ -175,7 +175,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.AreEqual(10, result.ConsumedTokenCount); Assert.AreEqual(11, timesTested); - var namedMatches = result[LoopToken]; + var namedMatches = result.NamedMatches[LoopToken]; Assert.AreEqual(10, namedMatches.Count); diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherLiteralTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherLiteralTest.cs index 903619c8..544b57f3 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherLiteralTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherLiteralTest.cs @@ -93,7 +93,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("const", result["test_token"].ElementAtOrDefault(0)); + Assert.AreEqual("const", result.NamedMatches["test_token"].ElementAtOrDefault(0)); } } } diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNameTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNameTest.cs index 58a3141a..be9d0cf0 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNameTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNameTest.cs @@ -153,7 +153,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("variable_n4me", result["name_token"].ElementAtOrDefault(0)); + Assert.AreEqual("variable_n4me", result.NamedMatches["name_token"].ElementAtOrDefault(0)); } } } diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNumberTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNumberTest.cs index 54eb4747..c81d2a86 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNumberTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherNumberTest.cs @@ -138,7 +138,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("420", result["number_token"].ElementAtOrDefault(0)); + Assert.AreEqual("420", result.NamedMatches["number_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -154,7 +154,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("421", result["number_token"].ElementAtOrDefault(0)); + Assert.AreEqual("421", result.NamedMatches["number_token"].ElementAtOrDefault(0)); } } } diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs index fa2d4c15..70ebcf0e 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs @@ -48,7 +48,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("int", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("int", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -64,7 +64,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("GfxWorld", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("GfxWorld", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -80,7 +80,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(2, result.ConsumedTokenCount); - Assert.AreEqual("unsigned int", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("unsigned int", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -96,7 +96,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(2, result.ConsumedTokenCount); - Assert.AreEqual("signed int", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("signed int", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -112,7 +112,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(2, result.ConsumedTokenCount); - Assert.AreEqual("const int", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("const int", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -128,7 +128,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(2, result.ConsumedTokenCount); - Assert.AreEqual("long long", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("long long", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -144,7 +144,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(4, result.ConsumedTokenCount); - Assert.AreEqual("const unsigned long long", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("const unsigned long long", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -160,7 +160,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("int", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("int", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -176,7 +176,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(4, result.ConsumedTokenCount); - Assert.AreEqual("std::string", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("std::string", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -192,7 +192,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(4, result.ConsumedTokenCount); - Assert.AreEqual("std::int32_t", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("std::int32_t", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -208,7 +208,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(4, result.ConsumedTokenCount); - Assert.AreEqual("a::b", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("a::b", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -224,7 +224,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsFalse(result.Successful); Assert.AreEqual(0, result.ConsumedTokenCount); - Assert.That.IsZero(result["type_token"].Count); + Assert.IsFalse(result.NamedMatches.ContainsKey("type_token")); } [TestMethod] @@ -240,7 +240,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsTrue(result.Successful); Assert.AreEqual(1, result.ConsumedTokenCount); - Assert.AreEqual("std", result["type_token"].ElementAtOrDefault(0)); + Assert.AreEqual("std", result.NamedMatches["type_token"].ElementAtOrDefault(0)); } [TestMethod] @@ -256,7 +256,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsFalse(result.Successful); Assert.AreEqual(0, result.ConsumedTokenCount); - Assert.That.IsZero(result["type_token"].Count); + Assert.IsFalse(result.NamedMatches.ContainsKey("type_token")); } [TestMethod] @@ -272,7 +272,7 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers Assert.IsFalse(result.Successful); Assert.AreEqual(0, result.ConsumedTokenCount); - Assert.That.IsZero(result["type_token"].Count); + Assert.IsFalse(result.NamedMatches.ContainsKey("type_token")); } } }