/// <summary> /// Constructor for tokens that are not parsed. /// </summary> /// <param name="text"></param> /// <param name="type"></param> /// <param name="priority"></param> public Token(string text, TokenType type, TokenPriority priority) { _Text = text; _Type = type; _Priority = priority; _ParsedObject = text; }
/// <summary> /// Constructor for tokens that are parsed. /// </summary> /// <param name="parsedObj"></param> /// <param name="type"></param> /// <param name="priority"></param> public Token(object parsedObj, TokenType type, TokenPriority priority) { _ParsedObject = parsedObj; _Text = ParsedObject.ToString(); _Type = type; _Priority = priority; }
/// <summary> /// Recursive method that reads an expression. /// </summary> /// <param name="t"></param> /// <param name="priority"></param> /// <returns></returns> private CodeExpression ReadExpression(Tokenizer t, TokenPriority priority) { CodeExpression left = null, right = null; bool cont = true, applyNot = false, applyNegative = false; while (cont) { switch (t.Current.Type) { case TokenType.Primitive: left = new CodePrimitiveExpression(t.Current.ParsedObject); t.GetNextToken(); cont = false; break; case TokenType.Operator: { // An operator here is considered a unary operator. switch (t.Current.Text) { case "-": applyNegative = true; break; case "!": applyNot = true; break; default: throw new Exception("Unexpected operator: " + t.Current.Text); } t.GetNextToken(); continue; } case TokenType.Identifier: left = ReadIdentifier(t); cont = false; break; case TokenType.OpenParens: t.GetNextToken(); left = ReadExpression(t, TokenPriority.None); t.GetNextToken(); if (left is CodeTypeReferenceExpression) { left = new CodeCastExpression((left as CodeTypeReferenceExpression).Type, ReadExpression(t, TokenPriority.None)); } cont = false; break; } if (t.IsInvalid) { cont = false; } } if (left == null) { throw new Exception("No expression found."); } if (applyNot) { left = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(false)); } else if (applyNegative) { left = new CodeBinaryOperatorExpression(new CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, left); } if (t.IsInvalid || t.Current.Type == TokenType.CloseParens || t.Current.Type == TokenType.Comma || t.Current.Type == TokenType.CloseBracket) { return(left); } cont = true; while (cont && !t.IsInvalid) { Token token = t.Current; switch (token.Type) { case TokenType.Operator: { if (t.Current.Priority < priority) { cont = false; } else { // In the case we have an operator, we'll assume it's a binary operator. CodeBinaryOperatorType binOp; bool notEquals = false; switch (token.Text) { case ">": binOp = CodeBinaryOperatorType.GreaterThan; break; case ">=": binOp = CodeBinaryOperatorType.GreaterThanOrEqual; break; case "<": binOp = CodeBinaryOperatorType.LessThan; break; case "<=": binOp = CodeBinaryOperatorType.LessThanOrEqual; break; case "=": case "==": binOp = CodeBinaryOperatorType.ValueEquality; break; case "!=": binOp = CodeBinaryOperatorType.ValueEquality; notEquals = true; break; case "|": binOp = CodeBinaryOperatorType.BitwiseOr; break; case "||": binOp = CodeBinaryOperatorType.BooleanOr; break; case "&": binOp = CodeBinaryOperatorType.BitwiseAnd; break; case "&&": binOp = CodeBinaryOperatorType.BooleanAnd; break; case "-": binOp = CodeBinaryOperatorType.Subtract; break; case "+": binOp = CodeBinaryOperatorType.Add; break; case "/": binOp = CodeBinaryOperatorType.Divide; break; case "%": binOp = CodeBinaryOperatorType.Modulus; break; case "*": binOp = CodeBinaryOperatorType.Multiply; break; default: throw new Exception("Unrecognized operator: " + t.Current.Text); } if (t.IsInvalid) { throw new Exception("Expected token for right side of binary expression."); } t.GetNextToken(); right = ReadExpression(t, token.Priority); left = new CodeBinaryOperatorExpression(left, binOp, right); // If the operator was the not equals operator, we just negate the previous binary expression. if (notEquals) { left = new CodeBinaryOperatorExpression(left, binOp, new CodePrimitiveExpression(false)); } } break; } case TokenType.CloseParens: //t.GetNextToken(); cont = false; break; case TokenType.Dot: // A dot could appear after some parentheses. In this case we need to parse // what's after the dot as an identifier. t.GetNextToken(); right = ReadIdentifier(t); CodeExpression ceTemp = right; while (true) { if (ceTemp is CodeVariableReferenceExpression) { left = new CodePropertyReferenceExpression(left, (ceTemp as CodeVariableReferenceExpression).VariableName); break; } else if (ceTemp is CodePropertyReferenceExpression) { CodePropertyReferenceExpression cpre = ceTemp as CodePropertyReferenceExpression; if (cpre.TargetObject is CodeThisReferenceExpression) { cpre.TargetObject = left; left = cpre; break; } else { ceTemp = cpre.TargetObject; } } else if (ceTemp is CodeFieldReferenceExpression) { CodeFieldReferenceExpression cfre = ceTemp as CodeFieldReferenceExpression; if (cfre.TargetObject is CodeThisReferenceExpression) { cfre.TargetObject = left; left = cfre; break; } } else if (ceTemp is CodeMethodInvokeExpression) { CodeMethodInvokeExpression cmie = ceTemp as CodeMethodInvokeExpression; if (cmie.Method.TargetObject is CodeThisReferenceExpression) { cmie.Method.TargetObject = left; left = cmie; break; } else { ceTemp = cmie.Method.TargetObject; } } else { throw new Exception("Unexpected identifier found after ."); } } cont = false; break; default: throw new Exception("Token not expected: " + token.Text); } } return(left); }
private ExpressionToken ParseExpression(ExpressionToken lhs, TokenPriority priority) { while (true) { if (lhs.Type == TokenType.MinusOperator) { lhs = ParseExpression(UpcomingToken, TokenPriority.UnaryMinus); if (lhs is ValueToken) { lhs = -lhs; } else { throw new ArgumentException($"Unary minus is valid only for ValueToken!{lhs} is not a ValueToken"); } NextToken(); break; } else if (lhs.Type == TokenType.NotOperator) { lhs = ParseExpression(UpcomingToken, TokenPriority.Not); if (lhs is ValueToken) { lhs = !lhs; } else { throw new ArgumentException($"Unary minus is valid only for ValueToken!{lhs} is not a ValueToken"); } NextToken(); break; } break; } while (UpcomingToken is OperatorToken && (UpcomingToken as OperatorToken).Priority >= priority) { OperatorToken op = UpcomingToken as OperatorToken; NextToken(); ExpressionToken rhs = UpcomingToken; NextToken(); while (UpcomingToken is OperatorToken && (UpcomingToken as OperatorToken).Priority > op.Priority) { rhs = ParseExpression(rhs, (UpcomingToken as OperatorToken).Priority); NextToken(); } switch (op.Type) { case TokenType.PlusOperator: lhs = lhs + rhs; break; case TokenType.MinusOperator: lhs = lhs - rhs; break; case TokenType.DivideOperator: lhs = lhs / rhs; break; case TokenType.MultiplyOperator: lhs = lhs * rhs; break; case TokenType.EqualOperator: lhs = ExpressionToken.AreTokensEqual(lhs, rhs); break; case TokenType.LessOperator: lhs = lhs < rhs; break; case TokenType.GreaterOperator: lhs = lhs > rhs; break; case TokenType.LessOrEqualOperator: lhs = lhs <= rhs; break; case TokenType.GreaterOrEqualOperator: lhs = lhs >= rhs; break; case TokenType.AndOperator: lhs = lhs & rhs; break; case TokenType.OrOperator: lhs = lhs | rhs; break; } } return(lhs); }