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