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