MAJOR: huge revamp of Sequence, Result, Reduction, Parser, Node, GSS
[sbp.git] / src / edu / berkeley / sbp / GSS.java
index 91ef765..c96ceee 100644 (file)
@@ -13,22 +13,31 @@ import java.lang.reflect.*;
 class GSS {
 
     Input input;
-    public GSS(Input input) { this.input = input; }
+    private Parser parser;
+    public GSS(Input input, Parser parser) { this.input = input; this.parser = parser;}
     public Input getInput() { return input; }
 
-    // FIXME: right now, these are the performance bottleneck
-    HashMapBag<Integer,Sequence>       performed       = new HashMapBag<Integer,Sequence>();
-
-    /** FIXME */
-    Forest.Many finalResult;
+    int numNewNodes = 0;
+    int numOldNodes = 0;
+    int viewPos = 0;
+    int numReductions = 0;
 
     /** corresponds to a positions <i>between tokens</i> the input stream; same as Tomita's U_i's */
-    class Phase<Tok> implements Invokable<State, Result, Object>, IntegerMappable, GraphViz.ToGraphViz, Iterable<Node> {
+    class Phase<Tok> implements Invokable<State, Result>, IntegerMappable, GraphViz.ToGraphViz, Iterable<Node> {
+
+        // FIXME: right now, these are the performance bottleneck
+        private HashMapBag<Integer,Sequence>       performed       = new HashMapBag<Integer,Sequence>();
 
-        public PriorityQueue<Reduction> reductionQueue = new PriorityQueue<Reduction>();
+        public Forest.Many finalResult;
+        private PriorityQueue<Reduction> reductionQueue = new PriorityQueue<Reduction>();
 
-        public void invoke(State st, Result result, Object o) {
-            //shifts++;
+        public void addReduction(Reduction r) {
+            //System.out.println("+ " + r);
+            parser.spin();
+            reductionQueue.add(r);
+        }
+        public void invoke(State st, Result result) {
+            parser.spin();
             good |= next.newNode(result, st, false);
         }
 
@@ -36,8 +45,8 @@ class GSS {
         final Tok token;
         final int pos;
 
-        public IntPairMap<Node> hash;  /* ALLOC */
-        private boolean good;
+        public IntPairMap<Node> hash = new IntPairMap<Node>();  /* ALLOC */
+        private boolean good = false;
         private Phase next = null;
         private Phase prev;
         private Input.Location location;
@@ -46,23 +55,54 @@ class GSS {
         
         private Forest forest;
 
-        public Phase(Phase prev, Phase previous, Tok token, Input.Location location,
-                     Input.Location nextLocation, Forest forest) throws ParseFailed {
+        public Phase(State startState) throws ParseFailed, IOException {
+            this(null, null);
+            Result primordealResult = new Result(null, null, null);
+            newNode(primordealResult, startState, true);
+        }
+        public Phase(Phase prev, Forest forest) throws ParseFailed, IOException {
+            this.location = input.getLocation();
+            this.token = (Tok)input.next();
             this.prevLocation = prev==null ? location : prev.getLocation();
             this.prev = prev;
             this.forest = forest;
-            this.pos = previous==null ? 0 : previous.pos+1;
-            this.token = token;
-            this.location = location;
-            this.nextLocation = nextLocation;
-            performed.clear();
-            hash = new IntPairMap<Node>();
-            good = false;
-            finalResult = null;
+            this.pos = prev==null ? 0 : prev.pos+1;
+            this.nextLocation = input.getLocation();
             if (prev != null) prev.shift(this, forest);
+            numReductions = 0;
+
+            int minPhasePos = Integer.MAX_VALUE;
+            int maxOrd = -1;
+            Reduction best = null;
+            //System.out.println("==============================================================================");
+            while(!reductionQueue.isEmpty()) {
+                Reduction r = reductionQueue.poll();
+                //System.out.println("- " + r);
+                if (r.parentPhase() != null)
+                    if (r.parentPhase().pos > minPhasePos)
+                        throw new Error();
+                r.perform();
+                if (r.parentPhase() != null) {
+                    if (r.parentPhase().pos < minPhasePos) {
+                        minPhasePos = r.parentPhase().pos;
+                        maxOrd = r.reduction().ord;
+                        best = r;
+                    } else if (r.parentPhase().pos == minPhasePos) {
+                        /*
+                        if (best != null && Parser.mastercache.comparePositions(r.reduction(), best.reduction()) < 0)
+                            throw new Error("\n"+r+"\n"+best+"\n"+
+                                            Parser.mastercache.comparePositions(r.reduction(), best.reduction())+"\n"+r.compareTo(best)+
+                                            "\n"+(r.reduction().ord-best.reduction().ord));
+                        */
+                        maxOrd = r.reduction().ord;
+                        best = r;
+                    }
+                }
+                numReductions++;
+            }
+            if (token==null) shift(null, null);
         }
 
-        public boolean isFrontier() { return next==null; }
         public boolean isDone() throws ParseFailed {
             if (token != null) return false;
             if (token==null && finalResult==null)
@@ -74,12 +114,20 @@ class GSS {
         public Input.Location getLocation() { return location; }
         public Input.Region   getRegion() { return getPrevLocation().createRegion(getLocation()); }
         public Input.Location getNextLocation() { return nextLocation; }
+        public boolean        isFrontier() { return hash!=null; }
 
         /** perform all shift operations, adding promoted nodes to <tt>next</tt> */
-        public void shift(Phase next, Forest result) throws ParseFailed {
-            // this massively improves GC performance
-            if (prev!=null) prev.hash = null;
+        private void shift(Phase next, Forest result) throws ParseFailed {
             this.next = next;
+            // this massively improves GC performance
+            if (prev != null) {
+                IntPairMap<Node> h = prev.hash;
+                prev.hash = null;
+                prev.performed = null;
+                for(Node n : h)
+                    n.check();
+            }
+            numOldNodes = hash.size();
             for(Node n : hash.values()) {
                 if (token == null && n.state().isAccepting()) {
                     if (finalResult==null) finalResult = new Forest.Many();
@@ -87,32 +135,28 @@ class GSS {
                         finalResult.merge(r.getForest());
                 }
                 if (token == null) continue;
-                n.state().invokeShifts(token, this, new Result(result, n, null), null);
+                n.state().invokeShifts(token, this, new Result(result, n, null));
             }
-            for(Node n : hash.values()) n.check();
+            numNewNodes = next==null ? 0 : next.hash.size();
+            viewPos = this.pos;
             if (!good && token!=null) ParseFailed.error("unexpected character", this);
             if (token==null && finalResult==null) ParseFailed.error("unexpected end of file", this);
+            for(Node n : hash) n.check();
         }
 
-        /** perform all reduction operations */
-        public void reduce() throws ParseFailed {
-            while(!reductionQueue.isEmpty())
-                reductionQueue.poll().perform();
-        }
-
-        public void newNodeFromReduction(Result result, State state, boolean fromEmptyReduction, Position reduction) {
+        void newNodeFromReduction(Result result, State state, Position reduction) {
             int pos = result.phase().pos;
             Sequence owner = reduction.owner();
-            for(Sequence s : owner.hates)
+            for(Sequence s : owner.hates())
                 if (performed.contains(pos, s))
                     return;
-            for(Sequence s : owner.needs)
+            for(Sequence s : owner.needs())
                 if (!performed.contains(pos, s))
                     return;
             if (owner.needed_or_hated && !performed.contains(pos, owner))
                 performed.add(pos, owner);
             if (state!=null)
-                newNode(result, state, fromEmptyReduction);
+                newNode(result, state, reduction.pos<=0);
         }
 
         /** add a new node (merging with existing nodes if possible)
@@ -122,16 +166,18 @@ 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(Result result, State state, boolean fromEmptyReduction) {
+        private boolean newNode(Result result, State state, boolean fromEmptyReduction) {
             Node p = hash.get(state, result.phase());
-            if (p != null) { p.merge(result); return true; }
+            if (p != null) { p.addResult(result); return true; }
             do {
                 if (token != null && state.canShift(token)) break;
                 if (state.isAccepting()) break;
                 if (token==null) break;
                 if (!state.canReduce(token)) return false;
             } while(false);
-            new Node(Phase.this, result, state, fromEmptyReduction);  // ALLOC
+            Node n = new Node(Phase.this, result, state, fromEmptyReduction);  // ALLOC
+            for(Object s : state.also)
+                newNode(new Result(null, n, null), (State)s, fromEmptyReduction);
             return true;
         }
 
@@ -155,6 +201,17 @@ class GSS {
         public boolean isTransparent() { return false; }
         public boolean isHidden() { return false; }
 
+        public void dumpGraphViz(String filename) throws IOException {
+            FileOutputStream fos = new FileOutputStream(filename);
+            PrintWriter p = new PrintWriter(new OutputStreamWriter(fos));
+            GraphViz gv = new GraphViz();
+            for(Object n : this)
+                ((Node)n).toGraphViz(gv);
+            gv.dump(p);
+            p.flush();
+            p.close();
+        }
+
     }
 
 }