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)); }