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