+// Copyright 2006 all rights reserved; see LICENSE file for BSD-style license
+
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.*;
/**
* <font color=blue>
public abstract Tree<NodeType> expand1() throws Ambiguous;
/** expand this forest into a set of trees */
- public void expand(HashSet<Tree<NodeType>> ht) { expand(ht, new HashSet<Forest<NodeType>>(), null); }
-
- static <NodeType> Forest<NodeType> create(Input.Region loc, NodeType head, Forest<NodeType>[] children, boolean lift) {
- if (loc == null) throw new Error();
- return new One<NodeType>(loc, head, children, lift);
+ public Iterable<Tree<NodeType>> expand() {
+ HashSet<Tree<NodeType>> ht = new HashSet<Tree<NodeType>>();
+ expand(ht, new HashSet<Forest<NodeType>>(), null);
+ return ht;
}
- /** create a new forest */
- public static <NodeType> Forest<NodeType> create(Input.Region loc, NodeType head, Forest<NodeType>[] children) {
- return Forest.create(loc, head, children, false); }
+ /** returns the input Region which this Forest was parsed from */
+ public abstract Input.Region getRegion();
// Package-Private //////////////////////////////////////////////////////////////////////////////
+ static <NodeType> Forest<NodeType> create(Input.Region region, NodeType head, Forest<NodeType>[] children,
+ boolean lift) {
+ if (region == null) throw new RuntimeException("invoked Forest.create(region=null) -- this should never happen");
+ return new One<NodeType>(region, head, children, lift);
+ }
+
+ static <NodeType> Forest<NodeType> create(Input.Region region, NodeType head, Forest<NodeType>[] children,
+ boolean lift, boolean liftLeft) {
+ if (region == null) throw new RuntimeException("invoked Forest.create(region=null) -- this should never happen");
+ return new One<NodeType>(region, head, children, lift, liftLeft);
+ }
+
+ /** create a new forest */
+ public static <NodeType> Forest<NodeType> create(Input.Region region, NodeType head, Forest<NodeType>[] children) {
+ return Forest.create(region, head, children, false); }
+
abstract void expand(HashSet<Tree<NodeType>> ht, HashSet<Forest<NodeType>> ignore, Tree<NodeType> bogus);
abstract void gather(HashSet<Forest<NodeType>> ignore);
abstract void edges(GraphViz.Node n);
boolean ambiguous() { return false; }
- abstract Input.Region getRegion();
-
// One //////////////////////////////////////////////////////////////////////////////
/** A "single" forest with a head and child subforests */
/** if true, the last child's children are considered children of this node */
private final boolean lift;
+ private final boolean liftLeft;
- Input.Region getRegion() { return location; }
+ public Input.Region getRegion() { return location; }
private One(Input.Region loc, NodeType head, Forest<NodeType>[] children, boolean lift) {
+ this(loc, head, children, lift, false);
+ }
+ private One(Input.Region loc, NodeType head, Forest<NodeType>[] children, boolean lift, boolean liftLeft) {
this.location = loc;
this.head = head;
+ if (head==null) throw new RuntimeException("invoked Forest.create(,null,,,) -- this should never happen");
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<children.length; i++) if (children[i]==null) throw new Error(i+"");
this.lift = lift;
+ this.liftLeft = liftLeft;
}
public Tree<NodeType> expand1() throws Ambiguous {
Tree<NodeType>[] ret = new Tree[children.length];
for(int i=0; i<children.length; i++) ret[i] = children[i].expand1();
- return new Tree<NodeType>(location, head, ret, lift);
+ return new Tree<NodeType>(location, head, ret, lift, liftLeft);
}
void gather(HashSet<Forest<NodeType>> hf) {
if (ignore.contains(this)) { ht.add(bogus); return; }
expand(0, new Tree[children.length], ht, ignore, bogus);
}
- private void expand(final int i, Tree<NodeType>[] ta, HashSet<Tree<NodeType>> ht, HashSet<Forest<NodeType>> ignore, Tree<NodeType> bogus) {
+ private void expand(final int i, Tree<NodeType>[] ta, HashSet<Tree<NodeType>> ht, HashSet<Forest<NodeType>> ignore,
+ Tree<NodeType> bogus) {
if (i==children.length) {
- ht.add(new Tree<NodeType>(location, head, ta, lift));
+ ht.add(new Tree<NodeType>(location, head, ta, lift, liftLeft));
} else {
HashSet<Tree<NodeType>> ht2 = new HashSet<Tree<NodeType>>();
children[i].expand(ht2, ignore, bogus);
/** An "ambiguity node"; this is immutable once it has been "looked at" */
static class Many<NodeType> extends Forest<NodeType> {
- HashSet<GSS.Phase.Node> parents = new HashSet<GSS.Phase.Node>();
private FastSet<Forest<NodeType>> hp = new FastSet<Forest<NodeType>>();
private boolean touched = false;
public Many() { }
- Input.Region getRegion() { return hp.iterator().next().getRegion(); } // all should be identical
+ public Input.Region getRegion() { return hp.iterator().next().getRegion(); } // all should be identical
public Tree<NodeType> expand1() throws Ambiguous {
touched();
void gather(HashSet<Forest<NodeType>> ht) {
touched();
+
+ // FIXME: do something more sensible here
+ if (ht.contains(this)) {
+ System.err.println("WARNING: grammar produced a circular forest\n" + this);
+ //throw new Error("grammar produced a circular forest:\n" + this);
+ return;
+ }
+
ht.add(this);
for(Forest<NodeType> f : hp) f.gather(ht);
}