// parses $apply compute expression (.e.g. compute(UnitPrice mul SalesPrice as computePrice) internal ComputeToken ParseCompute() { Debug.Assert(TokenIdentifierIs(ExpressionConstants.KeywordCompute), "token identifier is compute"); lexer.NextToken(); // '(' if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.OpenParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_OpenParenExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } lexer.NextToken(); List <ComputeExpressionToken> transformationTokens = new List <ComputeExpressionToken>(); while (true) { ComputeExpressionToken computed = this.ParseComputeExpression(); transformationTokens.Add(computed); if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma) { break; } this.lexer.NextToken(); } // ")" if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.CloseParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_CloseParenOrCommaExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); return(new ComputeToken(transformationTokens)); }
/// <summary> /// Parses typed literals. /// </summary> /// <param name="expressionLexer">The expression lexer.</param> /// <param name="targetTypeReference">Expected type to be parsed.</param> /// <returns>The literal token produced by building the given literal.</returns> private static object ParseTypedLiteral(this ExpressionLexer expressionLexer, IEdmTypeReference targetTypeReference) { UriLiteralParsingException typeParsingException; object targetValue = DefaultUriLiteralParser.Instance.ParseUriStringToType(expressionLexer.CurrentToken.Text, targetTypeReference, out typeParsingException); if (targetValue == null) { string message; if (typeParsingException == null) { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral( targetTypeReference.FullName(), expressionLexer.CurrentToken.Text, expressionLexer.CurrentToken.Position, expressionLexer.ExpressionText); throw new ODataException(message); } else { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteralWithReason( targetTypeReference.FullName(), expressionLexer.CurrentToken.Text, expressionLexer.CurrentToken.Position, expressionLexer.ExpressionText, typeParsingException.Message); throw new ODataException(message, typeParsingException); } } expressionLexer.NextToken(); return(targetValue); }
/// <summary> /// Parses parameter alias into token. /// </summary> /// <param name="lexer">The lexer to use.</param> /// <returns>The parameter alias token.</returns> private static FunctionParameterAliasToken ParseParameterAlias(ExpressionLexer lexer) { Debug.Assert(lexer != null, "lexer != null"); FunctionParameterAliasToken ret = new FunctionParameterAliasToken(lexer.CurrentToken.Text); lexer.NextToken(); return(ret); }
/// <summary> /// Parses null literals. /// </summary> /// <param name="expressionLexer">The expression lexer.</param> /// <returns>The literal token produced by building the given literal.</returns> private static object ParseNullLiteral(this ExpressionLexer expressionLexer) { Debug.Assert(expressionLexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.InternalKind == ExpressionTokenKind.NullLiteral"); expressionLexer.NextToken(); ODataNullValue nullValue = new ODataNullValue(); return(nullValue); }
/// <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 LiteralToken ParseNullLiteral(ExpressionLexer lexer) { Debug.Assert(lexer != null, "lexer != null"); Debug.Assert(lexer.CurrentToken.Kind == ExpressionTokenKind.NullLiteral, "this.lexer.CurrentToken.InternalKind == ExpressionTokenKind.NullLiteral"); LiteralToken result = new LiteralToken(null, lexer.CurrentToken.Text); lexer.NextToken(); return(result); }
/// <summary>Reads the next token, checks that it is a literal token type, converts to to a Common Language Runtime value as appropriate, and returns the value.</summary> /// <param name="expressionLexer">The expression lexer.</param> /// <returns>The value represented by the next token.</returns> internal static object ReadLiteralToken(this ExpressionLexer expressionLexer) { expressionLexer.NextToken(); if (expressionLexer.CurrentToken.Kind.IsLiteralType()) { return(TryParseLiteral(expressionLexer)); } throw new ODataException(ODataErrorStrings.ExpressionLexer_ExpectedLiteralToken(expressionLexer.CurrentToken.Text)); }
/// <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 LiteralToken TryParseLiteral(ExpressionLexer lexer) { Debug.Assert(lexer != null, "lexer != null"); switch (lexer.CurrentToken.Kind) { case ExpressionTokenKind.BooleanLiteral: case ExpressionTokenKind.DateLiteral: case ExpressionTokenKind.DecimalLiteral: case ExpressionTokenKind.StringLiteral: case ExpressionTokenKind.Int64Literal: case ExpressionTokenKind.IntegerLiteral: case ExpressionTokenKind.DoubleLiteral: case ExpressionTokenKind.SingleLiteral: case ExpressionTokenKind.GuidLiteral: case ExpressionTokenKind.BinaryLiteral: case ExpressionTokenKind.GeographyLiteral: case ExpressionTokenKind.GeometryLiteral: case ExpressionTokenKind.QuotedLiteral: case ExpressionTokenKind.DurationLiteral: case ExpressionTokenKind.TimeOfDayLiteral: case ExpressionTokenKind.DateTimeOffsetLiteral: case ExpressionTokenKind.CustomTypeLiteral: IEdmTypeReference literalEdmTypeReference = lexer.CurrentToken.GetLiteralEdmTypeReference(); // Why not using EdmTypeReference.FullName? (literalEdmTypeReference.FullName) string edmConstantName = GetEdmConstantNames(literalEdmTypeReference); return(ParseTypedLiteral(lexer, literalEdmTypeReference, edmConstantName)); case ExpressionTokenKind.BracedExpression: case ExpressionTokenKind.BracketedExpression: case ExpressionTokenKind.ParenthesesExpression: { LiteralToken result = new LiteralToken(lexer.CurrentToken.Text, lexer.CurrentToken.Text); lexer.NextToken(); return(result); } case ExpressionTokenKind.NullLiteral: return(ParseNullLiteral(lexer)); default: return(null); } }
/// <summary> /// Parses typed literals. /// </summary> /// <param name="lexer">The lexer to use.</param> /// <param name="targetTypeReference">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 LiteralToken ParseTypedLiteral(ExpressionLexer lexer, IEdmTypeReference targetTypeReference, string targetTypeName) { Debug.Assert(lexer != null, "lexer != null"); UriLiteralParsingException typeParsingException; object targetValue = DefaultUriLiteralParser.Instance.ParseUriStringToType(lexer.CurrentToken.Text, targetTypeReference, out typeParsingException); if (targetValue == null) { string message; if (typeParsingException == null) { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral( targetTypeName, lexer.CurrentToken.Text, lexer.CurrentToken.Position, lexer.ExpressionText); throw ParseError(message); } else { message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteralWithReason( targetTypeName, lexer.CurrentToken.Text, lexer.CurrentToken.Position, lexer.ExpressionText, typeParsingException.Message); throw ParseError(message, typeParsingException); } } LiteralToken result = new LiteralToken(targetValue, lexer.CurrentToken.Text); lexer.NextToken(); return(result); }
/// <summary> /// Read a query option from the lexer. /// </summary> /// <returns>The query option as a string.</returns> internal static string ReadQueryOption(ExpressionLexer lexer) { if (lexer.CurrentToken.Kind != ExpressionTokenKind.Equal) { throw new ODataException(ODataErrorStrings.UriSelectParser_TermIsNotValid(lexer.ExpressionText)); } // get the full text from the current location onward // there could be literals like 'A string literal; tricky!' in there, so we need to be careful. // Also there could be more nested (...) expressions that we ignore until we recurse enough times to get there. string expressionText = lexer.AdvanceThroughExpandOption(); if (lexer.CurrentToken.Kind == ExpressionTokenKind.SemiColon) { // Move over the ';' separator lexer.NextToken(); return(expressionText); } // If there wasn't a semicolon, it MUST be the last option. We must be at ')' in this case lexer.ValidateToken(ExpressionTokenKind.CloseParen); return(expressionText); }
// parses $apply aggregate tranformation (.e.g. aggregate(UnitPrice with sum as TotalUnitPrice) internal AggregateToken ParseAggregate() { Debug.Assert(TokenIdentifierIs(ExpressionConstants.KeywordAggregate), "token identifier is aggregate"); lexer.NextToken(); // '(' if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.OpenParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_OpenParenExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); // series of statements separates by commas var statements = new List <AggregateExpressionToken>(); while (true) { statements.Add(this.ParseAggregateExpression()); if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.Comma) { break; } this.lexer.NextToken(); } // ")" if (this.lexer.CurrentToken.Kind != ExpressionTokenKind.CloseParen) { throw ParseError(ODataErrorStrings.UriQueryExpressionParser_CloseParenOrCommaExpected(this.lexer.CurrentToken.Position, this.lexer.ExpressionText)); } this.lexer.NextToken(); return(new AggregateToken(statements)); }