private void AddOperator(BinaryOperatorToken token) { while (_operatorStack.Count > 0) { var currentPrecedence = _operatorStack.Peek().Precedence; if (token.Precedence > currentPrecedence || (token.Associativity == BinaryOperatorToken.AssociativityTypes.Right && token.Precedence == currentPrecedence)) break; EvaluateOperator(); } _operatorStack.Push(token); }
public void BinaryOperatorQueryTokenDefaultTest() { LiteralToken left = new LiteralToken(null); LiteralToken right = new LiteralToken(null); BinaryOperatorToken binary = new BinaryOperatorToken(BinaryOperatorKind.Or, left, right); this.Assert.AreEqual(QueryTokenKind.BinaryOperator, binary.Kind, "The InternalKind property has an unexpected value."); this.Assert.AreEqual(BinaryOperatorKind.Or, binary.OperatorKind, "The OperatorKind property should be Or."); this.Assert.AreEqual(left, binary.Left, "The Left property has an unexpected value."); this.Assert.AreEqual(right, binary.Right, "The Right property has an unexpected value."); }
/// <summary> /// Binds a binary operator token. /// </summary> /// <param name="binaryOperatorToken">The binary operator token to bind.</param> /// <returns>The bound binary operator token.</returns> internal QueryNode BindBinaryOperator(BinaryOperatorToken binaryOperatorToken) { ExceptionUtils.CheckArgumentNotNull(binaryOperatorToken, "binaryOperatorToken"); SingleValueNode left = this.GetOperandFromToken(binaryOperatorToken.OperatorKind, binaryOperatorToken.Left); SingleValueNode right = this.GetOperandFromToken(binaryOperatorToken.OperatorKind, binaryOperatorToken.Right); IEdmTypeReference typeReference; this.resolver.PromoteBinaryOperandTypes(binaryOperatorToken.OperatorKind, ref left, ref right, out typeReference); return new BinaryOperatorNode(binaryOperatorToken.OperatorKind, left, right, typeReference); }
public void OrOperatorShouldResultInBinaryOperatorNode() { this.leftParameterSingleValueQueryNode = new ConstantNode(false); this.rightParameterSingleValueQueryNode = new ConstantNode(true); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Or, new LiteralToken(false), new LiteralToken(true)); var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.Or).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Boolean); resultNode.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(false); resultNode.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(true); }
public void AndOperatorCompatibleTypeShouldResultInBinaryOperatorNode() { this.leftParameterSingleValueQueryNode = new UnaryOperatorNode(UnaryOperatorKind.Negate, new UnaryOperatorNode(UnaryOperatorKind.Not, new ConstantNode(null))); this.rightParameterSingleValueQueryNode = new SingleValueFunctionCallNode("func", null, EdmCoreModel.Instance.GetBoolean(false)); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar")); var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.And).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Boolean); resultNode.As<BinaryOperatorNode>().Left.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean); resultNode.As<BinaryOperatorNode>().Right.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean); }
public void GreaterThanOrEqualOperatorShouldResultInBinaryOperatorNode() { this.leftParameterSingleValueQueryNode = new ConstantNode(99); this.rightParameterSingleValueQueryNode = new ConstantNode(99.1); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.GreaterThanOrEqual, new LiteralToken("foo"), new LiteralToken("bar")); var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.GreaterThanOrEqual).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Boolean); resultNode.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(99d); resultNode.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(99.1); }
public void AndOperatorNullAndOpenPropertyShouldResultInBinaryOperatorNodeWithNullType() { this.leftParameterSingleValueQueryNode = new ConstantNode(null); this.rightParameterSingleValueQueryNode = new SingleValueOpenPropertyAccessNode(new ConstantNode(null), OpenPropertyName); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar")); var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); var binaryNode = resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.And).And; binaryNode.TypeReference.Should().BeNull(); binaryNode.Left.ShouldBeConstantQueryNode<object>(null); binaryNode.Right.ShouldBeSingleValueOpenPropertyAccessQueryNode(OpenPropertyName); }
private static void VerifyBinaryOperatorQueryTokensAreEqual(BinaryOperatorToken expected, BinaryOperatorToken actual, AssertionHandler assert) { assert.AreEqual(expected.OperatorKind, actual.OperatorKind, "The binary operator kind doesn't match the expected one."); VerifyQueryTokensAreEqual(expected.Left, actual.Left, assert); VerifyQueryTokensAreEqual(expected.Right, actual.Right, assert); }
/// <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.SearchKeywordOr)) { this.lexer.NextToken(); QueryToken right = this.ParseLogicalAnd(); left = new BinaryOperatorToken(BinaryOperatorKind.Or, left, 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.ParseUnary(); while (this.TokenIdentifierIs(ExpressionConstants.SearchKeywordAnd) || this.TokenIdentifierIs(ExpressionConstants.SearchKeywordNot) || this.lexer.CurrentToken.Kind == ExpressionTokenKind.StringLiteral || this.lexer.CurrentToken.Kind == ExpressionTokenKind.OpenParen) { // Handle A NOT B, A (B) // Bypass only when next token is AND if (this.TokenIdentifierIs(ExpressionConstants.SearchKeywordAnd)) { this.lexer.NextToken(); } QueryToken right = this.ParseUnary(); left = new BinaryOperatorToken(BinaryOperatorKind.And, left, 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(BinaryOperatorToken binaryOperatorToken) { BinaryOperatorBinder binaryOperatorBinder = new BinaryOperatorBinder(this.Bind, this.BindingState.Configuration.Resolver); return(binaryOperatorBinder.BindBinaryOperator(binaryOperatorToken)); }
/// <summary> /// Visits a BinaryOperatorToken /// </summary> /// <param name="tokenIn">The Binary operator token to visit.</param> /// <returns>A BinaryOperatorNode thats bound to this token</returns> public virtual T Visit(BinaryOperatorToken tokenIn) { throw new NotImplementedException(); }
public void LeftTokenTypeImcompatibleWithRightTokenShouldFail() { this.leftParameterSingleValueQueryNode = new ConstantNode(true); this.rightParameterSingleValueQueryNode = new ConstantNode(1); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Equal, new LiteralToken("foo"), new LiteralToken("bar")); Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); bind.ShouldThrow<ODataException>(). WithMessage((Strings.MetadataBinder_IncompatibleOperandsError("Edm.Boolean", "Edm.Int32", BinaryOperatorKind.Equal))); }
public void LeftTokenTypeIncompatibleWithOperatorAndRightTokenOpenPropertyShouldFail() { this.leftParameterSingleValueQueryNode = new ConstantNode(DateTimeOffset.Now); this.rightParameterSingleValueQueryNode = new SingleValueOpenPropertyAccessNode(new ConstantNode(null), "SomeProperty"); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar")); Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); bind.ShouldThrow<ODataException>(). WithMessage((Strings.MetadataBinder_IncompatibleOperandsError("Edm.DateTimeOffset", "<null>", BinaryOperatorKind.And))); }
/// <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(BinaryOperatorToken binaryOperatorToken) { BinaryOperatorBinder binaryOperatorBinder = new BinaryOperatorBinder(this.Bind, this.BindingState.Configuration.Resolver); return binaryOperatorBinder.BindBinaryOperator(binaryOperatorToken); }
/// <summary> /// Write the given binary token as Uri part. /// </summary> /// <param name="binary">To write as Uri part.</param> public void Write(BinaryOperatorToken binary) { Write(false, binary); }
/// <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(BinaryOperatorToken binaryOperatorToken) { BinaryOperatorBinder binaryOperatorBinder = new BinaryOperatorBinder(this.Bind); return(binaryOperatorBinder.BindBinaryOperator(binaryOperatorToken)); }
internal static bool TryEvaluateExpression(string text, out TokenBase token, bool requireReturnValue = true) { string temp = text; if (new NullCoalesceOperatorToken().TryGetToken(ref temp, out token)) { return(true); } temp = text; if (new TernaryOperatorToken().TryGetToken(ref temp, out token)) { return(true); } token = null; List <TokenBase> tokens = new List <TokenBase>(); List <Operator> operators = new List <Operator>(); while (operators.Count == tokens.Count) { if (tokens.Count != 0 && !requireReturnValue) { return(false); } TokenBase newToken; if (!TryGetValueToken(ref text, out newToken, requireReturnValue)) { return(false); } tokens.Add(newToken); text = text.TrimStart(); for (int i = (int)Operator.Multiply; i <= (int)Operator.BitwiseXor; ++i) { if (text.StartsWith(representations[i])) { operators.Add((Operator)i); text = text.Substring(representations[i].Length).TrimStart(); break; } } } if (!String.IsNullOrWhiteSpace(text)) { return(false); } while (tokens.Count > 1) { int lastPrecedence = 1000; int last = -1; for (int i = 0; i < operators.Count; ++i) { int precendence = precedenceLevel[(int)operators[i]]; if (precendence < lastPrecedence) { lastPrecedence = precendence; last = i; } else { break; } } tokens[last] = new BinaryOperatorToken(tokens[last], tokens[last + 1], operators[last]); tokens.RemoveAt(last + 1); operators.RemoveAt(last); } token = tokens[0]; return(true); }
private static void VerifyBinaryOperatorToken <T>(string expectedEndPathIdentifier, BinaryOperatorKind expectedOperator, T expectedLiteralValue, BinaryOperatorToken actual) { actual.Should().NotBeNull(); actual.OperatorKind.Should().Be(expectedOperator); EndPathToken left = actual.Left as EndPathToken; left.Should().NotBeNull(); left.Identifier.Should().Be(expectedEndPathIdentifier); LiteralToken right = actual.Right as LiteralToken; right.Should().NotBeNull(); right.Value.Should().Be(expectedLiteralValue); }
public void ModuloOperatorShouldResultInBinaryOperatorNode() { this.leftParameterSingleValueQueryNode = new ConstantNode(-9.9); this.rightParameterSingleValueQueryNode = new ConstantNode(-100.9); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Modulo, new LiteralToken("foo"), new LiteralToken("bar")); var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.Modulo).And.TypeReference.PrimitiveKind().Should().Be(EdmPrimitiveTypeKind.Double); resultNode.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(-9.9); resultNode.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(-100.9); }
public void CollectionRightTokenShouldFail() { this.binaryOperatorBinder = new BinaryOperatorBinder(this.BindMethodThatReturnsQueryNode, /*resolver*/ null); this.leftQueryNode = new ConstantNode("People"); this.rightQueryNode = new EntitySetNode(this.model.FindDeclaredEntitySet("People")); var binaryOperatorToken = new BinaryOperatorToken(BinaryOperatorKind.Equal, new LiteralToken("foo"), new LiteralToken("bar")); Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorToken); bind.ShouldThrow<ODataException>(). WithMessage((Strings.MetadataBinder_BinaryOperatorOperandNotSingleValue("Equal"))); }
/// <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, BinaryOperatorToken leftSubtree) { BinaryOperator leftOperator = BinaryOperator.GetOperator(leftSubtree.OperatorKind); return(leftOperator.Precedence < currentOperator.Precedence); }
public void RightTokenTypeImcompatibleWithOperatorShouldFail() { this.leftParameterSingleValueQueryNode = new ConstantNode(999); this.rightParameterSingleValueQueryNode = new ConstantNode(string.Empty); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.Multiply, new LiteralToken("foo"), new LiteralToken("bar")); Action bind = () => this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); bind.ShouldThrow<ODataException>(). WithMessage((Strings.MetadataBinder_IncompatibleOperandsError("Edm.Int32", "Edm.String", BinaryOperatorKind.Multiply))); }
/// <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 (true) { BinaryOperatorKind binaryOperatorKind; if (this.TokenIdentifierIs(ExpressionConstants.KeywordEqual)) { binaryOperatorKind = BinaryOperatorKind.Equal; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordNotEqual)) { binaryOperatorKind = BinaryOperatorKind.NotEqual; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordGreaterThan)) { binaryOperatorKind = BinaryOperatorKind.GreaterThan; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordGreaterThanOrEqual)) { binaryOperatorKind = BinaryOperatorKind.GreaterThanOrEqual; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordLessThan)) { binaryOperatorKind = BinaryOperatorKind.LessThan; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordLessThanOrEqual)) { binaryOperatorKind = BinaryOperatorKind.LessThanOrEqual; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordHas)) { binaryOperatorKind = BinaryOperatorKind.Has; } else { break; } this.lexer.NextToken(); QueryToken right = this.ParseAdditive(); left = new BinaryOperatorToken(binaryOperatorKind, left, 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.TokenIdentifierIs(ExpressionConstants.KeywordAdd) || this.TokenIdentifierIs(ExpressionConstants.KeywordSub)) { BinaryOperatorKind binaryOperatorKind; if (this.TokenIdentifierIs(ExpressionConstants.KeywordAdd)) { binaryOperatorKind = BinaryOperatorKind.Add; } else { Debug.Assert(this.TokenIdentifierIs(ExpressionConstants.KeywordSub), "Was a new binary operator added?"); binaryOperatorKind = BinaryOperatorKind.Subtract; } this.lexer.NextToken(); QueryToken right = this.ParseMultiplicative(); left = new BinaryOperatorToken(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.TokenIdentifierIs(ExpressionConstants.KeywordMultiply) || this.TokenIdentifierIs(ExpressionConstants.KeywordDivide) || this.TokenIdentifierIs(ExpressionConstants.KeywordModulo)) { BinaryOperatorKind binaryOperatorKind; if (this.TokenIdentifierIs(ExpressionConstants.KeywordMultiply)) { binaryOperatorKind = BinaryOperatorKind.Multiply; } else if (this.TokenIdentifierIs(ExpressionConstants.KeywordDivide)) { binaryOperatorKind = BinaryOperatorKind.Divide; } else { Debug.Assert(this.TokenIdentifierIs(ExpressionConstants.KeywordModulo), "Was a new binary operator added?"); binaryOperatorKind = BinaryOperatorKind.Modulo; } this.lexer.NextToken(); QueryToken right = this.ParseUnary(); left = new BinaryOperatorToken(binaryOperatorKind, left, right); } this.RecurseLeave(); return left; }
public void AndOperatorNullLiteralShouldResultInBinaryOperatorNodeWithConvert() { this.leftParameterSingleValueQueryNode = new ConstantNode(null); this.rightParameterSingleValueQueryNode = new SingleValueFunctionCallNode(FuncName, null, EdmCoreModel.Instance.GetBoolean(false)); var binaryOperatorQueryToken = new BinaryOperatorToken(BinaryOperatorKind.And, new LiteralToken("foo"), new LiteralToken("bar")); var resultNode = this.binaryOperatorBinder.BindBinaryOperator(binaryOperatorQueryToken); var binaryNode = resultNode.ShouldBeBinaryOperatorNode(BinaryOperatorKind.And).And; binaryNode.TypeReference.IsNullable.Should().BeTrue(); var left = binaryNode.Left.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean).And; left.TypeReference.IsNullable.Should().BeTrue(); left.Source.ShouldBeConstantQueryNode<object>(null); var right = binaryNode.Right.ShouldBeConvertQueryNode(EdmPrimitiveTypeKind.Boolean).And; right.TypeReference.IsNullable.Should().BeTrue(); right.Source.ShouldBeSingleValueFunctionCallQueryNode(FuncName); }
public bool Visit(BinaryOperatorToken tokenIn) { stringBuilder.Append('('); tokenIn.Left.Accept(this); stringBuilder.Append(' '); switch (tokenIn.OperatorKind) { case BinaryOperatorKind.Or: stringBuilder.Append("OR"); break; case BinaryOperatorKind.And: stringBuilder.Append("AND"); break; case BinaryOperatorKind.Equal: stringBuilder.Append("="); break; case BinaryOperatorKind.NotEqual: stringBuilder.Append("!="); break; case BinaryOperatorKind.GreaterThan: stringBuilder.Append(">"); break; case BinaryOperatorKind.GreaterThanOrEqual: stringBuilder.Append(">="); break; case BinaryOperatorKind.LessThan: stringBuilder.Append("<"); break; case BinaryOperatorKind.LessThanOrEqual: stringBuilder.Append("<="); break; case BinaryOperatorKind.Add: stringBuilder.Append("+"); break; case BinaryOperatorKind.Subtract: stringBuilder.Append("-"); break; case BinaryOperatorKind.Multiply: stringBuilder.Append("*"); break; case BinaryOperatorKind.Divide: stringBuilder.Append("/"); break; case BinaryOperatorKind.Modulo: stringBuilder.Append("%"); break; default: throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "QueryToken of type '{0}' is not supported.", tokenIn.OperatorKind)); } stringBuilder.Append(' '); EndPathToken endPathToken = tokenIn.Left as EndPathToken; if (endPathToken != null && endPathToken.Identifier.Equals("Timestamp") && enableTimestampQuery) { LiteralToken literalToken = tokenIn.Right as LiteralToken; stringBuilder.Append(SchemaUtil.GetTimestampEpochSecondString(literalToken.Value)); } else { tokenIn.Right.Accept(this); } stringBuilder.Append(')'); return(true); }