/// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <param name="targetType">Expected type to be parsed.</param>
        /// <param name="targetTypeName">The EDM type name of the expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralQueryToken ParseTypedLiteral(ExpressionLexer lexer, Type targetType, string targetTypeName)
        {
            Debug.Assert(lexer != null, "lexer != null");

            object targetValue;

            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(lexer.CurrentToken.Text, targetType, out targetValue))
            {
                string message = Strings.UriQueryExpressionParser_UnrecognizedLiteral(
                    targetTypeName,
                    lexer.CurrentToken.Text,
                    lexer.CurrentToken.Position,
                    lexer.ExpressionText);
                throw ParseError(message);
            }

            LiteralQueryToken result = new LiteralQueryToken()
            {
                Value        = targetValue,
                OriginalText = lexer.CurrentToken.Text
            };

            lexer.NextToken();
            return(result);
        }
        /// <summary>
        /// Parses a literal.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal query token or null if something else was found.</returns>
        internal static LiteralQueryToken TryParseLiteral(ExpressionLexer lexer)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(lexer != null, "lexer != null");

            switch (lexer.CurrentToken.Kind)
            {
                case ExpressionTokenKind.BooleanLiteral:
                    return ParseTypedLiteral(lexer, typeof(bool), EdmConstants.EdmBooleanTypeName);
                case ExpressionTokenKind.DateTimeLiteral:
                    return ParseTypedLiteral(lexer, typeof(DateTime), EdmConstants.EdmDateTimeTypeName);
                case ExpressionTokenKind.DecimalLiteral:
                    return ParseTypedLiteral(lexer, typeof(decimal), EdmConstants.EdmDecimalTypeName);
                case ExpressionTokenKind.NullLiteral:
                    return ParseNullLiteral(lexer);
                case ExpressionTokenKind.StringLiteral:
                    return ParseTypedLiteral(lexer, typeof(string), EdmConstants.EdmStringTypeName);
                case ExpressionTokenKind.Int64Literal:
                    return ParseTypedLiteral(lexer, typeof(Int64), EdmConstants.EdmInt64TypeName);
                case ExpressionTokenKind.IntegerLiteral:
                    return ParseTypedLiteral(lexer, typeof(Int32), EdmConstants.EdmInt32TypeName);
                case ExpressionTokenKind.DoubleLiteral:
                    return ParseTypedLiteral(lexer, typeof(double), EdmConstants.EdmDoubleTypeName);
                case ExpressionTokenKind.SingleLiteral:
                    return ParseTypedLiteral(lexer, typeof(Single), EdmConstants.EdmSingleTypeName);
                case ExpressionTokenKind.GuidLiteral:
                    return ParseTypedLiteral(lexer, typeof(Guid), EdmConstants.EdmGuidTypeName);
                case ExpressionTokenKind.BinaryLiteral:
                    return ParseTypedLiteral(lexer, typeof(byte[]), EdmConstants.EdmBinaryTypeName);
                default:
                    return null;
            }
        }
Beispiel #3
0
        /// <summary>Gets the current identifier text.</summary>
        /// <returns>The current identifier text.</returns>
        internal string GetIdentifier()
        {
            DebugUtils.CheckNoExternalCallers();

            if (this.Kind != ExpressionTokenKind.Identifier)
            {
                throw ExpressionLexer.ParseError(Strings.ExpressionToken_IdentifierExpected(this.Position));
            }

            return(this.Text);
        }
Beispiel #4
0
        /// <summary>
        /// Parses the key value literal.
        /// </summary>
        /// <param name="lexer">The lexer positioned on the key value.</param>
        /// <returns>The literal query token.</returns>
        private static LiteralQueryToken ParseKeyValueLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");

            LiteralQueryToken result = UriQueryExpressionParser.TryParseLiteral(lexer);

            if (result == null)
            {
                throw new ODataException(Strings.UriQueryPathParser_InvalidKeyValueLiteral(lexer.CurrentToken.Text));
            }

            return(result);
        }
        /// <summary>
        /// Parses null literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralQueryToken ParseNullLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");
            Debug.Assert(lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral");

            LiteralQueryToken result = new LiteralQueryToken()
            {
                Value        = null,
                OriginalText = lexer.CurrentToken.Text
            };

            lexer.NextToken();
            return(result);
        }
        /// <summary>
        /// Parses the $filter expression.
        /// </summary>
        /// <param name="filter">The $filter expression string to parse.</param>
        /// <returns>The lexical token representing the filter.</returns>
        internal QueryToken ParseFilter(string filter)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(filter != null, "filter != null");

            this.recursionDepth = 0;
            this.lexer          = new ExpressionLexer(filter);

            QueryToken result = this.ParseExpression();

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return(result);
        }
        /// <summary>
        /// Parses a literal.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal query token or null if something else was found.</returns>
        internal static LiteralQueryToken TryParseLiteral(ExpressionLexer lexer)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(lexer != null, "lexer != null");

            switch (lexer.CurrentToken.Kind)
            {
            case ExpressionTokenKind.BooleanLiteral:
                return(ParseTypedLiteral(lexer, typeof(bool), EdmConstants.EdmBooleanTypeName));

            case ExpressionTokenKind.DateTimeLiteral:
                return(ParseTypedLiteral(lexer, typeof(DateTime), EdmConstants.EdmDateTimeTypeName));

            case ExpressionTokenKind.DecimalLiteral:
                return(ParseTypedLiteral(lexer, typeof(decimal), EdmConstants.EdmDecimalTypeName));

            case ExpressionTokenKind.NullLiteral:
                return(ParseNullLiteral(lexer));

            case ExpressionTokenKind.StringLiteral:
                return(ParseTypedLiteral(lexer, typeof(string), EdmConstants.EdmStringTypeName));

            case ExpressionTokenKind.Int64Literal:
                return(ParseTypedLiteral(lexer, typeof(Int64), EdmConstants.EdmInt64TypeName));

            case ExpressionTokenKind.IntegerLiteral:
                return(ParseTypedLiteral(lexer, typeof(Int32), EdmConstants.EdmInt32TypeName));

            case ExpressionTokenKind.DoubleLiteral:
                return(ParseTypedLiteral(lexer, typeof(double), EdmConstants.EdmDoubleTypeName));

            case ExpressionTokenKind.SingleLiteral:
                return(ParseTypedLiteral(lexer, typeof(Single), EdmConstants.EdmSingleTypeName));

            case ExpressionTokenKind.GuidLiteral:
                return(ParseTypedLiteral(lexer, typeof(Guid), EdmConstants.EdmGuidTypeName));

            case ExpressionTokenKind.BinaryLiteral:
                return(ParseTypedLiteral(lexer, typeof(byte[]), EdmConstants.EdmBinaryTypeName));

            default:
                return(null);
            }
        }
        /// <summary>
        /// Parses the $orderby expression.
        /// </summary>
        /// <param name="orderBy">The $orderby expression string to parse.</param>
        /// <returns>The enumeraion of lexical tokens representing order by tokens.</returns>
        internal IEnumerable <OrderByQueryToken> ParseOrderBy(string orderBy)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(orderBy != null, "orderBy != null");

            this.recursionDepth = 0;
            this.lexer          = new ExpressionLexer(orderBy);

            List <OrderByQueryToken> orderByTokens = new List <OrderByQueryToken>();

            while (true)
            {
                QueryToken expression = this.ParseExpression();
                bool       ascending  = true;
                if (this.TokenIdentifierIs(ExpressionConstants.KeywordAscending))
                {
                    this.lexer.NextToken();
                }
                else if (this.TokenIdentifierIs(ExpressionConstants.KeywordDescending))
                {
                    this.lexer.NextToken();
                    ascending = false;
                }

                OrderByQueryToken orderByToken = new OrderByQueryToken()
                {
                    Direction  = ascending ? OrderByDirection.Ascending : OrderByDirection.Descending,
                    Expression = expression
                };
                orderByTokens.Add(orderByToken);
                if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma)
                {
                    break;
                }

                this.lexer.NextToken();
            }

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return(new ReadOnlyCollection <OrderByQueryToken>(orderByTokens));
        }
        /// <summary>
        /// Parses the -, not unary operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseUnary()
        {
            this.RecurseEnter();
            if (this.lexer.CurrentToken.Kind == ExpressionTokenKind.Minus || this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordNot))
            {
                ExpressionToken operatorToken = this.lexer.CurrentToken;
                this.lexer.NextToken();
                if (operatorToken.Kind == ExpressionTokenKind.Minus && (ExpressionLexer.IsNumeric(this.lexer.CurrentToken.Kind)))
                {
                    ExpressionToken numberLiteral = this.lexer.CurrentToken;
                    numberLiteral.Text      = "-" + numberLiteral.Text;
                    numberLiteral.Position  = operatorToken.Position;
                    this.lexer.CurrentToken = numberLiteral;
                    this.RecurseLeave();
                    return(this.ParsePrimary());
                }

                QueryToken        operand = this.ParseUnary();
                UnaryOperatorKind unaryOperatorKind;
                if (operatorToken.Kind == ExpressionTokenKind.Minus)
                {
                    unaryOperatorKind = UnaryOperatorKind.Negate;
                }
                else
                {
                    Debug.Assert(operatorToken.IdentifierIs(ExpressionConstants.KeywordNot), "Was a new unary operator added?");
                    unaryOperatorKind = UnaryOperatorKind.Not;
                }

                this.RecurseLeave();
                return(new UnaryOperatorQueryToken()
                {
                    OperatorKind = unaryOperatorKind,
                    Operand = operand
                });
            }

            this.RecurseLeave();
            return(this.ParsePrimary());
        }
        /// <summary>
        /// Parses the key value literal.
        /// </summary>
        /// <param name="lexer">The lexer positioned on the key value.</param>
        /// <returns>The literal query token.</returns>
        private static LiteralQueryToken ParseKeyValueLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");

            LiteralQueryToken result = UriQueryExpressionParser.TryParseLiteral(lexer);
            if (result == null)
            {
                throw new ODataException(Strings.UriQueryPathParser_InvalidKeyValueLiteral(lexer.CurrentToken.Text));
            }

            return result;
        }
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <returns>
        /// Enumeration of key values or null if there was a syntax error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values.
        /// </remarks>
        private static IEnumerable<NamedValue> ParseKeyValuesFromUri(string text)
        {
            Debug.Assert(text != null, "text != null");

            //// This is a modified copy of KeyInstance.TryParseFromUri

            ExpressionLexer lexer = new ExpressionLexer(text);
            ExpressionToken currentToken = lexer.CurrentToken;
            if (currentToken.Kind == ExpressionTokenKind.End)
            {
                return EmptyKeyValues;
            }

            List<NamedValue> keyValuesList = new List<NamedValue>();
            do
            {
                if (currentToken.Kind == ExpressionTokenKind.Identifier)
                {
                    // Name-value pair.
                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Kind != ExpressionTokenKind.Equal)
                    {
                        return null;
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return null;
                    }

                    keyValuesList.Add(new NamedValue() { Name = identifier, Value = ParseKeyValueLiteral(lexer) });
                }
                else if (currentToken.IsKeyValueToken)
                {
                    // Unnamed value.
                    keyValuesList.Add(new NamedValue() { Value = ParseKeyValueLiteral(lexer) });
                }
                else
                {
                    return null;
                }

                // Read the next token. We should be at the end, or find
                // we have a comma followed by something.
                currentToken = lexer.NextToken();
                if (currentToken.Kind == ExpressionTokenKind.Comma)
                {
                    currentToken = lexer.NextToken();
                    if (currentToken.Kind == ExpressionTokenKind.End)
                    {
                        // Trailing comma.
                        return null;
                    }
                }
            }
            while (currentToken.Kind != ExpressionTokenKind.End);

            return keyValuesList;
        }
Beispiel #12
0
        /// <summary>Attempts to parse key values from the specified text.</summary>
        /// <param name='text'>Text to parse (not null).</param>
        /// <returns>
        /// Enumeration of key values or null if there was a syntax error.
        /// </returns>
        /// <remarks>
        /// The returned instance contains only string values.
        /// </remarks>
        private static IEnumerable <NamedValue> ParseKeyValuesFromUri(string text)
        {
            Debug.Assert(text != null, "text != null");

            //// This is a modified copy of KeyInstance.TryParseFromUri

            ExpressionLexer lexer        = new ExpressionLexer(text);
            ExpressionToken currentToken = lexer.CurrentToken;

            if (currentToken.Kind == ExpressionTokenKind.End)
            {
                return(EmptyKeyValues);
            }

            List <NamedValue> keyValuesList = new List <NamedValue>();

            do
            {
                if (currentToken.Kind == ExpressionTokenKind.Identifier)
                {
                    // Name-value pair.
                    string identifier = lexer.CurrentToken.GetIdentifier();
                    lexer.NextToken();
                    if (lexer.CurrentToken.Kind != ExpressionTokenKind.Equal)
                    {
                        return(null);
                    }

                    lexer.NextToken();
                    if (!lexer.CurrentToken.IsKeyValueToken)
                    {
                        return(null);
                    }

                    keyValuesList.Add(new NamedValue()
                    {
                        Name = identifier, Value = ParseKeyValueLiteral(lexer)
                    });
                }
                else if (currentToken.IsKeyValueToken)
                {
                    // Unnamed value.
                    keyValuesList.Add(new NamedValue()
                    {
                        Value = ParseKeyValueLiteral(lexer)
                    });
                }
                else
                {
                    return(null);
                }

                // Read the next token. We should be at the end, or find
                // we have a comma followed by something.
                currentToken = lexer.NextToken();
                if (currentToken.Kind == ExpressionTokenKind.Comma)
                {
                    currentToken = lexer.NextToken();
                    if (currentToken.Kind == ExpressionTokenKind.End)
                    {
                        // Trailing comma.
                        return(null);
                    }
                }
            }while (currentToken.Kind != ExpressionTokenKind.End);

            return(keyValuesList);
        }
        /// <summary>
        /// Parses null literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralQueryToken ParseNullLiteral(ExpressionLexer lexer)
        {
            Debug.Assert(lexer != null, "lexer != null");
            Debug.Assert(lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral");

            LiteralQueryToken result = new LiteralQueryToken()
            {
                Value = null,
                OriginalText = lexer.CurrentToken.Text
            };

            lexer.NextToken();
            return result;
        }
        /// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="lexer">The lexer to use.</param>
        /// <param name="targetType">Expected type to be parsed.</param>
        /// <param name="targetTypeName">The EDM type name of the expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static LiteralQueryToken ParseTypedLiteral(ExpressionLexer lexer, Type targetType, string targetTypeName)
        {
            Debug.Assert(lexer != null, "lexer != null");

            object targetValue;
            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(lexer.CurrentToken.Text, targetType, out targetValue))
            {
                string message = Strings.UriQueryExpressionParser_UnrecognizedLiteral(
                    targetTypeName,
                    lexer.CurrentToken.Text,
                    lexer.CurrentToken.Position,
                    lexer.ExpressionText);
                throw ParseError(message);
            }

            LiteralQueryToken result = new LiteralQueryToken()
            {
                Value = targetValue,
                OriginalText = lexer.CurrentToken.Text
            };
            lexer.NextToken();
            return result;
        }
        /// <summary>
        /// Parses the $orderby expression.
        /// </summary>
        /// <param name="orderBy">The $orderby expression string to parse.</param>
        /// <returns>The enumeraion of lexical tokens representing order by tokens.</returns>
        internal IEnumerable<OrderByQueryToken> ParseOrderBy(string orderBy)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(orderBy != null, "orderBy != null");

            this.recursionDepth = 0;
            this.lexer = new ExpressionLexer(orderBy);

            List<OrderByQueryToken> orderByTokens = new List<OrderByQueryToken>();
            while (true)
            {
                QueryToken expression = this.ParseExpression();
                bool ascending = true;
                if (this.TokenIdentifierIs(ExpressionConstants.KeywordAscending))
                {
                    this.lexer.NextToken();
                }
                else if (this.TokenIdentifierIs(ExpressionConstants.KeywordDescending))
                {
                    this.lexer.NextToken();
                    ascending = false;
                }

                OrderByQueryToken orderByToken = new OrderByQueryToken()
                {
                    Direction = ascending ? OrderByDirection.Ascending : OrderByDirection.Descending,
                    Expression = expression
                };
                orderByTokens.Add(orderByToken);
                if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma)
                {
                    break;
                }

                this.lexer.NextToken();
            }

            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return new ReadOnlyCollection<OrderByQueryToken>(orderByTokens);
        }
        /// <summary>
        /// Parses the $filter expression.
        /// </summary>
        /// <param name="filter">The $filter expression string to parse.</param>
        /// <returns>The lexical token representing the filter.</returns>
        internal QueryToken ParseFilter(string filter)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(filter != null, "filter != null");

            this.recursionDepth = 0;
            this.lexer = new ExpressionLexer(filter);

            QueryToken result = this.ParseExpression();
            this.lexer.ValidateToken(ExpressionTokenKind.End);

            return result;
        }