/// <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;
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }
Пример #5
0
        /// <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));
        }
Пример #6
0
        /// <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;
        }