- public abstract <B,C> void visit(Invokable<Forest.Body<T>,B,C> ivbc, B b, C c);
- private static class TreeMaker2<T> extends TreeMaker<T> {
- private TreeConsumer<T> tc;
- public TreeMaker2(boolean toss, TreeConsumer<T> tc) { super(toss); this.tc = tc; }
- public void finish(T head, Input.Location loc) { tc.addTree(new Tree<T>(loc, head, toks.toArray(tree_hint)));; }
- public void start(T head, Input.Location loc) { }
- public void addTree(Tree<T> t) { toks.add(t); }
+
+ // Statics //////////////////////////////////////////////////////////////////////////////
+
+ /** Depth-first expansion, handling .One and .Many without recursion. */
+ private static <NodeType> Tree<NodeType> expand1ForOneAndMany(
+ Forest<NodeType> forest) throws Ambiguous {
+ List<Tree<NodeType>> nodes = new ArrayList<Tree<NodeType>>();
+ List<Tree<NodeType>> build = new ArrayList<Tree<NodeType>>();
+
+ // path stack
+ List<Forest.One<NodeType>> path = new ArrayList<Forest.One<NodeType>>();
+ List<Integer> sizes = new ArrayList<Integer>(),
+ poss = new ArrayList<Integer>();
+
+ // handle the left-most leaf
+ expand1Descend(path, nodes, sizes, poss, forest);
+
+ for (Forest.One<NodeType> f; path.size() > 0;) {
+ // up one
+ f = pop(path);
+ int size = pop(sizes) + 1;
+ int pos = pop(poss) + 1;
+ Forest<NodeType>[] children = f.children;
+ if (pos < children.length) {
+ // down the next branch
+ path.add(f);
+ sizes.add(new Integer(size));
+ poss.add(new Integer(pos));
+
+ // handle the left-most leaf
+ expand1Descend(path, nodes, sizes, poss, children[pos]);
+ } else {
+ if (path.size() > 0 && peek(path).lifts[peek(poss)]) {
+ // skip assembling this node, lift children
+ sizes.add(pop(sizes) + size - 1);
+ continue;
+ }
+ // assemble this node
+ for (int i=size; i > 0; i--)
+ build.add(nodes.remove(nodes.size() - i));
+ nodes.add(new Tree<NodeType>(f.location, f.head, build));
+ build.clear();
+ }
+ }
+
+ return pop(nodes);