/// <summary>Parse one of the literals of skip token.</summary> /// <param name="literal">Input literal.</param> /// <returns>Object resulting from conversion of literal.</returns> internal static object ParseSkipTokenLiteral(string literal) { ExpressionLexer l = new ExpressionLexer(literal); ConstantNode node; if (!TokenToQueryNodeTranslator.TryCreateLiteral(l.CurrentToken, out node)) { throw new InvalidOperationException(ServiceStrings.RequsetQueryParser_ExpectingLiteralInSkipToken(literal)); } return node.Value; }
/// <summary>Parse one of the literals of skip token.</summary> /// <param name="literal">Input literal.</param> /// <returns>Object resulting from conversion of literal.</returns> internal static object ParseSkipTokenLiteral(string literal) { ExpressionLexer l = new ExpressionLexer(literal); ConstantNode node; if (!TokenToQueryNodeTranslator.TryCreateLiteral(l.CurrentToken, out node)) { throw new InvalidOperationException(ServiceStrings.RequsetQueryParser_ExpectingLiteralInSkipToken(literal)); } return(node.Value); }
/// <summary>Attempts to parse nullable values (only positional values, no name-value pairs) from the specified text.</summary> /// <param name='text'>Text to parse (not null).</param> /// <param name='values'>After invocation, the parsed skiptoken/etag values as strings.</param> /// <returns> /// true if the given values were parsed; false if there was a /// syntactic error. /// </returns> /// <remarks> /// The returned collection contains only string values. They must be converted later. /// </remarks> internal static bool TryParseNullableTokens(string text, out IList<object> values) { Debug.Assert(text != null, "text != null"); List<object> positionalValues = new List<object>(); values = positionalValues; #if ODATALIB ExpressionLexer lexer = new ExpressionLexer(text, true, false); #else ExpressionLexer lexer = new ExpressionLexer(text); #endif ExpressionToken currentToken = lexer.CurrentToken; if (currentToken.Kind == ExpressionTokenKind.End) { return true; } do { if (currentToken.IsLiteral) { // Positional value. positionalValues.Add(lexer.CurrentToken.Text); } else { return false; } // Read the next token. We should be at the end, or find // we have a comma followed by something. lexer.NextToken(); currentToken = lexer.CurrentToken; if (currentToken.Kind == ExpressionTokenKind.Comma) { lexer.NextToken(); currentToken = lexer.CurrentToken; if (currentToken.Kind == ExpressionTokenKind.End) { // Trailing comma. return false; } } } while (currentToken.Kind != ExpressionTokenKind.End); return true; }
/// <summary>Makes the expression that is used as a filter corresponding to skip token.</summary> /// <param name="topLevelOrderingInfo">Ordering expression.</param> /// <param name="skipToken">The provided skip token.</param> /// <param name="parameterType">The parameter type of the lambda.</param> /// <returns>LambdaExpression corresponding to the skip token filter.</returns> internal LambdaExpression BuildSkipTokenFilter(OrderingInfo topLevelOrderingInfo, IList<object> skipToken, Type parameterType) { ParameterExpression element = Expression.Parameter(parameterType, "element"); Expression lastCondition = Expression.Constant(true, typeof(bool)); Expression lastMatch = Expression.Constant(false, typeof(bool)); foreach (var v in WebUtil.Zip(topLevelOrderingInfo.OrderingExpressions, skipToken, (x, y) => new { Order = x, Value = y })) { BinaryOperatorKind comparisonExp = v.Order.IsAscending ? BinaryOperatorKind.GreaterThan : BinaryOperatorKind.LessThan; Expression fixedLambda = ParameterReplacerVisitor.Replace( ((LambdaExpression)v.Order.Expression).Body, ((LambdaExpression)v.Order.Expression).Parameters[0], element); // TODO: this will be an EnumNode if $skiptoken contains enum constant. ConstantNode node; var lexer = new ExpressionLexer((string)v.Value); bool success = TokenToQueryNodeTranslator.TryCreateLiteral(lexer.CurrentToken, out node); Debug.Assert(success, "Was not a literal"); node = this.EnsureCorrectTypeAndPrecisionForLFDM(node, fixedLambda.Type); Expression right = this.nodeToExpressionTranslator.TranslateNode(node); Expression comparison = ExpressionGenerator.GenerateLogicalAnd( lastCondition, this.GenerateNullAwareComparison(fixedLambda, right, comparisonExp)); lastMatch = ExpressionGenerator.GenerateLogicalOr(lastMatch, comparison); lastCondition = ExpressionGenerator.GenerateLogicalAnd( lastCondition, this.GenerateComparisonExpression(fixedLambda, right, BinaryOperatorKind.Equal)); } lastMatch = ExpressionUtils.EnsurePredicateExpressionIsBoolean(lastMatch); Debug.Assert(lastMatch.Type == typeof(bool), "Skip token should generate boolean expression."); return Expression.Lambda(lastMatch, element); }
/// <summary>Makes the expression that is used as a filter corresponding to skip token.</summary> /// <param name="topLevelOrderingInfo">Ordering expression.</param> /// <param name="skipToken">The provided skip token.</param> /// <param name="parameterType">The parameter type of the lambda.</param> /// <returns>LambdaExpression corresponding to the skip token filter.</returns> internal LambdaExpression BuildSkipTokenFilter(OrderingInfo topLevelOrderingInfo, IList <object> skipToken, Type parameterType) { ParameterExpression element = Expression.Parameter(parameterType, "element"); Expression lastCondition = Expression.Constant(true, typeof(bool)); Expression lastMatch = Expression.Constant(false, typeof(bool)); foreach (var v in WebUtil.Zip(topLevelOrderingInfo.OrderingExpressions, skipToken, (x, y) => new { Order = x, Value = y })) { BinaryOperatorKind comparisonExp = v.Order.IsAscending ? BinaryOperatorKind.GreaterThan : BinaryOperatorKind.LessThan; Expression fixedLambda = ParameterReplacerVisitor.Replace( ((LambdaExpression)v.Order.Expression).Body, ((LambdaExpression)v.Order.Expression).Parameters[0], element); // TODO: this will be an EnumNode if $skiptoken contains enum constant. ConstantNode node; var lexer = new ExpressionLexer((string)v.Value); bool success = TokenToQueryNodeTranslator.TryCreateLiteral(lexer.CurrentToken, out node); Debug.Assert(success, "Was not a literal"); node = this.EnsureCorrectTypeAndPrecisionForLFDM(node, fixedLambda.Type); Expression right = this.nodeToExpressionTranslator.TranslateNode(node); Expression comparison = ExpressionGenerator.GenerateLogicalAnd( lastCondition, this.GenerateNullAwareComparison(fixedLambda, right, comparisonExp)); lastMatch = ExpressionGenerator.GenerateLogicalOr(lastMatch, comparison); lastCondition = ExpressionGenerator.GenerateLogicalAnd( lastCondition, this.GenerateComparisonExpression(fixedLambda, right, BinaryOperatorKind.Equal)); } lastMatch = ExpressionUtils.EnsurePredicateExpressionIsBoolean(lastMatch); Debug.Assert(lastMatch.Type == typeof(bool), "Skip token should generate boolean expression."); return(Expression.Lambda(lastMatch, element)); }
/// <summary>Reads a $select clause.</summary> /// <param name="value">Value to read.</param> /// <param name="dataServiceProviderWrapper">The provider wrapper for the service.</param> /// <returns>A list of paths, each of which is a list of identifiers.</returns> private static IList<IList<string>> SplitSelect(string value, DataServiceProviderWrapper dataServiceProviderWrapper) { Debug.Assert(!String.IsNullOrEmpty(value), "!String.IsNullOrEmpty(value)"); List<IList<string>> result = new List<IList<string>>(); List<string> currentPath = null; ExpressionLexer lexer = new ExpressionLexer(value); while (lexer.CurrentToken.Kind != ExpressionTokenKind.End) { string identifier; bool lastSegment = false; if (lexer.CurrentToken.Kind == ExpressionTokenKind.Star) { identifier = lexer.CurrentToken.Text; lexer.NextToken(); lastSegment = true; } else { identifier = lexer.ReadDottedIdentifier(true /*allowEndWithDotStar*/); bool nameIsContainerQualifed; if (dataServiceProviderWrapper.GetNameFromContainerQualifiedName(identifier, out nameIsContainerQualifed) == "*") { lastSegment = true; } } if (currentPath == null) { currentPath = new List<string>(); result.Add(currentPath); } currentPath.Add(identifier); // Check whether we're at the end, whether we're drilling in, // or whether we're finishing with this path. ExpressionTokenKind tokenId = lexer.CurrentToken.Kind; if (tokenId != ExpressionTokenKind.End) { if (lastSegment || tokenId != ExpressionTokenKind.Slash) { lexer.ValidateToken(ExpressionTokenKind.Comma); currentPath = null; } lexer.NextToken(); } } return result; }