private ODataExpression GetNext(ODataParameterExpression parameter, ODataExpression parent = null, IDictionary <string, ODataParameterExpression> lambdaParameters = null)
        {
            if (_offset >= _source.Length)
            {
                return(null);
            }

            while (_offset < _source.Length && Char.IsWhiteSpace(_source[_offset]))
            {
                _offset++;
            }

            if (_offset >= _source.Length)
            {
                return(null);
            }

            _current = _offset;

            var c = _source[_current];

            switch (c)
            {
            case '-':
                return(ParseSign(parameter, parent, lambdaParameters));

            case '\'':
                return(ParseString());

            case '(':
            case ')':
            case ',':
            case ':':
                return(ParseSyntax());

            default:
                if (isHex(c) && _offset + 36 <= _source.Length)
                {
                    var parsedAsGuid = ParseGuidString(_source.Substring(_offset, 36));
                    if (parsedAsGuid != null)
                    {
                        _offset += 36;
                        _current = _offset;
                        return(parsedAsGuid);
                    }
                }

                if (Char.IsNumber(c))     //It can be a number or a date
                {
                    return(ParseNumeric());
                }
                if (IsIdentifierStartChar(c))
                {
                    return(ParseIdentifier(false, parameter, parent, lambdaParameters));
                }
                throw new Exception(String.Format(
                                        "Unexpecter character '{0}' at offset {1}.", c, _current
                                        ));
            }
        }
        private ODataExpression ParseSign(ODataParameterExpression parameter, ODataExpression parent = null, IDictionary <string, ODataParameterExpression> lambdaParameters = null)
        {
            _current++;

            return(Char.IsDigit(_source[_current])
                ? ParseNumeric()
                : ParseIdentifier(true, parameter, parent, lambdaParameters));
        }
Ejemplo n.º 3
0
        private Expression VisitParameter(ODataParameterExpression node, Type parameterType)
        {
            if (_parameters.ContainsKey(node))
            {
                return(_parameters[node]);
            }

            return(_parameters[node] = Expression.Parameter(parameterType, node.Name));
        }
        internal IEnumerable <ODataExpression> Scan(ODataParameterExpression parameter)
        {
            _offset  = 0;
            _current = 0;

            var             tokens = new List <ODataExpression>();
            ODataExpression token;

            while ((token = GetNext(parameter)) != null)
            {
                tokens.Add(token);
            }

            return(tokens.ToArray());
        }
        private ODataExpression ParseIdentifier(bool minus, ODataParameterExpression parameter, ODataExpression parent = null, IDictionary <string, ODataParameterExpression> lambdaParameters = null)
        {
            for (_current++; _current < _source.Length; _current++)
            {
                var c = _source[_current];

                if (!IsIdentifierChar(c))
                {
                    break;
                }
            }

            var name = _source.Substring(_offset, _current - _offset);

            var lastOffset = _offset;

            _offset = _current;

            switch (name)
            {
            case "INF":
                return(ODataExpression.Constant(double.PositiveInfinity));

            case "-INF":
                return(ODataExpression.Constant(double.NegativeInfinity));

            case "Nan":
                return(ODataExpression.Constant(double.NaN));

            case "true":
                return(ODataExpression.Constant(true));

            case "false":
                return(ODataExpression.Constant(false));

            case "null":
                return(ODataExpression.Constant(null, typeof(object)));

            case "-":
            {
                return(new ODataUnaryExpression(ExpressionType.Negate));
            }

            default:
                if (minus)
                {
                    // Reset the offset.
                    _offset = lastOffset + 1;

                    return(new ODataUnaryExpression(ExpressionType.Negate));
                }
                break;
            }

            if (_offset < _source.Length)
            {
                switch (_source[_offset])
                {
                case '\'':
                {
                    StringType stringType;

                    switch (name)
                    {
                    case "X": stringType = StringType.Binary; break;

                    case "binary": stringType = StringType.Binary; break;

                    case "datetime": stringType = StringType.DateTime; break;

                    case "guid": stringType = StringType.Guid; break;

                    case "time": stringType = StringType.Time; break;

                    case "datetimeoffset": stringType = StringType.DateTimeOffset; break;

                    default: stringType = StringType.None; break;
                    }

                    if (stringType != StringType.None && _source[_offset] == '\'')
                    {
                        var content = ParseString();

                        return(ParseSpecialString((string)content.Value, stringType));
                    }

                    if (stringType == StringType.None)
                    {
                        var content = ParseString();

                        return(ParceValue(name, (string)content.Value));
                    }

                    break;
                }

                case ':':
                {
                    _offset++;

                    var depth = 0;

                    var p = ODataExpression.Parameter(name);

                    var lp = new Dictionary <string, ODataParameterExpression>(lambdaParameters ?? new Dictionary <string, ODataParameterExpression>());

                    lp[p.Name] = p;

                    var tokens = new List <ODataExpression>();

                    while (true)
                    {
                        var token = GetNext(parameter, null, lp);

                        if (token == null)
                        {
                            break;
                        }

                        if (token.NodeType == ExpressionType.Default)
                        {
                            var syntaxExpressionToken = (ODataSyntaxExpression)token;

                            if (syntaxExpressionToken.Syntax == ',')
                            {
                                _offset--;
                                break;
                            }

                            if (syntaxExpressionToken.Syntax == '(')
                            {
                                depth++;
                            }

                            if (syntaxExpressionToken.Syntax == ')')
                            {
                                if (depth == 0)
                                {
                                    _offset--;
                                    break;
                                }

                                depth--;
                            }
                        }

                        tokens.Add(token);
                    }

                    var body = CreateExpression(ConvertToRpn(tokens));

                    var lambdaExpression = new ODataLambdaExpression
                    {
                        Parameters = new[] { p },
                        Body       = body
                    };

                    return(lambdaExpression);
                }

                case '/':
                {
                    _offset++;

                    if (lambdaParameters != null && lambdaParameters.ContainsKey(name) && parent == null)
                    {
                        return(ParseIdentifier(false, parameter, lambdaParameters[name], lambdaParameters));
                    }
                    if (name.StartsWith("Ase.") && parent != null && name.Substring(4) == parent.ToString().Replace(parameter.ToString() + ".", ""))
                    {
                        return(ParseIdentifier(false, parameter, parent, lambdaParameters));
                    }

                    return(ParseIdentifier(false, parameter, ODataExpression.PropertyOrField(name, parent ?? parameter), lambdaParameters));
                }

                case '(':    //Если следующий элемент скобка, значит это функция
                {
                    var depth     = 0;
                    var comma     = false;
                    var arguments = new List <ODataExpression>();
                    var temp      = new List <ODataExpression>();

                    while (true)
                    {
                        var token = GetNext(parameter, null, lambdaParameters);

                        if (token == null)
                        {
                            break;
                        }
                        var syntax = token as ODataSyntaxExpression;

                        if (syntax != null && syntax.Syntax == ',')
                        {
                            if (temp.Any())
                            {
                                var tokens = ConvertToRpn(temp.ToArray());

                                var expression = CreateExpression(tokens);

                                arguments.Add(expression);

                                temp = new List <ODataExpression>();

                                comma = true;
                            }
                            else
                            {
                                throw new Exception("extra comma");
                            }
                        }
                        else
                        {
                            if (syntax != null && syntax.Syntax == '(')
                            {
                                if (comma)
                                {
                                    throw new Exception("extra comma");
                                }

                                depth++;
                            }

                            if (syntax != null && syntax.Syntax == ')')
                            {
                                if (comma)
                                {
                                    throw new Exception("extra comma");
                                }

                                depth--;
                            }

                            if (syntax == null ||
                                !(syntax.Syntax == '(' && depth == 1) && !(syntax.Syntax == ')' && depth == 0))
                            {
                                temp.Add(token);
                            }

                            comma = false;

                            if (depth == 0)
                            {
                                if (temp.Any())
                                {
                                    var tokens = ConvertToRpn(temp.ToArray());

                                    var expression = CreateExpression(tokens);


                                    arguments.Add(expression);
                                }

                                break;
                            }
                        }
                    }

                    if (depth != 0)
                    {
                        throw new Exception("Parenthesis mismatch");
                    }


                    var methodCallExpression = new ODataMethodCallExpression
                    {
                        Context    = parent,
                        MethodName = name,
                        Arguments  = arguments.ToArray()
                    };

                    if (_offset < _source.Length && _source[_offset] == '/')
                    {
                        _current++;

                        _offset = _offset + 1;


                        return(ParseIdentifier(false, parameter, methodCallExpression, lambdaParameters));
                    }


                    return(methodCallExpression);
                }
                }
            }

            if (name.IsOperator())
            {
                var expressionType = name.GetExpressionType();

                if (name.IsUnaryOperator())
                {
                    return(ODataExpression.MakeUnary(expressionType, null));
                }

                if (name.IsArithmeticOperator() || name.IsLogicalOperator())
                {
                    return(ODataExpression.MakeBinary(expressionType, null, null));
                }
            }

            if (parent == null && lambdaParameters != null && lambdaParameters.ContainsKey(name))
            {
                return(lambdaParameters[name]);
            }

            if (name.Contains("."))
            {
                var type = GetType(name);
                return(ODataExpression.Constant(type));
            }

            return(ODataExpression.PropertyOrField(name, parent ?? parameter));
        }
Ejemplo n.º 6
0
        private ODataExpression GetNext(ODataParameterExpression parameter, ODataExpression parent = null, IDictionary <string, ODataParameterExpression> lambdaParameters = null, bool funcBody = false)
        {
            if (_offset >= _source.Length)
            {
                return(null);
            }

            while (_offset < _source.Length && char.IsWhiteSpace(_source[_offset]))
            {
                _offset++;
            }

            if (_offset >= _source.Length)
            {
                return(null);
            }

            _current = _offset;

            var c = _source[_current];

            switch (c)
            {
            case '-':
                return(ParseSign(parameter, parent, lambdaParameters));

            case '\'':
                return(ParseString());

            case '(':
            {
                if (funcBody)
                {
                    return(ParseSyntax());
                }

                var position = GetBracketLastPosition(_current);

                if (position <= 0 || _source.Length <= position + 1 || _source[position + 1] != '/')
                {
                    return(ParseSyntax());
                }

                var source = _source.Substring(_current + 1, position - _current - 1);
                var lexer  = new ExpressionLexer(source);

                var             tokens = new List <ODataExpression>();
                ODataExpression token;

                while ((token = lexer.GetNext(parameter, parent, lambdaParameters)) != null)
                {
                    tokens.Add(token);
                }

                var expression = CreateExpression(ConvertToRpn(tokens));

                _current = position + 1;
                _offset  = _current + 1;

                return(ParseIdentifier(false, parameter, expression, lambdaParameters));
            }

            case ')':
            case ',':
            case ':':
                return(ParseSyntax());

            default:
                if (char.IsNumber(c))
                {
                    return(ParseNumeric());
                }

                if (IsIdentifierStartChar(c))
                {
                    return(ParseIdentifier(false, parameter, parent, lambdaParameters));
                }

                throw new Exception($"Unexpecter character '{c}' at offset {_current}.");
            }
        }