X-Git-Url: http://git.megacz.com/?p=sbp.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fsbp%2FGSS.java;h=9ab65870f9ef7ff883887e2bfa18dcc7a1ba6696;hp=3843f57020efe11b1df60b4612e8c818e89ddb91;hb=ceca07b4020b5dd051e0d01767a35842dec2ca74;hpb=ebb5fe5647046306f415e31e4967b23169c9004e diff --git a/src/edu/berkeley/sbp/GSS.java b/src/edu/berkeley/sbp/GSS.java index 3843f57..9ab6587 100644 --- a/src/edu/berkeley/sbp/GSS.java +++ b/src/edu/berkeley/sbp/GSS.java @@ -2,6 +2,8 @@ package edu.berkeley.sbp; import edu.berkeley.sbp.*; import edu.berkeley.sbp.util.*; import edu.berkeley.sbp.Sequence.Position; +import edu.berkeley.sbp.Parser.Table.State; +import edu.berkeley.sbp.Parser.Table.Reduction; import java.io.*; import java.util.*; import java.lang.reflect.*; @@ -12,34 +14,64 @@ class GSS { public GSS() { } private Phase.Node[] reducing_list = null; + public int resets = 0; + public int waits = 0; + HashMapBag inhibited = new HashMapBag(); + HashMapBag waiting = new HashMapBag(); + HashMapBag performed = new HashMapBag(); + /** corresponds to a positions between tokens the input stream; same as Tomita's U_i's */ - public class Phase implements Invokable { + public class Phase implements Invokable { /** the token immediately after this phase */ public final Token token; - boolean reducing = false; + boolean reducing; /** currently this is necessary only for the code() hack -- it doesn't actually correspond to the input */ private final int pos; /** FIXME */ - public Forest.Ref finalResult = null; + public Forest.Ref finalResult; /** all nodes, keyed by the value returned by code() */ - /*private*/ HashMap hash = new HashMap(); /* ALLOC */ + /*private*/ HashMap hash; /* ALLOC */ /** the number of nodes in this phase */ - private int numNodes = 0; + private int numNodes; - boolean closed = false; + boolean closed; + + private boolean good; + private Phase next = null; private Token.Location location; - public Phase(Phase previous, Token token, Token.Location location) { + public final Parser parser; + + private Forest forest; + Phase prev; + public Phase(Phase prev, Parser parser, Phase previous, Token token, Token.Location location, Forest forest) { + this.prev = prev; + this.forest = forest; + this.parser = parser; this.pos = previous==null ? 0 : previous.pos+1; this.token = token; this.location = location; + inhibited.clear(); + reset(); + } + + public void reset() { + waiting.clear(); + performed.clear(); + hash = new HashMap(); + good = false; + closed = false; + numNodes = 0; + reducing = false; + finalResult = null; + if (prev != null) prev.shift(this, forest); } public void complain(Node n, HashMap> errors, boolean force) { @@ -122,8 +154,6 @@ class GSS { return true; } - private String error = "generic syntax error"; - public Token.Location getLocation() { return location; } /** add a new node (merging with existing nodes if possible) @@ -133,12 +163,47 @@ class GSS { * @param fromEmptyReduction true iff this node is being created as a result of a reduction of length zero (see GRMLR paper) * @param start the earliest part of the input contributing to this node (used to make merging decisions) */ - public boolean newNode(Node parent, Forest pending, Parser.Table.State state, boolean fromEmptyReduction) { + public boolean newNode(Node parent, Forest pending, State state, boolean fromEmptyReduction) { + return newNode(parent, pending, state, fromEmptyReduction, null); } + public boolean newNode(Node parent, Forest pending, State state, boolean fromEmptyReduction, Reduction reduction) { + int pos = parent==null?0:parent.phase()==null?0:parent.phase().pos; + if (reduction!=null) { + if (inhibited.contains(pos, reduction.position.owner())) return false; + if (reduction.position.owner().needs != null) { + for(Sequence s : reduction.position.owner().needs) { + if (!performed.contains(pos, s)) { + waiting.add(s, new Waiting(parent, pending, state, fromEmptyReduction, reduction)); + return false; + } + } + } + if ((reduction.position.owner().needed != null && reduction.position.owner().needed.size()>0) || + (reduction.position.owner().hated != null && reduction.position.owner().hated.size()>0) || + (reduction.position.owner().hates != null && reduction.position.owner().hates.size()>0)) + performed.add(pos, reduction.position.owner()); + } Node p = hash.get(code(state, parent==null?null:parent.phase())); - if (p != null) return newNode2(p, parent, pending, state, fromEmptyReduction); - else return newNode3(parent, pending, state, fromEmptyReduction); + boolean ret; + if (reduction!=null) inhibit(reduction, parent==null?0:parent.phase().pos); + if (p != null) ret = newNode2(p, parent, pending, state, fromEmptyReduction, reduction); + else ret = newNode3(parent, pending, state, fromEmptyReduction, reduction); + if (reduction != null) { + boolean redo = true; + while(redo) { + redo = false; + for(Waiting w : waiting.getAll(reduction.position.owner())) { + if (w.parent==parent || (parent!=null&&w.parent!=null&&w.parent.phase()==parent.phase())) { + waiting.remove(reduction.position.owner(), w); + w.perform(); + redo = true; + break; + } + } + } + } + return ret; } - private boolean newNode2(Node p, Node parent, Forest pending, Parser.Table.State state, boolean fromEmptyReduction) { + private boolean newNode2(Node p, Node parent, Forest pending, State state, boolean fromEmptyReduction, Reduction reduction) { p.holder.merge(pending); if (p.parents().contains(parent)) return true; //if (p.fe && p.phase() != parent.phase()) throw new Error("yep yep"); @@ -147,7 +212,7 @@ class GSS { if (p!=parent && !fromEmptyReduction) p.queueReductions(parent); return true; } - private boolean newNode3(Node parent, Forest pending, Parser.Table.State state, boolean fromEmptyReduction) { + private boolean newNode3(Node parent, Forest pending, State state, boolean fromEmptyReduction, Reduction reduction) { do { if (token != null && state.canShift(token)) break; if (state.isAccepting()) break; @@ -165,35 +230,65 @@ class GSS { return true; } + public void uninhibit(int p, Sequence s) { + if (s.hated!=null) + for(Sequence s2 : s.hated) + inhibited.remove(p, s2); + } + + public void inhibit(Reduction r, int p) { + if (r.position.owner().hated == null) return; + // remember that dead states are still allowed to shift -- just not allowed to reduce + boolean reset = false; + for(Sequence seq : r.position.owner().hated) { + if (performed.contains(p,seq)) { + uninhibit(p, seq); + //System.out.println("\nresetting due to " + r.position.owner() + " killing " + seq); + if (!reset) inhibited.add(p, seq); + reset = true; + } + if (!reset) inhibited.add(p, seq); + } + if (reset) { + resets++; + throw new Reset(); + } + } /** perform all reduction operations */ public void reduce() { - reducing = true; - if (reducing_list==null || reducing_list.length < hash.size()) - reducing_list = new Phase.Node[hash.size() * 4]; - Collection hv = hash.values(); - hv.toArray(reducing_list); - int num = hv.size(); - for(int i=0; i hv = hash.values(); + hv.toArray(reducing_list); + int num = hv.size(); + for(int i=0; inext */ public void shift(Phase next, Forest result) throws Parser.Failed { + if (prev!=null) prev.hash = null; this.next = next; closed = true; Forest res = null; @@ -218,21 +313,41 @@ class GSS { getLocation()); // this massively improves GC performance - hash = null; + //hash = null; } + + public class Waiting { + Node parent; + Forest pending; + State state; + boolean fromEmptyReduction; + Reduction reduction; + public Waiting(Node parent, Forest pending, State state, boolean fromEmptyReduction, Reduction reduction) { + waits++; + this.parent = parent; + this.pending = pending; + this.state = state; + this.fromEmptyReduction = fromEmptyReduction; + this.reduction = reduction; + } + public void perform() { + //System.out.println("performing: " + reduction.position); + newNode(parent, pending, state, fromEmptyReduction, reduction); + } + } // GSS Nodes ////////////////////////////////////////////////////////////////////////////// /** a node in the GSS */ - public final class Node extends FastSet implements Invokable { + public final class Node extends FastSet implements Invokable { public boolean touched = false; private Forest.Ref holder = null; private boolean allqueued = false; /** what state this node is in */ - public final Parser.Table.State state; + public final State state; /** which Phase this Node belongs to (node that Node is also a non-static inner class of Phase) */ public Phase phase() { return Phase.this; } @@ -254,7 +369,7 @@ class GSS { state.invokeReductions(token, this, this, n2); } - public final void invoke(Parser.Table.Reduction r, Node n, Node n2) { + public final void invoke(Reduction r, Node n, Node n2) { if (n==null) { if (r.numPop==0) r.reduce(this); return; @@ -269,9 +384,18 @@ class GSS { } private boolean fe; - private Node(Node parent, Forest pending, Parser.Table.State state, boolean fe) { + public boolean dead = false; + public boolean redo = false; + private Node(Node parent, Forest pending, State state, boolean fe) { this.fe = fe; this.state = state; + for(Position p : state) { + if (p.owner().needs!=null) + for(Sequence s : p.owner().needs) { + //dead = true; + //redo = false; + } + } Phase start = parent==null ? null : parent.phase(); if (pending != null) this.holder().merge(pending); if (parent != null) parents().add(parent, true); @@ -292,7 +416,7 @@ class GSS { } /** this is something of a hack right now */ - private static long code(Parser.Table.State state, Phase start) { + private static long code(State state, Phase start) { return (((long)state.idx) << 32) | (start==null ? 0 : (start.pos+1)); } }