X-Git-Url: http://git.megacz.com/?p=sbp.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fsbp%2FParser.java;h=f37c5751b1a636c18dd2fd668c084d3f7d4c4c2a;hp=a54fa08df2eb57ee147e1d210b402a8dae7957ea;hb=f71911854d01647a743d52bfccff8d78a4497550;hpb=799bc0f3253172bd0cc3b54c90566825ac1a51c9;ds=sidebyside diff --git a/src/edu/berkeley/sbp/Parser.java b/src/edu/berkeley/sbp/Parser.java index a54fa08..f37c575 100644 --- a/src/edu/berkeley/sbp/Parser.java +++ b/src/edu/berkeley/sbp/Parser.java @@ -13,39 +13,36 @@ public abstract class Parser { private final Table pt; - private static void reachable(Element e, HashSet h) { - if (e instanceof Atom) return; - for(Sequence s : ((Union)e)) - reachable(s.firstp(), h); - } - private static void reachable(Position p, HashSet h) { - if (h.contains(p)) return; - h.add(p); - if (p.element() != null) reachable(p.element(), h); - } - - /** - * create a parser to parse the grammar with start symbol u - */ + /** create a parser to parse the grammar with start symbol u */ protected Parser(Union u) { this.pt = new Table(u, top()); } protected Parser(Table pt) { this.pt = pt; } - public abstract Forest shiftedToken(T t); + public abstract Forest shiftedToken(T t, Token.Location loc); public abstract Topology top(); /** parse input for a exactly one unique result, throwing Ambiguous if not unique or Failed if none */ - public Tree parse1(Token.Stream input) throws IOException, Failed, Ambiguous { return parse(input).expand1(); } + public Tree parse1(Token.Stream input) throws IOException, Failed, Ambiguous { + Forest ret = parse(input); + try { return ret.expand1(); } + catch (Ambiguous a) { + System.out.println("while expanding:"); + System.out.println(ret); + throw a; + } + } /** parse input, using the table pt to drive the parser */ public Forest parse(Token.Stream input) throws IOException, Failed { GSS gss = new GSS(); - GSS.Phase current = gss.new Phase(null, input.next()); + Token.Location loc = input.getLocation(); + GSS.Phase current = gss.new Phase(null, input.next(), loc); current.newNode(null, null, pt.start, true, null); for(;;) { - GSS.Phase next = gss.new Phase(current, input.next()); + loc = input.getLocation(); + GSS.Phase next = gss.new Phase(current, input.next(), loc); current.reduce(); - Forest forest = current.token==null ? null : shiftedToken((T)current.token); + Forest forest = current.token==null ? null : shiftedToken((T)current.token, loc); current.shift(next, forest); if (current.isDone()) return (Forest)current.finalResult; current.checkFailure(); @@ -80,23 +77,10 @@ public abstract class Parser { // Table ////////////////////////////////////////////////////////////////////////////// - static class Top extends Union { public Top() { super("0"); } } - /** an SLR(1) parse table which may contain conflicts */ - static class Table { + static class Table extends Walk.Cache { - private final Union start0 = new Top(); - private final Sequence start0seq; - - public final Walk.Cache cache = new Walk.Cache(); - - public HashSet closure() { - HashSet hp = new HashSet(); - reachable(start0, hp); - return hp; - } - public Position firstPosition() { return start0seq.firstp(); } - public Position lastPosition() { Position ret = start0seq.firstp(); while(!ret.isLast()) ret = ret.next(); return ret; } + public final Walk.Cache cache = this; private void walk(Element e, HashSet hs) { if (e==null) return; @@ -109,21 +93,6 @@ public abstract class Parser { walk(p.element(), hs); } } - public HashSet walk() { - HashSet ret = new HashSet(); - walk(start0, ret); - return ret; - } - - /* - public String toString() { - StringBuffer sb = new StringBuffer(); - for(Element e : walk()) - if (e instanceof Union) - ((Union)e).toString(sb); - return sb.toString(); - } - */ /** the start state */ public final State start; @@ -134,23 +103,29 @@ public abstract class Parser { /** construct a parse table for the given grammar */ public Table(Topology top) { this("s", top); } public Table(String startSymbol, Topology top) { this(new Union(startSymbol), top); } - public Table(Union u, Topology top) { - start0seq = new Sequence.Singleton(u, null, null); - start0.add(start0seq); + public Table(Union ux, Topology top) { + Union start0 = new Union("0"); + start0.add(new Sequence.Singleton(ux, null, null)); + + for(Sequence s : start0) cache.eof.put(s, true); + cache.eof.put(start0, true); // construct the set of states HashMap,State> all_states = new HashMap,State>(); - HashSet all_elements = walk(); + HashSet all_elements = new HashSet(); + walk(start0, all_elements); for(Element e : all_elements) cache.ys.put(e, new Walk.YieldSet(e, cache).walk()); - this.start = new State(closure(), all_states, all_elements); + HashSet hp = new HashSet(); + reachable(start0, hp); + this.start = new State(hp, all_states, all_elements); // for each state, fill in the corresponding "row" of the parse table for(State state : all_states.values()) for(Position p : state.hs) { // the Grammar's designated "last position" is the only accepting state - if (p==lastPosition()) + if (start0.contains(p.owner()) && p.next()==null) state.accept = true; // FIXME: how does right-nullability interact with follow restrictions? @@ -159,7 +134,7 @@ public abstract class Parser { Walk.Follow wf = new Walk.Follow(top.empty(), p.owner(), all_elements, cache); Reduction red = new Reduction(p); state.reductions.put(wf.walk(p.owner()), red); - if (wf.includesEof()) state.eofReductions.add(red, true); + if (wf.includesEof()) state.eofReductions.add(red); } // if the element following this position is an atom, copy the corresponding @@ -172,14 +147,35 @@ public abstract class Parser { /** a single state in the LR table and the transitions possible from it */ public class State implements Comparable, Iterable { - public final int idx = master_state_idx++; + /* + public boolean isResolvable(Token t) { + boolean found = false; + for(Reduction r : getReductions(t)) { + Position p = r.position; + if (!p.isRightNullable(cache)) continue; + if (p.owner().firstp()==p) continue; + if (found) { + // found two items meeting criteria #1 + return false; + } else { + found = true; + continue; + } + if (p.element()==null) continue; + Topology first = new Walk.First(top(), cache).walk(p.element()); + if (first.contains(t)) + } + } + */ + + public final int idx = master_state_idx++; private final HashSet hs; private transient HashMap gotoSetNonTerminals = new HashMap(); private transient TopologicalBag gotoSetTerminals = new TopologicalBag(); private TopologicalBag reductions = new TopologicalBag(); - private FastSet eofReductions = new FastSet(); + private HashSet eofReductions = new HashSet(); private TopologicalBag shifts = new TopologicalBag(); private boolean accept = false; @@ -236,7 +232,7 @@ public abstract class Parser { Atom a = (Atom)position.element(); HashSet hp = new HashSet(); reachable(position.next(), hp); - bag0.addAll(a, /*clo.walk()*/hp); + bag0.addAll(a, hp); } // Step 1b: for each _minimal, contiguous_ set of characters having an identical next-position @@ -298,7 +294,7 @@ public abstract class Parser { public class Reduction { // FIXME: cleanup; almost everything in here could go in either Sequence.Position.getRewrite() or else in GSS.Reduct public final int numPop; - private final Position position; + /*private*/ final Position position; private final Forest[] holder; // to avoid constant reallocation public int hashCode() { return position.hashCode(); } public boolean equals(Object o) { @@ -318,8 +314,15 @@ public abstract class Parser { holder[numPop-1] = f; return reduce(parent, numPop-2, rex, onlychild, target); } - public Forest reduce(GSS.Phase.Node parent, GSS.Phase.Node onlychild, GSS.Phase target, Forest rex) { - return reduce(parent, numPop-1, rex, onlychild, target); + public Forest reduce(GSS.Phase.Node parent, GSS.Phase.Node onlychild, Forest rex) { + return reduce(parent, numPop-1, rex, onlychild, parent.phase()); + } + + private Forest zero = null; + public Forest zero() { + if (zero != null) return zero; + if (numPop > 0) throw new Error(); + return zero = position.rewrite(null); } // FIXME: this could be more elegant and/or cleaner and/or somewhere else @@ -338,7 +341,7 @@ public abstract class Parser { } else { State state = parent.state.gotoSetNonTerminals.get(position.owner()); if (state!=null) - target.newNode(parent, rex, state, numPop<=0, parent.phase); + target.newNode(parent, rex, state, numPop<=0, parent.phase()); } return rex; } @@ -346,4 +349,19 @@ public abstract class Parser { } private static final Forest[] emptyForestArray = new Forest[0]; + + + // Helpers ////////////////////////////////////////////////////////////////////////////// + + private static void reachable(Element e, HashSet h) { + if (e instanceof Atom) return; + for(Sequence s : ((Union)e)) + reachable(s.firstp(), h); + } + private static void reachable(Position p, HashSet h) { + if (h.contains(p)) return; + h.add(p); + if (p.element() != null) reachable(p.element(), h); + } + }