private static AstNode parseAdditive(Parser parser) { AstNode left = parseMultiplicitive(parser); while (parser.MatchToken(TokenType.Operation) || parser.MatchToken(TokenType.Identifier, "and") || parser.MatchToken(TokenType.Identifier, "or")) { switch ((string)parser.CurrentToken().Value) { case "+": parser.AcceptToken(TokenType.Operation); left = new BinaryOpNode(BinaryOperation.Addition, left, parseMultiplicitive(parser)); continue; case "-": parser.AcceptToken(TokenType.Operation); left = new BinaryOpNode(BinaryOperation.Subtraction, left, parseMultiplicitive(parser)); continue; case "and": parser.AcceptToken(TokenType.Identifier); left = new BinaryOpNode(BinaryOperation.And, left, parseMultiplicitive(parser)); continue; case "or": parser.AcceptToken(TokenType.Identifier); left = new BinaryOpNode(BinaryOperation.Or, left, parseMultiplicitive(parser)); continue; default: break; } break; } return left; }
private static AstNode parseComparison(Parser parser) { AstNode left = parseFunctionCall(parser); while (parser.MatchToken(TokenType.Comparison)) { switch ((string)parser.CurrentToken().Value) { case "=": parser.AcceptToken(TokenType.Comparison); left = new BinaryOpNode(BinaryOperation.Equal, left, parseFunctionCall(parser)); continue; case "!=": parser.AcceptToken(TokenType.Comparison); left = new BinaryOpNode(BinaryOperation.NotEqual, left, parseFunctionCall(parser)); continue; case ">": parser.AcceptToken(TokenType.Comparison); left = new BinaryOpNode(BinaryOperation.GreaterThan, left, parseFunctionCall(parser)); continue; case "<": parser.AcceptToken(TokenType.Comparison); left = new BinaryOpNode(BinaryOperation.LessThan, left, parseFunctionCall(parser)); continue; case ">=": parser.AcceptToken(TokenType.Comparison); left = new BinaryOpNode(BinaryOperation.GreaterThanOrEqual, left, parseFunctionCall(parser)); continue; case "<=": parser.AcceptToken(TokenType.Comparison); left = new BinaryOpNode(BinaryOperation.LessThanOrEqual, left, parseFunctionCall(parser)); continue; default: break; } break; } return left; }
private object interpretBinaryOperation(BinaryOpNode binaryNode) { switch (binaryNode.BinaryOperation) { case BinaryOperation.Addition: return getLeft(binaryNode) + getRight(binaryNode); case BinaryOperation.Subtraction: return getLeft(binaryNode) - getRight(binaryNode); case BinaryOperation.Multiplication: return getLeft(binaryNode) * getRight(binaryNode); case BinaryOperation.Division: return getLeft(binaryNode) / getRight(binaryNode); case BinaryOperation.Modulus: return getLeft(binaryNode) % getRight(binaryNode); case BinaryOperation.Equal: return evaluateNode(binaryNode.Left).GetHashCode() == evaluateNode(binaryNode.Right).GetHashCode(); case BinaryOperation.NotEqual: return evaluateNode(binaryNode.Left).GetHashCode() != evaluateNode(binaryNode.Right).GetHashCode(); case BinaryOperation.GreaterThan: return getLeft(binaryNode) > getRight(binaryNode); case BinaryOperation.LessThan: return getLeft(binaryNode) < getRight(binaryNode); case BinaryOperation.GreaterThanOrEqual: return getLeft(binaryNode) >= getRight(binaryNode); case BinaryOperation.LessThanOrEqual: return getLeft(binaryNode) <= getRight(binaryNode); case BinaryOperation.Assignment: object value = evaluateNode(binaryNode.Left); string variable = ((IdentifierNode)binaryNode.Right).Identifier; if (variables.ContainsKey(variable)) variables.Remove(variable); variables.Add(variable, value); return value; case BinaryOperation.And: return (bool)evaluateNode(binaryNode.Left) && (bool)evaluateNode(binaryNode.Right); case BinaryOperation.Or: return (bool)evaluateNode(binaryNode.Left) || (bool)evaluateNode(binaryNode.Right); default: throw new Exception("Unexpected binary operation in interpreter: " + binaryNode.BinaryOperation); } }
private static AstNode parseMultiplicitive(Parser parser) { AstNode left = parseComparison(parser); while (parser.MatchToken(TokenType.Operation)) { switch ((string)parser.CurrentToken().Value) { case "*": parser.AcceptToken(TokenType.Operation); left = new BinaryOpNode(BinaryOperation.Multiplication, left, parseComparison(parser)); continue; case "/": parser.AcceptToken(TokenType.Operation); left = new BinaryOpNode(BinaryOperation.Division, left, parseComparison(parser)); continue; case "%": parser.AcceptToken(TokenType.Operation); left = new BinaryOpNode(BinaryOperation.Modulus, left, parseComparison(parser)); continue; default: break; } break; } return left; }
private double getRight(BinaryOpNode binaryNode) { return Convert.ToDouble(evaluateNode(binaryNode.Right)); }