checkpoint
[sbp.git] / src / edu / berkeley / sbp / Forest.java
1 package edu.berkeley.sbp;
2 import edu.berkeley.sbp.*;
3 import edu.berkeley.sbp.Sequence.Position;
4 import edu.berkeley.sbp.util.*;
5 import java.io.*;
6 import java.util.*;
7 import java.lang.reflect.*;
8
9 /** an efficient representation of a collection of trees (Tomita's shared packed parse forest) */
10 public abstract class Forest<T> /*extends PrintableTree<Forest.Body<T>>*/
11     implements IntegerMappable,
12                GraphViz.ToGraphViz {
13
14     private static int master_idx = 0;
15     private final int idx = master_idx++;
16     public int toInt() { return idx; }
17
18     /** assume that this forest contains exactly one tree and return it; otherwise throw an exception */
19     public abstract Tree<T> expand1() throws Ambiguous;
20
21     /** expand this forest into a set of trees */
22     public void expand(HashSet<Tree<T>> ht) { expand(ht, new HashSet<Forest<T>>(), null); }
23     public abstract void expand(HashSet<Tree<T>> ht, HashSet<Forest<T>> ignore, Tree<T> bogus);
24     public abstract void gather(HashSet<Forest<T>> ignore);
25     public HashSet<Tree<T>> expand(boolean toss) {
26         HashSet<Tree<T>> ret = new HashSet<Tree<T>>();
27         expand(ret);
28         return ret;
29     }
30
31     public static <T> Forest<T> create(Input.Region loc, T tag, Forest<T>[] tokens, boolean unwrap) {
32         return new Body<T>(loc, tag, tokens, unwrap);
33     }
34     public abstract void edges(GraphViz.Node n);
35     public boolean ambiguous() { return false; }
36
37     // Body //////////////////////////////////////////////////////////////////////////////
38
39     public /*protected*/ static class Body<T> extends Forest<T> /* extends PrintableTree<Forest<T>> implements */ {
40
41         private final Input.Region      location;
42         private final T                 tag;
43         private final Forest<T>[]       tokens;
44         private final boolean           unwrap;
45
46         private Body(Input.Region loc, T tag, Forest<T>[] tokens, boolean unwrap) {
47             this.location = loc;
48             this.tag = tag;
49             this.tokens = tokens==null ? emptyForestArray : new Forest[tokens.length];
50             if (tokens != null) System.arraycopy(tokens, 0, this.tokens, 0, tokens.length);
51             if (tokens != null) for(int i=0; i<tokens.length; i++) if (tokens[i]==null) throw new Error(i+"");
52             this.unwrap = unwrap;
53         }
54
55         public Tree<T> expand1() throws Ambiguous {
56             Tree<T>[] ret = new Tree[tokens.length];
57             for(int i=0; i<tokens.length; i++)
58                 ret[i] = tokens[i].expand1();
59             return new Tree<T>(location, tag, ret, unwrap);
60         }
61         public void gather(HashSet<Forest<T>> hf) {
62             hf.add(this);
63             for(Forest<T> f : tokens) f.gather(hf);
64         }
65         public void expand(HashSet<Tree<T>> ht, HashSet<Forest<T>> ignore, Tree<T> bogus) {
66             if (ignore.contains(this)) { ht.add(bogus); return; }
67             expand(0, new Tree[tokens.length], ht, ignore, bogus);
68         }
69         public void expand(final int i, Tree<T>[] ta, HashSet<Tree<T>> ht, HashSet<Forest<T>> ignore, Tree<T> bogus) {
70             if (i==tokens.length) {
71                 ht.add(new Tree<T>(location, tag, ta, unwrap));
72             } else {
73                 HashSet<Tree<T>> ht2 = new HashSet<Tree<T>>();
74                 tokens[i].expand(ht2, ignore, bogus);
75                 for(Tree<T> tc : ht2) {
76                     ta[i] = tc;
77                     expand(i+1, ta, ht, ignore, bogus);
78                     ta[i] = null;
79                 }
80             }
81         }
82
83         // GraphViz, ToInt //////////////////////////////////////////////////////////////////////////////
84
85         public boolean isTransparent() { return false; }
86         public boolean isHidden() { return false; }
87         public GraphViz.Node toGraphViz(GraphViz gv) {
88             if (gv.hasNode(this)) return gv.createNode(this);
89             GraphViz.Node n = gv.createNode(this);
90             n.label = headToString()==null?"":headToString();
91             n.directed = true;
92             edges(n);
93             return n;
94         }
95         boolean edges = false;
96         public void edges(GraphViz.Node n) {
97             if (edges) return;
98             edges = true;
99             for(int i=0; i<tokens.length; i++) {
100                 if (i==tokens.length-1 && unwrap && !tokens[i].ambiguous()) {
101                     tokens[i].edges(n);
102                 } else {
103                     n.edge(tokens[i], null);
104                 }
105             }
106         }
107
108         protected String  headToString()         { return tag==null?null:tag.toString(); }
109         protected String  headToJava()           { return "null"; }
110         protected String  left()                 { return "{"; }
111         protected String  right()                { return "}"; }
112         protected boolean ignoreSingleton()      { return false; }
113     }
114
115
116     // Ref //////////////////////////////////////////////////////////////////////////////
117
118     /**
119      *  This class represents a partially complete collection of
120      *  forests to be viewed as a forest at some later date; once
121      *  viewed, it becomes immutable
122      */
123     static class Ref<T> extends Forest<T> {
124         public HashSet<GSS.Phase.Node> parents = new HashSet<GSS.Phase.Node>();
125         private FastSet<Forest<T>> hp = new FastSet<Forest<T>>();
126
127         public Ref() { }
128
129         public Tree<T> expand1() throws Ambiguous {
130             if (hp.size() > 1) throw new Ambiguous(this);
131             return hp.iterator().next().expand1();
132         }
133         
134         public void gather(HashSet<Forest<T>> ht) {
135             ht.add(this);
136             for(Forest<T> f : hp) f.gather(ht);
137         }
138
139         public Forest resolve() { return this; }
140         public void expand(HashSet<Tree<T>> ht, HashSet<Forest<T>> ignore, Tree<T> bogus) {
141             if (ignore.contains(this)) { ht.add(bogus); return; }
142             for (Forest<T> f : hp) f.expand(ht, ignore, bogus);
143         }
144         public boolean contains(Forest f) { return hp.contains(f); }
145         public void merge(Forest p) { if (p!=this) hp.add(p, true); }
146         public boolean ambiguous() {
147             if (hp.size()==0) return false;
148             if (hp.size()==1) return hp.iterator().next().ambiguous();
149             return true;
150         }
151
152         // GraphViz, ToInt //////////////////////////////////////////////////////////////////////////////
153
154         public int toInt() {
155             if (hp.size()==1) return hp.iterator().next().toInt();
156             return super.toInt();
157         }
158         public boolean isTransparent() { return hp.size()==1; }
159         public boolean isHidden() { return hp.size()==0; }
160         public void edges(GraphViz.Node n) {
161             if (hp.size()==1) { hp.iterator().next().edges(n); return; }
162             for(Forest f : hp) f.edges(n);
163         }
164         public GraphViz.Node toGraphViz(GraphViz gv) {
165             //if (hp.size()==0) return null;
166             if (hp.size()==1) return hp.iterator().next().toGraphViz(gv);
167             if (gv.hasNode(this)) return gv.createNode(this);
168             GraphViz.Node n = gv.createNode(this);
169             n.label = "?";
170             n.color = "red";
171             for(Forest f : hp) n.edge(f, null);
172             return n;
173         }
174     }
175
176     // Statics //////////////////////////////////////////////////////////////////////////////
177
178     private static Tree[] tree_hint = new Tree[0];
179     private static String[] string_hint = new String[0];
180     private static final Forest[] emptyForestArray = new Forest[0];
181
182     protected String  headToString()    { return null; }
183     protected String  headToJava()      { return "null"; }
184     protected String  left()            { return "<?"; }
185     protected String  right()           { return "?>"; }
186     protected boolean ignoreSingleton() { return true; }
187 }