From 5245f40307b4e49195461c01d4da47e6a62a2bb4 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 27 Oct 2019 01:46:43 +0200 Subject: [PATCH] ZoneCodeGenerator: Create parent class for all tests that use Evaluations --- .../CommandFile/Tests/TestCondition.cs | 120 ++++--------- .../Parsing/CommandFile/Tests/TestCount.cs | 121 +------------- .../CommandFile/Tests/TestWithEvaluation.cs | 157 ++++++++++++++++++ 3 files changed, 192 insertions(+), 206 deletions(-) create mode 100644 src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestWithEvaluation.cs diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs index 8745421e..56a87aaf 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs @@ -1,119 +1,57 @@ using System; -using System.Collections.Generic; -using System.Text; +using ZoneCodeGenerator.Domain.Evaluation; using ZoneCodeGenerator.Parsing.Matching; using ZoneCodeGenerator.Parsing.Matching.Matchers; -using ZoneCodeGenerator.Parsing.Testing; namespace ZoneCodeGenerator.Parsing.CommandFile.Tests { - class TestCondition : AbstractTokenTest + class TestCondition : TestWithEvaluation { + private const string TagAlways = "always"; + private const string TagNever = "never"; private const string TypeNameToken = "typeName"; - private const string ConditionStatementTag = "conditionStatement"; - private const string ConditionTag = "condition"; - private const string ConditionRelationTag = "conditionRelation"; - private const string OperationTag = "operation"; - private const string OperandTag = "operand"; - private const string ConditionChainLinkTag = "conditionChainLink"; - private const string ConditionChainTag = "conditionChain"; - // operand ::= + | | true | false - private static readonly TokenMatcher operand = new MatcherGroupOr( - new MatcherGroupAnd( - new MatcherTypename(), - new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray()) - ), - new MatcherNumber(), - new MatcherLiteral("true"), - new MatcherLiteral("false") - ).WithTag(OperandTag); - - // 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(">")) - ).WithTag(OperationTag); - - // conditionStatement ::= ( ) | [ ] - private static readonly TokenMatcher conditionStatement = new MatcherGroupOr( - new MatcherGroupAnd( - new MatcherLiteral("("), - new MatcherWithTag(ConditionStatementTag), - new MatcherLiteral(")") - ), - new MatcherGroupAnd( - new MatcherWithTag(OperandTag), - new MatcherGroupOptional(new MatcherGroupAnd( - new MatcherWithTag(OperationTag), - new MatcherWithTag(ConditionStatementTag) - )) - ) - ).WithTag(ConditionStatementTag); - - // conditionChainLink ::= == | != | <= | >= | < | > - private static readonly TokenMatcher conditionRelation = new MatcherGroupOr( - new MatcherGroupAnd(new MatcherLiteral("="), new MatcherLiteral("=")), - new MatcherGroupAnd(new MatcherLiteral("!"), new MatcherLiteral("=")), - new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("=")), - new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral("=")), - new MatcherLiteral("<"), - new MatcherLiteral(">") - ).WithTag(ConditionRelationTag); - - // condition ::= - private static readonly TokenMatcher condition = new MatcherGroupAnd( - new MatcherWithTag(ConditionStatementTag), - new MatcherWithTag(ConditionRelationTag), - new MatcherWithTag(ConditionStatementTag) - ).WithTag(ConditionTag); - - // conditionChainLink ::= && | || - private static readonly TokenMatcher conditionChainLink = new MatcherGroupOr( - new MatcherGroupAnd(new MatcherLiteral("&"), new MatcherLiteral("&")), - new MatcherGroupAnd(new MatcherLiteral("|"), new MatcherLiteral("|")) - ).WithTag(ConditionChainLinkTag); - - // conditionChain ::= ( )* - private static readonly TokenMatcher conditionChain = new MatcherGroupAnd( - new MatcherWithTag(ConditionTag), - new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherGroupAnd( - new MatcherWithTag(ConditionChainLinkTag), - new MatcherWithTag(ConditionTag) - )) - ).WithTag(ConditionChainTag); - - // set condition (always | never | ); + // set condition (always | never | ); private static readonly TokenMatcher[] matchers = { new MatcherLiteral("set"), new MatcherLiteral("condition"), new MatcherTypename().WithName(TypeNameToken), new MatcherGroupOr( - new MatcherLiteral("always"), - new MatcherLiteral("never"), - new MatcherWithTag(ConditionChainTag) + new MatcherLiteral("always").WithTag(TagAlways), + new MatcherLiteral("never").WithTag(TagNever), + new MatcherWithTag(TagEvaluation) ), new MatcherLiteral(";") }; public TestCondition() : base(matchers) { - AddTaggedMatcher(operand); - AddTaggedMatcher(operation); - AddTaggedMatcher(conditionStatement); - AddTaggedMatcher(conditionRelation); - AddTaggedMatcher(condition); - AddTaggedMatcher(conditionChainLink); - AddTaggedMatcher(conditionChain); + } protected override void ProcessMatch(ICommandParserState state) { + IEvaluation evaluation; + switch (NextTag()) + { + case TagAlways: + evaluation = new OperandStatic(1); + break; + + case TagNever: + evaluation = new OperandStatic(0); + break; + + case TagEvaluation: + evaluation = ProcessEvaluation(state); + break; + + default: + throw new Exception("Unexpected Tag in TestCondition"); + } + + } } } \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs index 4b308557..dd9484b6 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs @@ -1,60 +1,12 @@ using System; -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; namespace ZoneCodeGenerator.Parsing.CommandFile.Tests { - class TestCount : AbstractTokenTest + class TestCount : TestWithEvaluation { - 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( - new MatcherTypename(), - new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray()) - ), - new MatcherNumber() - ).WithTag(OperandTag); - - // operation ::= + | - | * | / | << | >> - private static readonly TokenMatcher operation = new MatcherGroupOr( - 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 MatcherGroupAnd( - new MatcherGroupOr( - new MatcherGroupAnd( - new MatcherLiteral("("), - new MatcherWithTag(CalculationStatementTag), - new MatcherLiteral(")") - ), - new MatcherWithTag(OperandTag) - ), - new MatcherGroupOptional(new MatcherGroupAnd( - new MatcherWithTag(OperationTag), - new MatcherWithTag(CalculationStatementTag) - )).WithTag(OperationOfCalculationStatementTag) - - ).WithTag(CalculationStatementTag); // set count ; private static readonly TokenMatcher[] matchers = @@ -62,84 +14,23 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests new MatcherLiteral("set"), new MatcherLiteral("count"), new MatcherTypename().WithName(TypeNameToken), - new MatcherWithTag(CalculationStatementTag), + new MatcherWithTag(TagEvaluation), new MatcherLiteral(";") }; public TestCount() : base(matchers) { - AddTaggedMatcher(operand); - AddTaggedMatcher(operation); - AddTaggedMatcher(calculationStatement); + } protected override void ProcessMatch(ICommandParserState state) { - switch (NextTag()) + if (!NextTag().Equals(TagEvaluation)) { - 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"); + throw new Exception("Expected first count tag to be a calculation statement"); } - 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; + var evaluation = ProcessEvaluation(state); } } } \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestWithEvaluation.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestWithEvaluation.cs new file mode 100644 index 00000000..df6bb1a0 --- /dev/null +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestWithEvaluation.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ZoneCodeGenerator.Domain.Evaluation; +using ZoneCodeGenerator.Parsing.Matching; +using ZoneCodeGenerator.Parsing.Matching.Matchers; +using ZoneCodeGenerator.Parsing.Testing; + +namespace ZoneCodeGenerator.Parsing.CommandFile.Tests +{ + abstract class TestWithEvaluation : AbstractTokenTest + { + private const string TagOperand = "operand"; + private const string TagOperationType = "operationType"; + private const string TokenOperationType = "operationTypeToken"; + + // Evaluation Sub-Tags + private const string TagEvaluationParenthesis = "evaluationParenthesis"; + private const string TagEvaluationNot = "evaluationNot"; + private const string TagEvaluationOperation = "evaluationOperation"; + + // Operand Sub-Tags + private const string TagOperandNumber = "operandNumber"; + private const string TagOperandTypename = "operandTypename"; + private const string TagOperandArray = "operandArray"; + private const string TokenOperandNumber = "operandNumberToken"; + private const string TokenOperandTypename = "operandTypenameToken"; + private const string TokenOperandArray = "operandArrayToken"; + + // Visible to children + protected const string TagEvaluation = "evaluation"; + + // operand ::= * | + private static readonly TokenMatcher operand = new MatcherGroupOr( + new MatcherGroupAnd( + new MatcherTypename().WithName(TokenOperandTypename), + new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(TokenOperandArray).WithTag(TagOperandArray)) + ).WithTag(TagOperandTypename), + new MatcherNumber().WithName(TokenOperandNumber).WithTag(TagOperandNumber) + ).WithTag(TagOperand); + + // operationType ::= + | - | * | / | << | >> | ... + private static readonly TokenMatcher operationType = new MatcherGroupOr( + OperationType.Types + .Select(type => new MatcherLiteral(type.Syntax.ToCharArray().Select(c => c.ToString()).ToArray()).WithName(TokenOperationType)) + .Cast().ToArray() + ).WithTag(TagOperationType); + + // evaluation ::= ( ) | [ ] + private static readonly TokenMatcher evaluation = new MatcherGroupAnd( + new MatcherGroupOr( + new MatcherGroupAnd( + new MatcherGroupOptional(new MatcherLiteral("!")).WithTag(TagEvaluationNot), + new MatcherLiteral("("), + new MatcherWithTag(TagEvaluation), + new MatcherLiteral(")") + ).WithTag(TagEvaluationParenthesis), + new MatcherWithTag(TagOperand) + ), + new MatcherGroupOptional(new MatcherGroupAnd( + new MatcherWithTag(TagOperationType), + new MatcherWithTag(TagEvaluation) + )).WithTag(TagEvaluationOperation) + + ).WithTag(TagEvaluation); + + protected TestWithEvaluation(TokenMatcher[] matchers) : base(matchers) + { + AddTaggedMatcher(operand); + AddTaggedMatcher(operationType); + AddTaggedMatcher(evaluation); + } + + private IEvaluation ProcessOperand(ICommandParserState state) + { + var operandTypeTag = NextTag(); + + if (operandTypeTag.Equals(TagOperandNumber)) + { + var numberString = NextMatch(TokenOperandNumber); + return new OperandStatic(int.Parse(numberString)); + } + else if(operandTypeTag.Equals(TagOperandTypename)) + { + var typenameString = NextMatch(TokenOperandTypename); + var arrayIndexStrings = new List(); + + while (PeekTag().Equals(TagOperandArray)) + { + NextTag(); + arrayIndexStrings.Add(NextMatch(TokenOperandArray)); + } + + return new OperandDynamic(); + } + else + { + throw new Exception("Unknown Operand Type"); + } + } + + private OperationType ProcessOperationType(ICommandParserState state) + { + var operationMatch = NextMatch(TokenOperationType); + + return OperationType.Types.First(type => type.Syntax.Equals(operationMatch)); + } + + private IEvaluation ProcessEvaluationInParenthesis(ICommandParserState state) + { + if (NextTag().Equals(TagEvaluationNot)) + { + NextTag(); + return new Operation(ProcessEvaluation(state), new OperandStatic(0), OperationType.OperationEquals); + } + + return ProcessEvaluation(state); + } + + protected IEvaluation ProcessEvaluation(ICommandParserState state) + { + IEvaluation firstStatementPart; + switch (NextTag()) + { + case TagEvaluationParenthesis: + firstStatementPart = ProcessEvaluationInParenthesis(state); + break; + + case TagOperand: + firstStatementPart = ProcessOperand(state); + break; + + default: + throw new Exception("Invalid followup tag @ Evaluation"); + } + + if (PeekTag() == TagEvaluationOperation) + { + NextTag(); + + if (NextTag() != TagOperationType) + throw new Exception("Expected operationType tag @ Evaluation"); + + var type = ProcessOperationType(state); + + if (NextTag() != TagEvaluation) + throw new Exception("Expected EvaluationTag @ Evaluation"); + + var secondStatementPart = ProcessEvaluation(state); + + return new Operation(firstStatementPart, secondStatementPart, type); + } + + return firstStatementPart; + } + } +} \ No newline at end of file