public virtual void TestParsesMultiCorrectly() { Evaluator eval = QueryParser.Parse(".foo > ol, ol > li + li"); NUnit.Framework.Assert.IsTrue(eval is CombiningEvaluator.OR); CombiningEvaluator.OR or = (CombiningEvaluator.OR)eval; NUnit.Framework.Assert.AreEqual(2, or.evaluators.Count); CombiningEvaluator.And andLeft = (CombiningEvaluator.And)or.evaluators[0]; CombiningEvaluator.And andRight = (CombiningEvaluator.And)or.evaluators[1]; NUnit.Framework.Assert.AreEqual("ol :ImmediateParent.foo", andLeft.ToString()); NUnit.Framework.Assert.AreEqual(2, andLeft.evaluators.Count); NUnit.Framework.Assert.AreEqual("li :prevli :ImmediateParentol", andRight.ToString()); NUnit.Framework.Assert.AreEqual(2, andLeft.evaluators.Count); }
public virtual void TestOrGetsCorrectPrecedence() { // tests that a selector "a b, c d, e f" evals to (a AND b) OR (c AND d) OR (e AND f)" // top level or, three child ands Evaluator eval = QueryParser.Parse("a b, c d, e f"); NUnit.Framework.Assert.IsTrue(eval is CombiningEvaluator.OR); CombiningEvaluator.OR or = (CombiningEvaluator.OR)eval; NUnit.Framework.Assert.AreEqual(3, or.evaluators.Count); foreach (Evaluator innerEval in or.evaluators) { NUnit.Framework.Assert.IsTrue(innerEval is CombiningEvaluator.And); CombiningEvaluator.And and = (CombiningEvaluator.And)innerEval; NUnit.Framework.Assert.AreEqual(2, and.evaluators.Count); NUnit.Framework.Assert.IsTrue(and.evaluators[0] is Evaluator.Tag); NUnit.Framework.Assert.IsTrue(and.evaluators[1] is StructuralEvaluator.Parent); } }
private void Combinator(char combinator) { tq.ConsumeWhitespace(); String subQuery = ConsumeSubQuery(); // support multi > childs Evaluator rootEval; // the new topmost evaluator Evaluator currentEval; // the evaluator the new eval will be combined to. could be root, or rightmost or. Evaluator newEval = Parse(subQuery); // the evaluator to add into target evaluator bool replaceRightMost = false; if (evals.Count == 1) { rootEval = currentEval = evals[0]; // make sure OR (,) has precedence: if (rootEval is CombiningEvaluator.OR && combinator != ',') { currentEval = ((CombiningEvaluator.OR)currentEval).RightMostEvaluator(); replaceRightMost = true; } } else { rootEval = currentEval = new CombiningEvaluator.And(evals); } evals.Clear(); // for most combinators: change the current eval into an AND of the current eval and the new eval if (combinator == '>') { currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.ImmediateParent(currentEval)); } else { if (combinator == ' ') { currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.Parent(currentEval)); } else { if (combinator == '+') { currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.ImmediatePreviousSibling(currentEval )); } else { if (combinator == '~') { currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.PreviousSibling(currentEval)); } else { if (combinator == ',') { // group or. CombiningEvaluator.OR or; if (currentEval is CombiningEvaluator.OR) { or = (CombiningEvaluator.OR)currentEval; or.Add(newEval); } else { or = new CombiningEvaluator.OR(); or.Add(currentEval); or.Add(newEval); } currentEval = or; } else { throw new Selector.SelectorParseException("Unknown combinator: " + combinator); } } } } } if (replaceRightMost) { ((CombiningEvaluator.OR)rootEval).ReplaceRightMostEvaluator(currentEval); } else { rootEval = currentEval; } evals.Add(rootEval); }