static {
   Precedence[] values = Precedence.values();
   for (Precedence precedence : values) {
     int ordinal = precedence.ordinal();
     precedence.higher = ordinal > 0 ? values[ordinal - 1] : null;
   }
 }
 static {
   Set<IElementType> operations = new HashSet<IElementType>();
   Precedence[] values = Precedence.values();
   for (Precedence precedence : values) {
     operations.addAll(Arrays.asList(precedence.getOperations().getTypes()));
   }
   ALL_OPERATIONS = TokenSet.create(operations.toArray(new IElementType[operations.size()]));
 }
  /**
   * Return true if the passed in node or any of its up-stream (higher index siblings have
   * moveAllowed="false".
   */
  private static boolean isNotReparentable(NodeInfo ni) {
    if (ni.node.getAttribute(Constants.ATT_MOVE_ALLOWED).equals("false")) return true;

    Precedence nodePrec = ni.precedence;
    Element node = (Element) ni.node.getNextSibling();

    while (node != null) {
      if (node.getAttribute(Constants.ATT_MOVE_ALLOWED).equals("false")) {
        Precedence p = Precedence.newInstance(node.getAttribute(Constants.ATT_FRAGMENT));
        if (nodePrec.isEqualTo(p)) return true;
      }
      node = (Element) node.getNextSibling();
    }
    return false;
  }
  /*
   * element (operation element)*
   *
   * see the precedence table
   */
  private void parseBinaryExpression(Precedence precedence) {
    //        System.out.println(precedence.name() + " at " + myBuilder.getTokenText());

    PsiBuilder.Marker expression = mark();

    precedence.parseHigherPrecedence(this);

    while (!interruptedWithNewLine() && atSet(precedence.getOperations())) {
      IElementType operation = tt();

      parseOperationReference();

      JetNodeType resultType = precedence.parseRightHandSide(operation, this);
      expression.done(resultType);
      expression = expression.precede();
    }

    expression.drop();
  }
  /**
   * This method determines if any illegal hopping is being specified. To determine if the
   * positioning is specifying an ordering that will result in hopping I need to determine for each
   * node n in the list if any of the nodes to be positioned to its right currently lie to its left
   * in the CVP and have moveAllowed="false" and have the same precedence or if any of the nodes to
   * be positioned to its left currently lie to its right in the CVP and have moveAllowed="false"
   * and have the same precedence.
   */
  static boolean isIllegalHoppingSpecified(List<NodeInfo> order) {
    for (int i = 0; i < order.size(); i++) {
      NodeInfo ni = (NodeInfo) order.get(i);

      // look for move restricted nodes
      if (!ni.node.getAttribute(Constants.ATT_MOVE_ALLOWED).equals("false")) continue;

      // now check nodes in lower position to see if they "hopped" here
      // or if they have similar precedence and came from another parent.

      for (int j = 0; j < i; j++) {
        NodeInfo niSib = (NodeInfo) order.get(j);

        // skip lower precedence nodes from this parent. These will get
        // bumped during the lower precedence check
        if (niSib.precedence == Precedence.getUserPrecedence()) continue;

        if (niSib.precedence.isEqualTo(ni.precedence)
            && (niSib.indexInCVP == -1
                || // from another parent
                ni.indexInCVP < niSib.indexInCVP)) // niSib hopping left
        return true;
      }

      // now check upper positioned nodes to see if they "hopped"

      for (int j = i + 1; j < order.size(); j++) {
        NodeInfo niSib = (NodeInfo) order.get(j);

        // ignore nodes from other parents and user precedence nodes
        if (niSib.indexInCVP == -1 || niSib.precedence == Precedence.getUserPrecedence()) continue;

        if (ni.indexInCVP > niSib.indexInCVP
            && // niSib hopped right
            niSib.precedence.isEqualTo(ni.precedence)) return true;
      }
    }
    return false;
  }