diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs index 9d719f4c..4b9ec688 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs @@ -11,6 +11,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl class CommandParserState : ICommandParserState { private static readonly ITokenTest[] tests = { + new TestAlign(), new TestAsset(), new TestBlock(), new TestCondition(), @@ -18,6 +19,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl new TestGame(), new TestReorder(), new TestScriptString(), + new TestString(), new TestUse() }; diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAlign.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAlign.cs new file mode 100644 index 00000000..6851dd34 --- /dev/null +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAlign.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ZoneCodeGenerator.Parsing.Matching; +using ZoneCodeGenerator.Parsing.Matching.Matchers; +using ZoneCodeGenerator.Parsing.Testing; + +namespace ZoneCodeGenerator.Parsing.CommandFile.Tests +{ + class TestAlign : AbstractTokenTest + { + private const string MemberTypeNameToken = "name"; + private const string AlignValueToken = "align"; + + private static readonly TokenMatcher[] matchers = { + new MatcherLiteral("set"), + new MatcherLiteral("align"), + new MatcherTypename().WithName(MemberTypeNameToken), + new MatcherNumber().WithName(AlignValueToken), + new MatcherLiteral(";") + }; + + public TestAlign() : base(matchers) + { + + } + + protected override void ProcessMatch(ICommandParserState state) + { + + } + } +} diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs index 8eda2eff..4b308557 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using ZoneCodeGenerator.Domain.Evaluation; using ZoneCodeGenerator.Parsing.Matching; using ZoneCodeGenerator.Parsing.Matching.Matchers; using ZoneCodeGenerator.Parsing.Testing; @@ -10,11 +11,15 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests { class TestCount : AbstractTokenTest { - private const string TypeNameToken = "typeName"; private const string CalculationStatementTag = "calculationStatement"; private const string OperationTag = "operation"; private const string OperandTag = "operand"; + private const string OperationOfCalculationStatementTag = "operationOfCalculationStatement"; + + private const string TypeNameToken = "typeName"; + private const string OperationToken = "operationToken"; + // operand ::= * | private static readonly TokenMatcher operand = new MatcherGroupOr( new MatcherGroupAnd( @@ -26,28 +31,29 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests // operation ::= + | - | * | / | << | >> private static readonly TokenMatcher operation = new MatcherGroupOr( - new MatcherLiteral("+"), - new MatcherLiteral("-"), - new MatcherLiteral("*"), - new MatcherLiteral("/"), - new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("<")), - new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral(">")) + new MatcherLiteral("+").WithName(OperationToken), + new MatcherLiteral("-").WithName(OperationToken), + new MatcherLiteral("*").WithName(OperationToken), + new MatcherLiteral("/").WithName(OperationToken), + new MatcherLiteral("<", "<").WithName(OperationToken), + new MatcherLiteral(">", ">").WithName(OperationToken) ).WithTag(OperationTag); // calculationStatement ::= ( ) | [ ] - private static readonly TokenMatcher calculationStatement = new MatcherGroupOr( - new MatcherGroupAnd( - new MatcherLiteral("("), - new MatcherWithTag(CalculationStatementTag), - new MatcherLiteral(")") + private static readonly TokenMatcher calculationStatement = new MatcherGroupAnd( + new MatcherGroupOr( + new MatcherGroupAnd( + new MatcherLiteral("("), + new MatcherWithTag(CalculationStatementTag), + new MatcherLiteral(")") + ), + new MatcherWithTag(OperandTag) ), - new MatcherGroupAnd( - new MatcherWithTag(OperandTag), - new MatcherGroupOptional(new MatcherGroupAnd( - new MatcherWithTag(OperationTag), - new MatcherWithTag(CalculationStatementTag) - )) - ) + new MatcherGroupOptional(new MatcherGroupAnd( + new MatcherWithTag(OperationTag), + new MatcherWithTag(CalculationStatementTag) + )).WithTag(OperationOfCalculationStatementTag) + ).WithTag(CalculationStatementTag); // set count ; @@ -69,6 +75,71 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests protected override void ProcessMatch(ICommandParserState state) { + switch (NextTag()) + { + case CalculationStatementTag: + ProcessCalculationStatement(state); + break; + + default: + throw new Exception("Expected first count tag to be a calculation statement"); + } + } + + private IEvaluation ProcessCalculationStatement(ICommandParserState state) + { + IEvaluation firstStatementPart; + switch (NextTag()) + { + case CalculationStatementTag: + firstStatementPart = ProcessCalculationStatement(state); + break; + + case OperandTag: + firstStatementPart = ProcessOperand(state); + break; + + default: + throw new Exception("Invalid followup tag @ CalculationStatement"); + } + + if (PeekTag() == OperationOfCalculationStatementTag) + { + NextTag(); + + if(NextTag() != OperationTag) + throw new Exception("Expected operation tag @ CalculationStatement"); + + OperationType operationType = ProcessOperation(state); + + if (NextTag() != CalculationStatementTag) + throw new Exception("Expected calculationStatement tag @ CalculationStatement"); + + var secondStatementPart = ProcessCalculationStatement(state); + + return new Operation(firstStatementPart, secondStatementPart, operationType); + } + + return firstStatementPart; + } + + private IEvaluation ProcessOperand(ICommandParserState state) + { + return null; + } + + private OperationType ProcessOperation(ICommandParserState state) + { + var operationToken = NextMatch(OperationToken); + + var result = OperationType.Types.FirstOrDefault(type => type.Syntax.Equals(operationToken)); + + if (result == null) + { + throw new LoadingException($"Unknown operation '{operationToken}'"); + } + + return result; } } } \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs new file mode 100644 index 00000000..998a2e97 --- /dev/null +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ZoneCodeGenerator.Parsing.Matching; +using ZoneCodeGenerator.Parsing.Matching.Matchers; +using ZoneCodeGenerator.Parsing.Testing; + +namespace ZoneCodeGenerator.Parsing.CommandFile.Tests +{ + class TestString : AbstractTokenTest + { + private const string MemberTypeNameToken = "name"; + + private static readonly TokenMatcher[] matchers = { + new MatcherLiteral("set"), + new MatcherLiteral("string"), + new MatcherTypename().WithName(MemberTypeNameToken), + new MatcherLiteral(";") + }; + + public TestString() : base(matchers) + { + + } + + protected override void ProcessMatch(ICommandParserState state) + { + + } + } +} diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs index 8742cf97..354c7644 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs @@ -1,28 +1,37 @@ -namespace ZoneCodeGenerator.Parsing.Matching.Matchers +using System.Text; + +namespace ZoneCodeGenerator.Parsing.Matching.Matchers { class MatcherLiteral : BaseMatcher { - private readonly string literal; + private readonly string[] literals; - public MatcherLiteral(string literal) + public MatcherLiteral(params string[] literals) { - this.literal = literal; + this.literals = literals; } protected override MatchingResult Matches(MatchingContext context, int tokenOffset) { - var token = context.Lexer.PeekToken(tokenOffset); - var isMatch = string.Equals(token, literal); + var matcherOutputBuilder = new StringBuilder(); - if (!isMatch) return new MatchingResult(false, 0); + foreach (var literal in literals) + { + var token = context.Lexer.PeekToken(tokenOffset); + var isMatch = string.Equals(token, literal); - SetMatcherOutput(literal); - return new MatchingResult(true, 1); + if (!isMatch) return new MatchingResult(false, 0); + + matcherOutputBuilder.Append(literal); + } + + SetMatcherOutput(matcherOutputBuilder.ToString()); + return new MatchingResult(true, literals.Length); } protected override string GetIdentifier() { - return $"Literal(\"{literal}\")"; + return $"Literal(\"{string.Join("", literals)}\")"; } } }