34759e366148392ceb9fa07e9e5ed322c1a107a9
[sbp.git] / src / edu / berkeley / sbp / Forest.java
1 package edu.berkeley.sbp;
2 import edu.berkeley.sbp.*;
3 import edu.berkeley.sbp.*;
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>>*/ implements Iterable<Forest.Body<T>> {
11
12     /** assume that this forest contains exactly one tree and return it; otherwise throw an exception */
13     public final Tree<T> expand1() throws Ambiguous, ParseFailed {
14         Iterator<Tree<T>> it = expand(true).iterator();
15         if (!it.hasNext()) throw new ParseFailed();
16         return it.next();
17     }
18
19     /** expand this forest into a set of trees */
20     public HashSet<Tree<T>> expand(boolean toss) {
21         HashSet<Tree<T>> ret = new HashSet<Tree<T>>();
22         for(Body<T> b : this)
23             ret.addAll(b.expand(toss, new ArrayList<Tree<T>>(), 0, new HashSet<Tree<T>>()));
24         if (toss && ret.size() > 1) throw new Ambiguous(this);
25         return ret;
26     }
27
28     static        <T> Forest<T> singleton(Input.Location loc)                       { return create(loc, null, new Forest[] { }, false, true); }
29     static        <T> Forest<T> singleton(Input.Location loc, Forest<T> body)       { return create(loc, null, new Forest[] { body },  false, true); }
30     static        <T> Forest<T> leaf(Input.Location loc, T tag) { return create(loc, tag, null, false, false); }
31     public static <T> Forest<T> create(Input.Location loc, T tag, Forest<T>[] tokens, boolean unwrap, boolean singleton) {
32         return new MyBody<T>(loc, tag, tokens, unwrap, singleton);
33     }
34
35     // Body //////////////////////////////////////////////////////////////////////////////
36
37     protected static interface Body<T> {
38          HashSet<Tree<T>> expand(boolean toss, ArrayList<Tree<T>> toks, int i, HashSet<Tree<T>> h);
39     }
40
41     protected static class MyBody<T> extends Forest<T> implements Body<T> /* extends PrintableTree<Forest<T>> implements Iterable<Forest.Body<T>>*/ {
42         public Iterator<Body<T>> iterator() { return new SingletonIterator<Body<T>>(this); }
43
44         private final Input.Location    location;
45         private final T                 tag;
46         private final Forest<T>[]       tokens;
47         private final boolean           unwrap;
48         private final boolean           singleton;
49
50         private MyBody(Input.Location loc, T tag, Forest<T>[] tokens, boolean unwrap, boolean singleton) {
51             this.location = loc;
52             this.tag = tag;
53             this.tokens = tokens==null ? emptyForestArray : new Forest[tokens.length];
54             if (tokens != null) System.arraycopy(tokens, 0, this.tokens, 0, tokens.length);
55             if (tokens != null) for(int i=0; i<tokens.length; i++) if (tokens[i]==null) throw new Error(i+"");
56             this.unwrap = unwrap;
57             this.singleton = singleton;
58         }
59
60         public HashSet<Tree<T>> expand(boolean toss, ArrayList<Tree<T>> toks, int i, HashSet<Tree<T>> h) {
61             if (singleton) {
62                 for(Body<T> b : tokens[0]) b.expand(toss, toks, i, h);
63
64             } else if (i==tokens.length) {
65                 h.add(new Tree<T>(null, tag, toks.toArray(tree_hint)));
66
67             } else if (unwrap && i==tokens.length-1) {
68                 if (tokens[i] != null)
69                     for(Body b : tokens[i])
70                         b.expand(toss, toks, 0, h);
71
72             } else {
73                 boolean hit = false;
74                 for(Tree<T> r : tokens[i].expand(toss)) {
75                     hit = true;
76                     int old = toks.size();
77                     toks.add(r);
78                     expand(toss, toks, i+1, h);
79                     while(toks.size() > old) toks.remove(toks.size()-1);
80                 }
81                 //if (!hit) throw new Error();
82             }
83             return h;
84         }
85
86         protected String  headToString()         { return null; }
87         protected String  headToJava()           { return null; }
88         protected String  left()                 { return "{"; }
89         protected String  right()                { return "}"; }
90         protected boolean ignoreSingleton()      { return false; }
91     }
92
93
94     // Ref //////////////////////////////////////////////////////////////////////////////
95
96     /**
97      *  This class represents a partially complete collection of
98      *  forests to be viewed as a forest at some later date; once
99      *  viewed, it becomes immutable
100      */
101     static class Ref<T> extends Forest<T> {
102         private FastSet<Forest<T>> hp = new FastSet<Forest<T>>();
103         public Ref() { }
104         public void merge(Forest p) { if (p!=this) hp.add(p, true); }
105         public Iterator<Body<T>> iterator() {
106             final Iterator<Forest<T>> ift = hp==null ? null : hp.iterator();
107             return new Iterator<Body<T>>() {
108                 Iterator<Body<T>> ibt = ift==null ? null : ift.hasNext() ? ift.next().iterator() : null;
109                 public void remove() { throw new RuntimeException("not supported"); }
110                 public boolean hasNext() {
111                     if (ibt==null) return false;
112                     if (ibt.hasNext()) return true;
113                     ibt = ift.hasNext() ? ift.next().iterator() : null;
114                     return hasNext();
115                 }
116                 public Body<T> next() {
117                     return ibt.next();
118                 }
119             };
120
121         }
122         public Forest resolve() { return this; }
123     }
124
125
126     // Statics //////////////////////////////////////////////////////////////////////////////
127
128     private static Tree[] tree_hint = new Tree[0];
129     private static final Forest[] emptyForestArray = new Forest[0];
130
131     protected String  headToString()    { return null; }
132     protected String  headToJava()      { return null; }
133     protected String  left()            { return "<?"; }
134     protected String  right()           { return "?>"; }
135     protected boolean ignoreSingleton() { return true; }
136 }