// Package-Private //////////////////////////////////////////////////////////////////////////////
- static <NodeType> Forest<NodeType> create(Input.Region region, NodeType head, Forest<NodeType>[] children, boolean lift) {
+ 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); }
/** if true, the last child's children are considered children of this node */
private final boolean lift;
+ private final boolean liftLeft;
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");
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) {
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);
/** a short string describing where the input is coming from, such as a filename */
public String getName();
+ /** might called by Parser when it is done with the input */
+ public void close();
+
/**
* <b>Optional:</b> <i>If possible</i>, this method will return a
* rendering of the input region (for example, if the input is a
// - be on the frontier or
// - have a non-doomed node closer to the frontier than themself
if (phase.isFrontier()) dead = false;
- for(Result r : children)
- if (state.doomed) { if (r.usedByAnyNode()) { dead = false; break; } }
- else { if (r.usedByNonDoomedNode()) { dead = false; break; } }
+ else for(Result r : children)
+ if (state.doomed) { if (r.usedByAnyNode()) { dead = false; break; } }
+ else { if (r.usedByNonDoomedNode()) { dead = false; break; } }
dead |= results.size()==0;
- if (!dead || destroyed) return;
+ if (!dead) return;
destroyed = true;
while(children.size()>0)
for(Result r : children) {
return ANSI.purple(ret.toString());
}
- static void error(String message, GSS.Phase phase) throws ParseFailed {
- error(message, phase.getLocation(), phase.getToken(),
- phase, phase.getRegion(), phase.getGSS().getInput(), phase.getGSS());
+ static void error(String message, GSS.Phase phase, Object token, Input.Region region) throws ParseFailed {
+ error(message,
+ token,
+ phase,
+ region,
+ phase.getGSS().getInput(),
+ phase.getGSS());
}
- static void error(String message,
- Input.Location loc,
- Object token,
- Iterable<Node> nodes,
- Input.Region region,
- Input input,
- GSS gss) throws ParseFailed{
+ private static void error(String message,
+ Object token,
+ Iterable<Node> nodes,
+ Input.Region region,
+ Input input,
+ GSS gss) throws ParseFailed{
String lookAhead = token==null ? "<EOF>" : token.toString();
StringBuffer ret = new StringBuffer();
ret.append(ANSI.bold(ANSI.red(message)));
- if (token != null) {
- ret.append(" \'");
- ret.append(ANSI.cyan(StringUtil.escapify(token+"", "\\\'\r\n")));
- ret.append("\'");
- }
+ String toks = token+"";
ret.append(" at ");
ret.append(ANSI.yellow(region+""));
if (input != null) {
public Forest<NodeType> parse(Input<Token> input) throws IOException, ParseFailed {
verbose = System.getProperty("sbp.verbose", null) != null;
spinpos = 0;
+ GSS gss = new GSS(input, this);
try {
- GSS gss = new GSS(input, this);
for(GSS.Phase current = gss.new Phase<Token>(pt.start); ;) {
-
- if (verbose) {
- // FIXME: clean this up
- String s;
- s = " " + spin[spinpos++ % (spin.length)]+" parsing ";
- s += input.getName();
- s += " "+input.getLocation();
- while(s.indexOf(':') != -1 && s.indexOf(':') < 8) s = " " + s;
- String y = "@"+gss.viewPos+" ";
- while(y.length() < 9) y = " " + y;
- s += y;
- s += " nodes="+gss.numOldNodes;
- while(s.length() < 50) s = s + " ";
- s += " shifted="+gss.numNewNodes;
- while(s.length() < 60) s = s + " ";
- s += " reductions="+gss.numReductions;
- System.err.print("\r"+s+ANSI.clreol()+"\r");
- }
-
+ if (verbose) debug(current.token, gss, input);
if (current.isDone()) return (Forest<NodeType>)current.finalResult;
- Forest forest = shiftToken((Token)current.token, current.getRegion());
+ Input.Region region = current.getLocation().createRegion(current.getNextLocation());
+ Forest forest = shiftToken((Token)current.token, region);
current = gss.new Phase<Token>(current, forest);
}
- } finally { if (verbose) System.err.print("\r"+ANSI.clreol()); }
+ } finally {
+ if (verbose) {
+ System.err.print("\r"+ANSI.clreol());
+ debug(null, gss, input);
+ }
+ }
}
// Spinner //////////////////////////////////////////////////////////////////////////////
System.err.print("\r " + spin[spinpos++ % (spin.length)]+"\r");
}
+ private int _last = -1;
+ private String buf = "";
+ private void debug(Object t, GSS gss, Input input) {
+ //FIXME
+ int c = t==null ? -1 : ((t+"").charAt(0));
+ int last = _last;
+ _last = c;
+ switch(c) {
+ case edu.berkeley.sbp.chr.CharAtom.left:
+ buf += "\033[31m{\033[0m";
+ break;
+ case edu.berkeley.sbp.chr.CharAtom.right:
+ buf += "\033[31m}\033[0m";
+ break;
+ case -1: // FIXME
+ case '\n':
+ if (verbose) {
+ if (last==' ') buf += ANSI.blue("\\n");
+ System.err.println("\r"+ANSI.clreol()+"\r"+buf);
+ buf = "";
+ }
+ break;
+ default:
+ buf += ANSI.cyan(""+((char)c));
+ break;
+ }
+ if (t==null) return;
+
+ // FIXME: clean this up
+ String s;
+ s = " " + spin[spinpos++ % (spin.length)]+" parsing ";
+ s += input.getName();
+ s += " "+input.getLocation();
+ while(s.indexOf(':') != -1 && s.indexOf(':') < 8) s = " " + s;
+ String y = "@"+gss.viewPos+" ";
+ while(y.length() < 9) y = " " + y;
+ s += y;
+ s += " nodes="+gss.numOldNodes;
+ while(s.length() < 50) s = s + " ";
+ s += " shifted="+gss.numNewNodes;
+ while(s.length() < 60) s = s + " ";
+ s += " reductions="+gss.numReductions;
+ while(s.length() < 78) s = s + " ";
+ System.err.print("\r"+ANSI.invert(s+ANSI.clreol())+"\r");
+ }
+
// Table //////////////////////////////////////////////////////////////////////////////
/** an SLR(1) parse table which may contain conflicts */
// Interface Methods //////////////////////////////////////////////////////////////////////////////
+ public boolean doomed() { return doomed; }
boolean isAccepting() { return accept; }
public Iterator<Position> iterator() { return hs.iterator(); }
boolean canShift(Token t) { return oshifts!=null && oshifts.contains(t); }
}
public int toInt() { return idx; }
+ public String toString() {
+ StringBuffer ret = new StringBuffer();
+ for(Position p : hs)
+ ret.append(p+"\n");
+ return ret.toString();
+ }
}
}
parent.removeChild(this);
while(children.size() > 0)
for(Node n : children) {
- children.remove(n);
+ removeChild(n);
n.removeResult(this);
break;
}
? new Unwrap(e, head, drop)
: new RewritingSequence(head, e, drop);
}
+ public static Sequence createLeft(Object head, Element[] e, boolean[] drop, boolean foster) {
+ return foster
+ ? new UnwrapLeft(e, head, drop)
+ : new RewritingSequence(head, e, drop);
+ }
/** return a new sequence identical to this one, but with a positive conjunct <tt>s</tt> */
public Sequence and(Sequence s) {
}
}
+ static class UnwrapLeft extends Sequence {
+ private boolean[] drops;
+ private final Object tag;
+ public UnwrapLeft(Element[] e, Object tag) { this(e, tag, null); }
+ public UnwrapLeft(Element[] e, Object tag, boolean[] drops) { super(e); this.drops = drops; this.tag = tag; }
+ Sequence _clone() { return new UnwrapLeft(elements, tag, drops); }
+ public <T> Forest<T> postReduce(Input.Region loc, Forest<T>[] args, Position p) {
+ for(int i=0; i<args.length; i++) if (args[i]==null) throw new Error();
+ if (drops==null) return Forest.create(loc, (T)tag, args, false, true);
+ int count = 0;
+ for(int i=0; i<drops.length; i++) if (!drops[i]) count++;
+ Forest<T>[] args2 = new Forest[count];
+ int j = 0;
+ for(int i=0; i<args.length; i++) if (!drops[i]) args2[j++] = args[i];
+ return Forest.create(loc, (T)tag, args2, false, true);
+ }
+ Forest epsilonForm(Input.Region loc, Grammar cache) {
+ return Forest.create(loc, tag, new Forest[0], false);
+ }
+ }
+
static class RewritingSequence extends Sequence {
private Object tag;
private final boolean[] drops;
// FIXME: fairly inefficient because we keep copying arrays
/** package-private constructor, allows setting the "lift" bit */
Tree(Input.Region loc, NodeType head, Tree<NodeType>[] children, boolean lift) {
+ this(loc, head, children, lift, false);
+ }
+ Tree(Input.Region loc, NodeType head, Tree<NodeType>[] children, boolean lift, boolean liftLeft) {
this.location = loc;
this.ihead = head;
- if (lift && children != null && children.length > 0) {
+ // FIXME: lift+liftLeft togheter
+ if (liftLeft && children != null && children.length > 0) {
+ Tree<NodeType> last = children[0];
+ this.children = new Tree[(children.length-1)+last.children.length];
+ System.arraycopy(children, 1, this.children, last.children.length, children.length-1);
+ if (last.children.length > 0)
+ System.arraycopy(last.children, 0, this.children, 0, last.children.length);
+ } else if (lift && children != null && children.length > 0) {
Tree<NodeType> last = children[children.length-1];
this.children = new Tree[(children.length-1)+last.children.length];
System.arraycopy(children, 0, this.children, 0, children.length-1);