package edu.berkeley.sbp;
import edu.berkeley.sbp.*;
import edu.berkeley.sbp.Sequence.Position;
import edu.berkeley.sbp.util.*;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
/**
*
* An efficient representation of a collection of trees (Tomita's
* shared packed parse forest).
*
*/
public abstract class Forest implements GraphViz.ToGraphViz {
/** assume that this forest contains exactly one tree and return it; otherwise throw an exception */
public abstract Tree expand1() throws Ambiguous;
/** expand this forest into a set of trees */
public void expand(HashSet> ht) { expand(ht, new HashSet>(), null); }
static Forest create(Input.Region loc, NodeType head, Forest[] children, boolean lift) {
return new One(loc, head, children, lift);
}
/** create a new forest */
public static Forest create(Input.Region loc, NodeType head, Forest[] children) {
return Forest.create(loc, head, children, false); }
// Package-Private //////////////////////////////////////////////////////////////////////////////
abstract void expand(HashSet> ht, HashSet> ignore, Tree bogus);
abstract void gather(HashSet> ignore);
abstract void edges(GraphViz.Node n);
boolean ambiguous() { return false; }
// One //////////////////////////////////////////////////////////////////////////////
/** A "single" forest with a head and child subforests */
private static class One extends Forest {
private final Input.Region location;
private final NodeType head;
private final Forest[] children;
/** if true, the last child's children are considered children of this node */
private final boolean lift;
private One(Input.Region loc, NodeType head, Forest[] children, boolean lift) {
this.location = loc;
this.head = head;
this.children = children==null ? emptyForestArray : new Forest[children.length];
if (children != null) System.arraycopy(children, 0, this.children, 0, children.length);
if (children != null) for(int i=0; i expand1() throws Ambiguous {
Tree[] ret = new Tree[children.length];
for(int i=0; i(location, head, ret, lift);
}
void gather(HashSet> hf) {
hf.add(this);
for(Forest f : children) f.gather(hf);
}
void expand(HashSet> ht, HashSet> ignore, Tree bogus) {
if (ignore.contains(this)) { ht.add(bogus); return; }
expand(0, new Tree[children.length], ht, ignore, bogus);
}
private void expand(final int i, Tree[] ta, HashSet> ht, HashSet> ignore, Tree bogus) {
if (i==children.length) {
ht.add(new Tree(location, head, ta, lift));
} else {
HashSet> ht2 = new HashSet>();
children[i].expand(ht2, ignore, bogus);
for(Tree tc : ht2) {
ta[i] = tc;
expand(i+1, ta, ht, ignore, bogus);
ta[i] = null;
}
}
}
// GraphViz, ToInt //////////////////////////////////////////////////////////////////////////////
public boolean isTransparent() { return false; }
public boolean isHidden() { return false; }
public GraphViz.Node toGraphViz(GraphViz gv) {
if (gv.hasNode(this)) return gv.createNode(this);
GraphViz.Node n = gv.createNode(this);
n.label = headToString()==null?"":headToString();
n.directed = true;
edges(n);
return n;
}
boolean edges = false; // FIXME ??
public void edges(GraphViz.Node n) {
if (edges) return;
edges = true;
for(int i=0; i extends Forest {
HashSet parents = new HashSet();
private FastSet> hp = new FastSet>();
private boolean touched = false;
public Many() { }
public Tree expand1() throws Ambiguous {
touched();
if (hp.size() > 1) {
HashSet> hf0 = new HashSet>();
Iterator> ih = hp.iterator();
ih.next().gather(hf0);
for(Forest f : hp) {
HashSet> hf1 = new HashSet>();
f.gather(hf1);
hf0.retainAll(hf1);
}
HashSet> ht = new HashSet>();
expand(ht, hf0, new Tree(null, "*"));
throw new Ambiguous((Forest>)this,
(HashSet>)(Object)ht);
}
return hp.iterator().next().expand1();
}
void gather(HashSet> ht) {
touched();
ht.add(this);
for(Forest f : hp) f.gather(ht);
}
private void touched() {
if (touched) return;
touched = true;
/*
FastSet> f2 = new FastSet>();
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;
}
void expand(HashSet> ht, HashSet> ignore, Tree bogus) {
touched();
if (ignore.contains(this)) { ht.add(bogus); return; }
for (Forest 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;
}
}
// Statics //////////////////////////////////////////////////////////////////////////////
private static Tree[] tree_hint = new Tree[0];
private static String[] string_hint = new String[0];
private static final Forest[] emptyForestArray = new Forest[0];
protected String headToString() { return null; }
protected String headToJava() { return "null"; }
protected String left() { return ""; }
protected String right() { return "?>"; }
protected boolean ignoreSingleton() { return true; }
}