- 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); }
- }
- private static abstract class TreeMaker<T> implements Invokable<Forest.Body<T>,Boolean,Integer>, TreeConsumer<T> {
- public ArrayList<Tree<T>> toks = new ArrayList<Tree<T>>();
- private boolean toss;
- protected T head;
- public TreeMaker(boolean toss) { this.toss = toss; }
- public abstract void start(T head, Input.Location loc);
- public abstract void finish(T head, Input.Location loc);
- public abstract void addTree(Tree<T> t);
- public void invoke(Forest.Body<T> bod, Boolean o, Integer i) {
- if (i==null) {
- ArrayList<Tree<T>> toks = this.toks;
- this.toks = new ArrayList<Tree<T>>();
- bod.expand(0, this);
- this.toks = toks;
- } else {
- bod.expand(i, this);
- }
+ private void touched() {
+ if (touched) return;
+ touched = true;
+ /*
+ FastSet<Forest<NodeType>> f2 = new FastSet<Forest<NodeType>>();
+ for(Forest f : hp)
+ if (f instanceof Forest.One) f2.add(f);
+ else for(Forest ff : ((Forest.Many<NodeType>)f))
+ f2.add(ff);
+ hp = f2;
+ */
+ }
+ public boolean contains(Forest f) {
+ touched();
+ return hp.contains(f);
+ }
+ public void merge(Forest p) {
+ if (touched) throw new RuntimeException("attempt to merge() on a Forest.Many that has already been examined");
+ if (p==this) throw new RuntimeException("attempt to merge() a Forest.Many to itself!");
+ hp.add(p, true);
+ }
+ boolean ambiguous() {
+ touched();
+ if (hp.size()==0) return false;
+ if (hp.size()==1) return hp.iterator().next().ambiguous();
+ return true;
+ }
+
+ void expand(HashSet<Tree<NodeType>> ht, HashSet<Forest<NodeType>> ignore, Tree<NodeType> bogus) {
+ touched();
+ if (ignore.contains(this)) { ht.add(bogus); return; }
+ for (Forest<NodeType> f : hp) f.expand(ht, ignore, bogus);
+ }
+
+
+ // GraphViz, ToInt //////////////////////////////////////////////////////////////////////////////
+
+ public boolean isTransparent() { return hp.size()==1; }
+ public boolean isHidden() { return hp.size()==0; }
+ public void edges(GraphViz.Node n) {
+ if (hp.size()==1) { hp.iterator().next().edges(n); return; }
+ for(Forest f : hp) f.edges(n);
+ }
+ public GraphViz.Node toGraphViz(GraphViz gv) {
+ if (hp.size()==1) return hp.iterator().next().toGraphViz(gv);
+ if (gv.hasNode(this)) return gv.createNode(this);
+ GraphViz.Node n = gv.createNode(this);
+ n.label = "?";
+ n.color = "red";
+ for(Forest f : hp) n.edge(f, null);
+ return n;