ZoneCodeGenerator: When parsing Evaluation nest operations so the operator precendence is evaluated as specified

This commit is contained in:
Jan 2019-11-08 03:00:20 +01:00
parent 0a8d5246b2
commit 6c1404116c

View File

@ -16,6 +16,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
// Evaluation Sub-Tags // Evaluation Sub-Tags
private const string TagEvaluationParenthesis = "evaluationParenthesis"; private const string TagEvaluationParenthesis = "evaluationParenthesis";
private const string TagEvaluationParenthesisEnd = "evaluationParenthesisEnd";
private const string TagEvaluationNot = "evaluationNot"; private const string TagEvaluationNot = "evaluationNot";
private const string TagEvaluationOperation = "evaluationOperation"; private const string TagEvaluationOperation = "evaluationOperation";
@ -53,7 +54,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
new MatcherGroupOptional(new MatcherLiteral("!").WithTag(TagEvaluationNot)), new MatcherGroupOptional(new MatcherLiteral("!").WithTag(TagEvaluationNot)),
new MatcherLiteral("("), new MatcherLiteral("("),
new MatcherWithTag(TagEvaluation), new MatcherWithTag(TagEvaluation),
new MatcherLiteral(")") new MatcherLiteral(")").WithTag(TagEvaluationParenthesisEnd)
).WithTag(TagEvaluationParenthesis), ).WithTag(TagEvaluationParenthesis),
new MatcherWithTag(TagOperand) new MatcherWithTag(TagOperand)
), ),
@ -108,16 +109,29 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
private IEvaluation ProcessEvaluationInParenthesis(ICommandParserState state) private IEvaluation ProcessEvaluationInParenthesis(ICommandParserState state)
{ {
var isNegated = false;
if (NextTag().Equals(TagEvaluationNot)) if (NextTag().Equals(TagEvaluationNot))
{ {
NextTag(); NextTag();
return new Operation(ProcessEvaluation(state), new OperandStatic(0), OperationType.OperationEquals); isNegated = true;
} }
return ProcessEvaluation(state); var processedEvaluation = ProcessEvaluation(state);
if (NextTag() != TagEvaluationParenthesisEnd)
throw new Exception("Expected parenthesis end tag @ EvaluationInParenthesis");
return !isNegated
? processedEvaluation
: new Operation(processedEvaluation, new OperandStatic(0), OperationType.OperationEquals);
} }
protected IEvaluation ProcessEvaluation(ICommandParserState state) protected IEvaluation ProcessEvaluation(ICommandParserState state)
{
var operands = new List<IEvaluation>();
var operators = new List<OperationType>();
while (true)
{ {
IEvaluation firstStatementPart; IEvaluation firstStatementPart;
switch (NextTag()) switch (NextTag())
@ -133,6 +147,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
default: default:
throw new Exception("Invalid followup tag @ Evaluation"); throw new Exception("Invalid followup tag @ Evaluation");
} }
operands.Add(firstStatementPart);
if (PeekTag() == TagEvaluationOperation) if (PeekTag() == TagEvaluationOperation)
{ {
@ -141,17 +156,31 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
if (NextTag() != TagOperationType) if (NextTag() != TagOperationType)
throw new Exception("Expected operationType tag @ Evaluation"); throw new Exception("Expected operationType tag @ Evaluation");
var type = ProcessOperationType(state); operators.Add(ProcessOperationType(state));
if (NextTag() != TagEvaluation) if (NextTag() != TagEvaluation)
throw new Exception("Expected EvaluationTag @ Evaluation"); throw new Exception("Expected EvaluationTag @ Evaluation");
}
var secondStatementPart = ProcessEvaluation(state); else
{
return new Operation(firstStatementPart, secondStatementPart, type); break;
}
} }
return firstStatementPart; while (operators.Any())
{
var nextOperator = operators
.OrderBy(type => type.Precedence)
.First();
var operatorIndex = operators.IndexOf(nextOperator);
var operation = new Operation(operands[operatorIndex], operands[operatorIndex + 1], nextOperator);
operands.RemoveRange(operatorIndex, 2);
operands.Insert(operatorIndex, operation);
operators.RemoveAt(operatorIndex);
}
return operands[0];
} }
} }
} }