checkpoint
[sbp.git] / src / edu / berkeley / sbp / GSS.java
index bd2ecd6..2154731 100644 (file)
@@ -10,6 +10,7 @@ import java.lang.reflect.*;
 /** implements Tomita's Graph Structured Stack */
 class GSS {
 
+    public static int count = 0;
     public GSS() { }
 
     private Phase.Node[] reducing_list = null;
@@ -25,7 +26,7 @@ class GSS {
     public  Forest.Ref finalResult;
 
     /** corresponds to a positions <i>between tokens</i> the input stream; same as Tomita's U_i's */
-    public class Phase<Tok> implements Invokable<State, Forest, Phase<Tok>.Node>, IntegerMappable {
+    class Phase<Tok> implements Invokable<State, Forest, Phase<Tok>.Node>, IntegerMappable {
 
         public void invoke(State st, Forest result, Node n) {
             good |= next.newNode(n, result, st, false);
@@ -48,7 +49,7 @@ class GSS {
 
         private Forest forest;
 
-        public Phase(Phase prev, Parser parser, Phase previous, Tok token, Input.Location location, Forest forest) {
+        public Phase(Phase prev, Parser parser, Phase previous, Tok token, Input.Location location, Forest forest) throws ParseFailed {
             this.prev = prev;
             this.forest = forest;
             this.parser = parser;
@@ -59,13 +60,14 @@ class GSS {
             reset();
         }
 
-        public void reset() {
+        public void reset() throws ParseFailed {
             waiting.clear();
             performed.clear();
             hash = new IntPairMap<Phase.Node>();
             singularReductions = new IntPairMap<Forest>();
             expectedInhibit.clear();
             expectedInhibit.addAll(inhibited);
+            reset = false;
             good = false;
             closed = false;
             reducing = false;
@@ -113,7 +115,7 @@ class GSS {
             }
             if (!owner.lame)
                 newNode(parent, pending, state, fromEmptyReduction);
-            if (reduction!=null) inhibit(reduction, parent==null?0:parent.phase().pos);
+            if (reduction!=null) uninhibit(reduction, parent==null?0:parent.phase().pos);
             if (reduction != null) {
                 boolean redo = true;
                 while(redo) {
@@ -156,19 +158,19 @@ class GSS {
             return true;
         }
 
-        public void uninhibit(int p, Sequence s) {
+        public void inhibit(int p, Sequence s) {
             if (s.hated!=null)
                 for(Sequence s2 : s.hated)
                     inhibited.remove(p, s2);
         }
 
-        public void inhibit(Position r, int p) {
+        public void uninhibit(Position r, int p) {
             if (r.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.owner().hated) {
                 if (performed.contains(p,seq)) {
-                    uninhibit(p, seq);
+                    inhibit(p, seq);
                     //System.out.println("\nresetting due to " + r.owner() + " killing " + seq);
                     //inhibited.clear();
                     inhibited.add(p, seq);
@@ -183,7 +185,7 @@ class GSS {
         }
         
         /** perform all reduction operations */
-        public void reduce() {
+        public void reduce() throws ParseFailed{
             try {
                 reducing = true;
                 if (reducing_list==null || reducing_list.length < hash.size())
@@ -209,8 +211,10 @@ class GSS {
                 reset();
                 reduce();
             }
+            count = 0;
         }
 
+        private boolean reset = false;
         class Reset extends RuntimeException { }
 
         /** perform all shift operations, adding promoted nodes to <tt>next</tt> */
@@ -234,7 +238,10 @@ class GSS {
             }
 
             if (!good && token!=null)
-                throw new ParseFailed(ParseFailed.error(ANSI.red("unexpected character")+" "+ANSI.purple(token)+" encountered at "+ANSI.green(getLocation())+"\n", token, hash.values()),
+                throw new ParseFailed(ParseFailed.error(ANSI.red("unexpected character ")+" \'"+
+                                                        ANSI.purple(StringUtil.escapify(token+"", "\\\'\r\n"))+
+                                                        "\' encountered at "+
+                                                        ANSI.green(getLocation())+"\n", token, hash.values()),
                                         getLocation());
             if (token==null && finalResult==null)
                 throw new ParseFailed(ParseFailed.error(ANSI.red("unexpected end of file\n"), token, hash.values()),
@@ -242,7 +249,7 @@ class GSS {
         }
 
 
-        public class Waiting {
+        class Waiting {
             Node parent;
             Forest pending;
             State state;
@@ -265,7 +272,7 @@ class GSS {
         // Node /////////////////////////////////////////////////////////////////////////////////
 
         /** a node in the GSS */
-        public final class Node extends FastSet<Node> implements Invokable<Position, Node, Node>, IntegerMappable {
+        final class Node extends FastSet<Node> implements Invokable<Position, Node, Node>, IntegerMappable {
 
             private Forest.Ref holder = null;
             private boolean allqueued = false;
@@ -290,6 +297,7 @@ class GSS {
                 else            state.invokeReductions(token, this, this, n2);
             }
 
+            public void performEmptyReductions() { state.invokeReductions(token, this, null, null); }
             public final void invoke(Position r, Node n, Node n2) {
                 if (n==null || n2==null || r.pos==0) {
                     if (r.pos==0) {
@@ -304,39 +312,33 @@ class GSS {
                     Forest[] holder = new Forest[r.pos];
                     if (r.pos<=0) throw new Error("called wrong form of reduce()");
                     int pos = r.pos-1;
-                    Forest old = holder[pos];
-                    holder[pos] = n.pending();
-                    if (pos==0) {
-                        System.arraycopy(holder, 0, r.holder, 0, holder.length);
-                        Forest rex = null;
-                        if (r.pos==1)  rex = singularReductions.get(this, r);
-                        if (rex==null) {
-                            rex = r.rewrite(n.phase().getLocation());
-                            if (r.pos==1) singularReductions.put(this, r, rex);
-                        }
-                        n2.finish(r, rex, n.phase(), holder);
-                    } else {
-                        n2.reduce(r, pos-1, n.phase(), holder);
-                    }
-                    holder[pos] = old;
+                    n.reduce(r, pos, n.phase(), holder, n2);
                 }
             }
 
-            public void reduce(Position r, int pos, Phase target, Forest[] holder) {
+            public void reduce(Position r, int pos, Phase target, Forest[] holder) { reduce(r, pos, target, holder, null); }
+            public void reduce(Position r, int pos, Phase target, Forest[] holder, Node only) {
                 Forest old = holder[pos];
                 holder[pos] = this.pending();
                 if (pos==0) {
                     System.arraycopy(holder, 0, r.holder, 0, holder.length);
                     for(int i=0; i<r.pos; i++) if (r.holder[i]==null) throw new Error("realbad");
                     Forest rex = null;
-                    if (r.pos==1)  rex = singularReductions.get(this, r);
+
+                    // FIXME: I'm unsure about this -- basically we want to deal with the case where
+                    //        there are two nodes, each of whose Ref points to the same Forest instance.
+                    //        Some node in the next phase has both of these as parents.  This might happen
+                    //        since the same reduction can appear in more than one state.
+                    if (r.pos==1)  rex = singularReductions.get(this.pending(), r);
                     if (rex==null) {
                         rex = r.rewrite(phase().getLocation());
-                        if (r.pos==1) singularReductions.put(this, r, rex);
+                        if (r.pos==1) singularReductions.put(this.pending(), r, rex);
                     }
-                    for(Node child : this.parents()) child.finish(r, rex, target, holder);
+                    if (only != null)  only.finish(r, rex, target, holder);
+                    else               for(Node child : this.parents()) child.finish(r, rex, target, holder);
                 } else {
-                    for(Node child : this.parents()) child.reduce(r, pos-1, target, holder);
+                    if (only != null)  only.reduce(r, pos-1, target, holder);
+                    else               for(Node child : this.parents()) child.reduce(r, pos-1, target, holder);
                 }
                 holder[pos] = old;
             }
@@ -348,8 +350,6 @@ class GSS {
                     target.newNode(this, result, state0, r.pos<=0, r);
             }
 
-            public void performEmptyReductions() { state.invokeReductions(token, this, null, null); }
-
             private Node(Node parent, Forest pending, State state) {
                 this.state = state;
                 this.holder().merge(pending);