Esempio n. 1
0
        /// <summary>
        /// Parses the add, sub operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseAdditive()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseMultiplicative();

            while (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordAdd) ||
                   this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordSub))
            {
                BinaryOperatorKind binaryOperatorKind;
                if (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordAdd))
                {
                    binaryOperatorKind = BinaryOperatorKind.Add;
                }
                else
                {
                    Debug.Assert(this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordSub), "Was a new binary operator added?");
                    binaryOperatorKind = BinaryOperatorKind.Subtract;
                }

                this.lexer.NextToken();
                QueryToken right = this.ParseMultiplicative();
                left = new BinaryOperatorQueryToken(binaryOperatorKind, left, right);
            }

            this.RecurseLeave();
            return(left);
        }
Esempio n. 2
0
        /// <summary>
        /// Parses the mul, div, mod operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseMultiplicative()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseUnary();

            while (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordMultiply) ||
                   this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordDivide) ||
                   this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordModulo))
            {
                BinaryOperatorKind binaryOperatorKind;
                if (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordMultiply))
                {
                    binaryOperatorKind = BinaryOperatorKind.Multiply;
                }
                else if (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordDivide))
                {
                    binaryOperatorKind = BinaryOperatorKind.Divide;
                }
                else
                {
                    Debug.Assert(this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordModulo), "Was a new binary operator added?");
                    binaryOperatorKind = BinaryOperatorKind.Modulo;
                }

                this.lexer.NextToken();
                QueryToken right = this.ParseUnary();
                left = new BinaryOperatorQueryToken(binaryOperatorKind, left, right);
            }

            this.RecurseLeave();
            return(left);
        }
Esempio n. 3
0
        /// <summary>
        /// Write the binary token as URI part to this builder.
        /// </summary>
        /// <param name="binary">To write as URI part.</param>
        protected virtual void WriteBinary(BinaryOperatorQueryToken binary)
        {
            ExceptionUtils.CheckArgumentNotNull(binary, "binary");

            BinaryOperatorUriBuilder writer = new BinaryOperatorUriBuilder(this);

            writer.Write(binary);
        }
        /// <summary>
        /// Parses the eq, ne, lt, gt, le, ge operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseComparison()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseAdditive();

            while (this.lexer.CurrentToken.IsComparisonOperator)
            {
                BinaryOperatorKind binaryOperatorKind;
                switch (this.lexer.CurrentToken.Text)
                {
                case ExpressionConstants.KeywordEqual:
                    binaryOperatorKind = BinaryOperatorKind.Equal;
                    break;

                case ExpressionConstants.KeywordNotEqual:
                    binaryOperatorKind = BinaryOperatorKind.NotEqual;
                    break;

                case ExpressionConstants.KeywordGreaterThan:
                    binaryOperatorKind = BinaryOperatorKind.GreaterThan;
                    break;

                case ExpressionConstants.KeywordGreaterThanOrEqual:
                    binaryOperatorKind = BinaryOperatorKind.GreaterThanOrEqual;
                    break;

                case ExpressionConstants.KeywordLessThan:
                    binaryOperatorKind = BinaryOperatorKind.LessThan;
                    break;

                case ExpressionConstants.KeywordLessThanOrEqual:
                    binaryOperatorKind = BinaryOperatorKind.LessThanOrEqual;
                    break;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.UriQueryExpressionParser_ParseComparison));
                }

                this.lexer.NextToken();
                QueryToken right = this.ParseAdditive();
                left = new BinaryOperatorQueryToken()
                {
                    OperatorKind = binaryOperatorKind,
                    Left         = left,
                    Right        = right
                };
            }

            this.RecurseLeave();
            return(left);
        }
Esempio n. 5
0
        /// <summary>
        /// Parses the and operator.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseLogicalAnd()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseComparison();

            while (this.TokenIdentifierIs(ExpressionConstants.KeywordAnd))
            {
                this.lexer.NextToken();
                QueryToken right = this.ParseComparison();
                left = new BinaryOperatorQueryToken(BinaryOperatorKind.And, left, right);
            }

            this.RecurseLeave();
            return(left);
        }
        /// <summary>
        /// Determine whether parentheses are needed around the right subtree base on the current operator.
        /// </summary>
        /// <param name="currentOperator">The current binary node's operator.</param>
        /// <param name="rightSubtree">The right binary subtree.</param>
        /// <returns>True if need parentheses, false if not.</returns>
        private static bool NeedParenthesesRight(BinaryOperator currentOperator, BinaryOperatorQueryToken rightSubtree)
        {
            BinaryOperator rightOperator = BinaryOperator.GetOperator(rightSubtree.OperatorKind);
            if (currentOperator.Precedence < rightOperator.Precedence)
            {
                return false;
            }

            if (currentOperator.Precedence > rightOperator.Precedence)
            {
                return true;
            }

            // They are equal in precedence, 
            return currentOperator.NeedParenEvenWhenTheSame;
        }
        /// <summary>
        /// Determine whether parentheses are needed around the right subtree base on the current operator.
        /// </summary>
        /// <param name="currentOperator">The current binary node's operator.</param>
        /// <param name="rightSubtree">The right binary subtree.</param>
        /// <returns>True if need parentheses, false if not.</returns>
        private static bool NeedParenthesesRight(BinaryOperator currentOperator, BinaryOperatorQueryToken rightSubtree)
        {
            BinaryOperator rightOperator = BinaryOperator.GetOperator(rightSubtree.OperatorKind);

            if (currentOperator.Precedence < rightOperator.Precedence)
            {
                return(false);
            }

            if (currentOperator.Precedence > rightOperator.Precedence)
            {
                return(true);
            }

            // They are equal in precedence,
            return(currentOperator.NeedParenEvenWhenTheSame);
        }
        private void Write(bool needParenthesis, BinaryOperatorQueryToken binary)
        {
            if (needParenthesis)
            {
                this.builder.Append(ExpressionConstants.SymbolOpenParen);
            }

            BinaryOperator currentOperator = BinaryOperator.GetOperator(binary.OperatorKind);

            // Left binary expression may need paren depending on their operator
            BinaryOperatorQueryToken leftBinaryExpr = binary.Left as BinaryOperatorQueryToken;

            if (leftBinaryExpr != null)
            {
                Write(NeedParenthesesLeft(currentOperator, leftBinaryExpr), leftBinaryExpr);
            }
            else
            {
                this.builder.WriteQuery(binary.Left);
            }

            this.builder.Append(ExpressionConstants.SymbolEscapedSpace);
            this.builder.Append(currentOperator.Text);
            this.builder.Append(ExpressionConstants.SymbolEscapedSpace);

            // Right binary expression may need paren depending on their operator
            BinaryOperatorQueryToken rightBinaryExpr = binary.Right as BinaryOperatorQueryToken;

            if (rightBinaryExpr != null)
            {
                Write(NeedParenthesesRight(currentOperator, rightBinaryExpr), rightBinaryExpr);
            }
            else
            {
                this.builder.WriteQuery(binary.Right);
            }

            if (needParenthesis)
            {
                this.builder.Append(ExpressionConstants.SymbolClosedParen);
            }
        }
        /// <summary>
        /// Parses the or operator.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseLogicalOr()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseLogicalAnd();

            while (this.TokenIdentifierIs(ExpressionConstants.KeywordOr))
            {
                this.lexer.NextToken();
                QueryToken right = this.ParseLogicalAnd();
                left = new BinaryOperatorQueryToken()
                {
                    OperatorKind = BinaryOperatorKind.Or,
                    Left         = left,
                    Right        = right
                };
            }

            this.RecurseLeave();
            return(left);
        }
Esempio n. 10
0
        /// <summary>
        /// Binds a binary operator token.
        /// </summary>
        /// <param name="binaryOperatorToken">The binary operator token to bind.</param>
        /// <returns>The bound binary operator token.</returns>
        protected virtual QueryNode BindBinaryOperator(BinaryOperatorQueryToken binaryOperatorToken)
        {
            ExceptionUtils.CheckArgumentNotNull(binaryOperatorToken, "binaryOperatorToken");

            SingleValueQueryNode left = this.Bind(binaryOperatorToken.Left) as SingleValueQueryNode;
            if (left == null)
            {
                throw new ODataException(Strings.MetadataBinder_BinaryOperatorOperandNotSingleValue(binaryOperatorToken.OperatorKind.ToString()));
            }

            SingleValueQueryNode right = this.Bind(binaryOperatorToken.Right) as SingleValueQueryNode;
            if (right == null)
            {
                throw new ODataException(Strings.MetadataBinder_BinaryOperatorOperandNotSingleValue(binaryOperatorToken.OperatorKind.ToString()));
            }

            IEdmTypeReference leftType = left.TypeReference;
            IEdmTypeReference rightType = right.TypeReference;
            if (!TypePromotionUtils.PromoteOperandTypes(binaryOperatorToken.OperatorKind, ref leftType, ref rightType))
            {
                string leftTypeName = left.TypeReference == null ? "<null>" : left.TypeReference.ODataFullName();
                string rightTypeName = right.TypeReference == null ? "<null>" : right.TypeReference.ODataFullName();
                throw new ODataException(Strings.MetadataBinder_IncompatibleOperandsError(leftTypeName, rightTypeName, binaryOperatorToken.OperatorKind));
            }

            if (leftType != null)
            {
                left = ConvertToType(left, leftType);
            }

            if (rightType != null)
            {
                right = ConvertToType(right, rightType);
            }

            return new BinaryOperatorQueryNode()
            {
                OperatorKind = binaryOperatorToken.OperatorKind,
                Left = left,
                Right = right
            };
        }
        /// <summary>
        /// Parses the or operator.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseLogicalOr()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseLogicalAnd();
            while (this.TokenIdentifierIs(ExpressionConstants.KeywordOr))
            {
                this.lexer.NextToken();
                QueryToken right = this.ParseLogicalAnd();
                left = new BinaryOperatorQueryToken(BinaryOperatorKind.Or, left, right);
            }

            this.RecurseLeave();
            return left;
        }
        private void Write(bool needParenthesis, BinaryOperatorQueryToken binary)
        {
            if (needParenthesis)
            {
                this.builder.Append(ExpressionConstants.SymbolOpenParen);
            }

            BinaryOperator currentOperator = BinaryOperator.GetOperator(binary.OperatorKind);

            // Left binary expression may need paren depending on their operator
            BinaryOperatorQueryToken leftBinaryExpr = binary.Left as BinaryOperatorQueryToken;
            if (leftBinaryExpr != null)
            {
                Write(NeedParenthesesLeft(currentOperator, leftBinaryExpr), leftBinaryExpr);
            }
            else
            {
                this.builder.WriteQuery(binary.Left);
            }

            this.builder.Append(ExpressionConstants.SymbolEscapedSpace);
            this.builder.Append(currentOperator.Text);
            this.builder.Append(ExpressionConstants.SymbolEscapedSpace);

            // Right binary expression may need paren depending on their operator
            BinaryOperatorQueryToken rightBinaryExpr = binary.Right as BinaryOperatorQueryToken;
            if (rightBinaryExpr != null)
            {
                Write(NeedParenthesesRight(currentOperator, rightBinaryExpr), rightBinaryExpr);
            }
            else
            {
                this.builder.WriteQuery(binary.Right);
            }

            if (needParenthesis)
            {
                this.builder.Append(ExpressionConstants.SymbolClosedParen);
            }
        }
 /// <summary>
 /// Write the given binary token as Uri part.
 /// </summary>
 /// <param name="binary">To write as Uri part.</param>
 public void Write(BinaryOperatorQueryToken binary)
 {
     Write(false, binary);
 }
 /// <summary>
 /// Determine whether parentheses are needed around the left subtree base on the current operator.
 /// </summary>
 /// <param name="currentOperator">The current binary node's operator.</param>
 /// <param name="leftSubtree">The left binary subtree.</param>
 /// <returns>True if need parenthese, false if not.</returns>
 private static bool NeedParenthesesLeft(BinaryOperator currentOperator, BinaryOperatorQueryToken leftSubtree)
 {
     BinaryOperator leftOperator = BinaryOperator.GetOperator(leftSubtree.OperatorKind);
     return leftOperator.Precedence < currentOperator.Precedence;
 }
        /// <summary>
        /// Parses the and operator.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseLogicalAnd()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseComparison();
            while (this.TokenIdentifierIs(ExpressionConstants.KeywordAnd))
            {
                this.lexer.NextToken();
                QueryToken right = this.ParseComparison();
                left = new BinaryOperatorQueryToken()
                {
                    OperatorKind = BinaryOperatorKind.And,
                    Left = left,
                    Right = right
                };
            }

            this.RecurseLeave();
            return left;
        }
Esempio n. 16
0
        /// <summary>
        /// Write the binary token as URI part to this builder.
        /// </summary>
        /// <param name="binary">To write as URI part.</param>
        protected virtual void WriteBinary(BinaryOperatorQueryToken binary)
        {
            ExceptionUtils.CheckArgumentNotNull(binary, "binary");

            BinaryOperatorUriBuilder writer = new BinaryOperatorUriBuilder(this);
            writer.Write(binary);
        }
        /// <summary>
        /// Parses the eq, ne, lt, gt, le, ge operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseComparison()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseAdditive();
            while (this.lexer.CurrentToken.IsComparisonOperator)
            {
                BinaryOperatorKind binaryOperatorKind;
                switch (this.lexer.CurrentToken.Text)
                {
                    case ExpressionConstants.KeywordEqual:
                        binaryOperatorKind = BinaryOperatorKind.Equal;
                        break;
                    case ExpressionConstants.KeywordNotEqual:
                        binaryOperatorKind = BinaryOperatorKind.NotEqual;
                        break;
                    case ExpressionConstants.KeywordGreaterThan:
                        binaryOperatorKind = BinaryOperatorKind.GreaterThan;
                        break;
                    case ExpressionConstants.KeywordGreaterThanOrEqual:
                        binaryOperatorKind = BinaryOperatorKind.GreaterThanOrEqual;
                        break;
                    case ExpressionConstants.KeywordLessThan:
                        binaryOperatorKind = BinaryOperatorKind.LessThan;
                        break;
                    case ExpressionConstants.KeywordLessThanOrEqual:
                        binaryOperatorKind = BinaryOperatorKind.LessThanOrEqual;
                        break;
                    default:
                        throw new ODataException(Strings.General_InternalError(InternalErrorCodes.UriQueryExpressionParser_ParseComparison));
                }

                this.lexer.NextToken();
                QueryToken right = this.ParseAdditive();
                left = new BinaryOperatorQueryToken()
                {
                    OperatorKind = binaryOperatorKind,
                    Left = left,
                    Right = right
                };
            }

            this.RecurseLeave();
            return left;
        }
        /// <summary>
        /// Parses the add, sub operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseAdditive()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseMultiplicative();
            while (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordAdd) ||
                this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordSub))
            {
                BinaryOperatorKind binaryOperatorKind;
                if (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordAdd))
                {
                    binaryOperatorKind = BinaryOperatorKind.Add;
                }
                else
                {
                    Debug.Assert(this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordSub), "Was a new binary operator added?");
                    binaryOperatorKind = BinaryOperatorKind.Subtract;
                }

                this.lexer.NextToken();
                QueryToken right = this.ParseMultiplicative();
                left = new BinaryOperatorQueryToken()
                {
                    OperatorKind = binaryOperatorKind,
                    Left = left,
                    Right = right
                };
            }

            this.RecurseLeave();
            return left;
        }
        /// <summary>
        /// Parses the mul, div, mod operators.
        /// </summary>
        /// <returns>The lexical token representing the expression.</returns>
        private QueryToken ParseMultiplicative()
        {
            this.RecurseEnter();
            QueryToken left = this.ParseUnary();
            while (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordMultiply) ||
                this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordDivide) ||
                this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordModulo))
            {
                BinaryOperatorKind binaryOperatorKind;
                if (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordMultiply))
                {
                    binaryOperatorKind = BinaryOperatorKind.Multiply;
                }
                else if (this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordDivide))
                {
                    binaryOperatorKind = BinaryOperatorKind.Divide;
                }
                else
                {
                    Debug.Assert(this.lexer.CurrentToken.IdentifierIs(ExpressionConstants.KeywordModulo), "Was a new binary operator added?");
                    binaryOperatorKind = BinaryOperatorKind.Modulo;
                }

                this.lexer.NextToken();
                QueryToken right = this.ParseUnary();
                left = new BinaryOperatorQueryToken()
                {
                    OperatorKind = binaryOperatorKind,
                    Left = left,
                    Right = right
                };
            }

            this.RecurseLeave();
            return left;
        }
 /// <summary>
 /// Write the given binary token as Uri part.
 /// </summary>
 /// <param name="binary">To write as Uri part.</param>
 public void Write(BinaryOperatorQueryToken binary)
 {
     Write(false, binary);
 }
        /// <summary>
        /// Determine whether parentheses are needed around the left subtree base on the current operator.
        /// </summary>
        /// <param name="currentOperator">The current binary node's operator.</param>
        /// <param name="leftSubtree">The left binary subtree.</param>
        /// <returns>True if need parenthese, false if not.</returns>
        private static bool NeedParenthesesLeft(BinaryOperator currentOperator, BinaryOperatorQueryToken leftSubtree)
        {
            BinaryOperator leftOperator = BinaryOperator.GetOperator(leftSubtree.OperatorKind);

            return(leftOperator.Precedence < currentOperator.Precedence);
        }