コード例 #1
0
        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)));
        }
コード例 #2
0
        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();
            }
        }
コード例 #3
0
        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>()));
        }