Пример #1
0
 /**
  * Flattens the tree by pushing down the field name. For example, if the tree looks like this:
  *
  * <pre>
  *                EQ
  *             /      \
  *        VALUE         EQ
  *        /    \      /    \
  *      TEXT  field GLOBAL (N)
  * </pre>
  *
  * Then we will output tree that looks like this:
  *
  * <pre>
  *                EQ
  *             /      \
  *        VALUE       (N)
  *        /    \
  *      TEXT  field
  * </pre>
  *
  * Here <code>(N)</code> is an arbitrary node. We also drop EQ if it is in front of conjunction or
  * disjunction. We do not drop it for other comparators, as we want parsing to fail for foo &lt;
  * (1 2).
  */
 private static Tree flatten(Tree tree, Tree restriction) throws QueryTreeException {
   if (tree.getType() == QueryLexer.VALUE) {
     return tree;
   }
   if (tree.getType() == QueryLexer.HAS || tree.getType() == QueryLexer.EQ) {
     Tree lhs = tree.getChild(0);
     if (lhs.getType() == QueryLexer.VALUE) {
       String myField = lhs.getChild(1).getText();
       if (restriction == null) {
         restriction = lhs;
       } else {
         String otherField = restriction.getChild(1).getText();
         if (!myField.equals(otherField)) {
           throw new QueryTreeException(
               String.format("Restriction on %s and %s", otherField, myField),
               lhs.getChild(1).getCharPositionInLine());
         }
       }
     }
     Tree rhs = tree.getChild(1);
     Tree flattened = flatten(rhs, restriction);
     if (flattened.getType() == QueryLexer.HAS
         || flattened.getType() == QueryLexer.EQ
         || flattened.getType() == QueryLexer.CONJUNCTION
         || flattened.getType() == QueryLexer.DISJUNCTION
         || flattened.getType() == QueryLexer.SEQUENCE) {
       return flattened;
     }
     if (flattened != rhs) {
       tree.setChild(1, flattened);
     }
     if (restriction != lhs) {
       tree.setChild(0, restriction);
     }
     return tree;
   }
   for (int i = 0; i < tree.getChildCount(); ++i) {
     Tree original = tree.getChild(i);
     Tree flattened = flatten(tree.getChild(i), restriction);
     if (original != flattened) {
       tree.setChild(i, flattened);
     }
   }
   return tree;
 }
Пример #2
0
 public static Tree simplify(Tree tree) {
   for (int i = 0; i < tree.getChildCount(); ++i) {
     Tree child = tree.getChild(i);
     Tree optimized = simplify(child);
     if (child != optimized) {
       tree.setChild(i, optimized);
     }
   }
   switch (tree.getType()) {
     case QueryLexer.CONJUNCTION:
     case QueryLexer.DISJUNCTION:
     case QueryLexer.SEQUENCE:
       if (tree.getChildCount() == 1) {
         return tree.getChild(0);
       }
       break;
   }
   return tree;
 }