-
- // Display //////////////////////////////////////////////////////////////////////////////
-
- private String toString = null;
- public String toString() {
- if (toString != null) return toString;
- StringBuffer ret = new StringBuffer();
- if (results.size()==1) {
- for(Forest.Body<T> r : results)
- ret.append(r);
- return toString = ret.toString();
+
+
+ // GraphViz, ToInt //////////////////////////////////////////////////////////////////////////////
+
+ public boolean isTransparent() { return hp.size()==1; }
+ public boolean isHidden() { return hp.size()==0; }
+ public void edges(GraphViz.StateNode n) {
+ if (hp.size()==1) { hp.iterator().next().edges(n); return; }
+ for(Forest f : hp) f.edges(n);
+ }
+ public GraphViz.StateNode toGraphViz(GraphViz gv) {
+ if (hp.size()==1) return hp.iterator().next().toGraphViz(gv);
+ if (gv.hasNode(this)) return gv.createNode(this);
+ GraphViz.StateNode n = gv.createNode(this);
+ n.label = "?";
+ n.color = "red";
+ for(Forest f : hp) n.edge(f, null);
+ return n;
+ }
+ }
+
+
+ // 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();