@Override
  public void setUnknownTokenBoundaries() {
    Deque<ASTNode> stack1 = new ArrayDeque<ASTNode>();
    Deque<ASTNode> stack2 = new ArrayDeque<ASTNode>();
    stack1.push(this);

    while (!stack1.isEmpty()) {
      ASTNode next = stack1.pop();
      stack2.push(next);

      if (next.children != null) {
        for (int i = next.children.size() - 1; i >= 0 ; i--) {
          stack1.push((ASTNode)next.children.get(i));
        }
      }
    }

    while (!stack2.isEmpty()) {
      ASTNode next = stack2.pop();

      if (next.children == null) {
        if (next.startIndex < 0 || next.stopIndex < 0) {
          next.startIndex = next.stopIndex = next.token.getTokenIndex();
        }
      } else if (next.startIndex >= 0 && next.stopIndex >= 0) {
        continue;
      } else if (next.children.size() > 0) {
        ASTNode firstChild = (ASTNode)next.children.get(0);
        ASTNode lastChild = (ASTNode)next.children.get(next.children.size()-1);
        next.startIndex = firstChild.getTokenStartIndex();
        next.stopIndex = lastChild.getTokenStopIndex();
      }
    }
  }
For every node in this subtree, make sure it's start/stop token's
are set.  Walk depth first, visit bottom up.  Only updates nodes
with at least one token index &lt; 0.

In contrast to the method in the parent class, this method is
iterative.
parser/src/java/org/apache/hadoop/hive/ql/parse/ASTNode.java