- public Ref() { }
- public void merge(Forest p) { if (p!=this) hp.add(p, true); }
- public <B,C> void invoke(Invokable<Forest.Body<T>,B,C> ivbc, B b, C c) {
- if (hp==null) return;
- for(Forest<T> f : hp) f.invoke(ivbc, b, c);
+ private boolean touched = false;
+
+ public Many() { }
+
+ public Iterator<One<T>> iterator() {
+ touched();
+ return (Iterator<One<T>>)hp.iterator(); // FIXME: fastset's iterator is not safe!
+ }
+
+ public Tree<T> expand1() throws Ambiguous {
+ touched();
+ if (hp.size() > 1) {
+ HashSet<Forest<T>> hf0 = new HashSet<Forest<T>>();
+ Iterator<Forest<T>> ih = hp.iterator();
+ ih.next().gather(hf0);
+ for(Forest<T> f : hp) {
+ HashSet<Forest<T>> hf1 = new HashSet<Forest<T>>();
+ f.gather(hf1);
+ hf0.retainAll(hf1);
+ }
+ HashSet<Tree<T>> ht = new HashSet<Tree<T>>();
+ expand(ht, hf0, new Tree(null, "*"));
+ throw new Ambiguous((Forest<?>)this,
+ (HashSet<Tree<?>>)(Object)ht);
+ }
+ return hp.iterator().next().expand1();
+ }
+
+ public void gather(HashSet<Forest<T>> ht) {
+ touched();
+ ht.add(this);
+ for(Forest<T> f : hp) f.gather(ht);
+ }
+
+ private void touched() {
+ if (touched) return;
+ touched = true;
+ FastSet<Forest<T>> f2 = new FastSet<Forest<T>>();
+ for(Forest f : hp)
+ if (f instanceof Forest.One) f2.add(f);
+ else for(Forest ff : ((Forest.Many)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;
+ }
+
+ public void expand(HashSet<Tree<T>> ht, HashSet<Forest<T>> ignore, Tree<T> bogus) {
+ touched();
+ if (ignore.contains(this)) { ht.add(bogus); return; }
+ for (Forest<T> f : hp) f.expand(ht, ignore, bogus);