private Expression BuildDeclarationExpression(Stack <Token> stack, ParameterExpression p) { var token = stack.Pop(); if (token.Type != TokenType.Identifier) { throw new XPressionException(token.Source, "Expected an identifier", token.Position); } var vars = NestedVars.GetVars(stack, Grammar.IgnoreCase); if (vars.ContainsKey(token.Lexeme)) { throw new XPressionException(token.Source, "Duplicate variable declaration: " + token.Lexeme, token.Position); } if (p.Type.GetPropertyOrFieldMember(token.Lexeme, Grammar.IgnoreCase) != null) { throw new XPressionException(token.Source, "Invalid variable declaration: " + token.Lexeme, token.Position); } vars.Add(token.Lexeme, null); return(Expression.Call(MemberTokens.Variables.Declare, p.Convert <object>(), Expression.Constant(token.Lexeme))); }
public Expression PopExpression(Stack <Token> stack, ParameterExpression p) { Expression left, right; if (stack.Count == 0) { // it probably is an operator error (too less operators) throw new XPressionException("operator error"); } var token = stack.Pop(); switch (token.Type) { case TokenType.Expression: return(((ExpressionToken)token).Expression); case TokenType.Identifier: case TokenType.Array: var segmented = token as SegmentedIdentifierToken; var memberExpression = token.Type != TokenType.Array ? (segmented != null ? p.GetMemberExpression(segmented.Segments, Grammar.IgnoreCase) : p.GetMemberExpression(token.Lexeme, Grammar.IgnoreCase) ) : p.GetMemberExpression(token.Lexeme.Split(Grammar.IdentifierDelimiter), Grammar.IgnoreCase); if (memberExpression == null && Grammar.ImplementsVariables) { Type varType; if (NestedVars.GetVars(stack, Grammar.IgnoreCase).TryGetValue(token.Lexeme, out varType) || Grammar.Strict) { // get variable var getter = Grammar.IgnoreCase ? MemberTokens.VariablesIgnoreCase.Get : MemberTokens.Variables.Get; return(Expression.Call(getter, p, Expression.Constant(token.Lexeme)).Convert(varType ?? typeof(object))); } } if (Grammar.Strict)// || segmented != null) { if (memberExpression == null) { throw new XPressionException(token.Source, "invalid member: " + token.Lexeme, token.Position); } } if (token.Type == TokenType.Array) { return(BuildArrayAccessExpression((FunctionToken)token, memberExpression != null ? (Expression)memberExpression : Expression.Constant(token.Lexeme), stack, p)); } return(memberExpression != null ? (Expression)memberExpression : Expression.Constant(token.Lexeme)); // when strict is off, handle as a string constant case TokenType.Literal: var literalToken = (LiteralToken)token; if (literalToken.ConvertedValue is TimeSpan && !string.IsNullOrEmpty(token.Lexeme) && token.Lexeme[0] == 'P') { // just to be sure.... var me = p.GetMemberExpression(token.Lexeme, Grammar.IgnoreCase); if (me != null) { return(me); } } return(Expression.Constant(literalToken.ConvertedValue)); case TokenType.Function: case TokenType.FunctionalBinaryOperator: case TokenType.FunctionalUnaryOperator: try { Expression expression; if (Grammar.FunctionBuilder.TryBuildExpression(this, (FunctionToken)token, stack, p, out expression)) { return(expression); } } catch (XPressionException) { throw; } catch (Exception ex) { throw new XPressionException(token.Source, ex.Message, token.Position, ex); } throw new XPressionException(token.Source, "unknown function: " + token.Lexeme, token.Position); case TokenType.Assignment: return(BuildAssignmentExpression(stack, p)); case TokenType.Declaration: return(BuildDeclarationExpression(stack, p)); case TokenType.LogicalOr: return(BuildBinaryExpression(stack, Expression.OrElse, p)); case TokenType.LogicalAnd: return(BuildBinaryExpression(stack, Expression.AndAlso, p)); case TokenType.LogicalNot: return(BuildUnaryExpression(stack, Expression.Not, p)); case TokenType.Negate: return(BuildUnaryExpression(stack, Expression.Negate, p)); case TokenType.Mod: return(BuildBinaryExpression(stack, Expression.Modulo, p)); case TokenType.Div: return(BuildBinaryExpression(stack, Expression.Divide, p)); case TokenType.Mul: return(BuildBinaryExpression(stack, Expression.Multiply, p)); case TokenType.Pow: return(BuildBinaryExpression(stack, Expression.Power, p)); case TokenType.Add: return(BuildBinaryExpression(stack, Expression.Add, p)); case TokenType.Sub: return(BuildBinaryExpression(stack, Expression.Subtract, p)); case TokenType.Has: return(BuildBinaryHasExpression(stack, p)); case TokenType.BitwiseOr: return(BuildBinaryExpression(stack, Expression.Or, p)); case TokenType.BitwiseAnd: return(BuildBinaryExpression(stack, Expression.And, p)); case TokenType.BitwiseXOr: return(BuildBinaryExpression(stack, Expression.ExclusiveOr, p)); case TokenType.LeftShift: return(BuildBinaryExpression(stack, Expression.LeftShift, p)); case TokenType.RightShift: return(BuildBinaryExpression(stack, Expression.RightShift, p)); case TokenType.BitwiseNot: return(BuildUnaryExpression(stack, Expression.OnesComplement, p)); case TokenType.Equal: return(BuildBinaryExpression(stack, Expression.Equal, p)); case TokenType.LessThan: return(BuildBinaryCompareExpressionExceptEqual(stack, Expression.LessThan, p, ExpressionType.LessThan)); case TokenType.GreaterThan: return(BuildBinaryCompareExpressionExceptEqual(stack, Expression.GreaterThan, p, ExpressionType.GreaterThan)); case TokenType.LessThanOrEqual: return(BuildBinaryCompareExpressionExceptEqual(stack, Expression.LessThanOrEqual, p, ExpressionType.LessThanOrEqual)); case TokenType.GreaterThanOrEqual: return(BuildBinaryCompareExpressionExceptEqual(stack, Expression.GreaterThanOrEqual, p, ExpressionType.GreaterThanOrEqual)); case TokenType.NotEqual: return(BuildBinaryExpression(stack, Expression.NotEqual, p)); case TokenType.Like: return(BuildLikeExpression(stack, token, p)); case TokenType.Contains: right = PopExpression(stack, p); left = PopExpression(stack, p); return(Expression.Call(left, MemberTokens.String.Contains, right)); case TokenType.StartsWith: right = PopExpression(stack, p); left = PopExpression(stack, p); return(Expression.Call(left, MemberTokens.String.StartsWith, right)); case TokenType.EndsWith: right = PopExpression(stack, p); left = PopExpression(stack, p); return(Expression.Call(left, MemberTokens.String.EndsWith, right)); default: throw new ArgumentOutOfRangeException(); } }
private Expression BuildAssignmentExpression(Stack <Token> stack, ParameterExpression p) { Type varType; Dictionary <string, Type> vars; MethodInfo setter; var right = PopExpression(stack, p); var token = stack.Pop(); if (token.Type != TokenType.Identifier) { if (token.Type == TokenType.Expression && Grammar.ImplementsVariables) { var expr = token.CastTo <ExpressionToken>().Expression as MethodCallExpression; if (expr != null && expr.Method == MemberTokens.Variables.Declare) { // left token is declaration var name = (string)expr.Arguments[1].CastTo <ConstantExpression>().Value; vars = NestedVars.GetVars(stack, Grammar.IgnoreCase); vars.TryGetValue(name, out varType); if (varType == null) { vars[name] = right.Type; } setter = Grammar.IgnoreCase ? MemberTokens.VariablesIgnoreCase.Set : MemberTokens.Variables.Set; return(Expression.And(expr, Expression.Call(setter, p.Convert <object>(), Expression.Constant(name), right.Convert <object>()))); } } throw new XPressionException(token.Source, "Expected an identifier or declaration", token.Position); } var segmented = token as SegmentedIdentifierToken; var memberExpression = segmented != null ? p.GetMemberExpression(segmented.Segments, Grammar.IgnoreCase) : p.GetMemberExpression(token.Lexeme, Grammar.IgnoreCase); if (memberExpression != null) { var memberType = memberExpression.Member.GetMemberType(); if (!right.Type.CanBeConvertedInto(memberType)) { throw new XPressionException(token.Source, string.Format("Invalid cast. Cannot cast from {0} to {1}", right.Type.Name, memberType.Name), token.Position); } return(Expression.Call(MemberTokens.Assignment.Set, memberExpression.Expression.Convert <object>(), Expression.Constant(memberExpression.Member), right.Convert <object>())); } if (!Grammar.ImplementsVariables) { throw new XPressionException(token.Source, "Member not found: " + token.Lexeme, token.Position); } vars = NestedVars.GetVars(stack, Grammar.IgnoreCase); if (!vars.TryGetValue(token.Lexeme, out varType)) { throw new XPressionException(token.Source, "Variable not declared: " + token.Lexeme, token.Position); } if (varType == null) { vars[token.Lexeme] = (varType = right.Type); } if (!right.Type.CanBeConvertedInto(varType)) { throw new XPressionException(token.Source, string.Format("Invalid cast. Cannot cast from {0} to {1}", right.Type.Name, varType.Name), token.Position); } setter = Grammar.IgnoreCase ? MemberTokens.VariablesIgnoreCase.Set : MemberTokens.Variables.Set; return(Expression.Call(setter, p.Convert <object>(), Expression.Constant(token.Lexeme), right.Convert <object>())); }