more unform naming for add/remove
[sbp.git] / src / edu / berkeley / sbp / StateNode.java
1 // Copyright 2006-2007 all rights reserved; see LICENSE file for BSD-style license
2
3 package edu.berkeley.sbp;
4 import edu.berkeley.sbp.*;
5 import edu.berkeley.sbp.util.*;
6 import edu.berkeley.sbp.Parser.Table.*;
7 import edu.berkeley.sbp.Sequence.Pos;
8 import edu.berkeley.sbp.Sequence.Pos;
9 import java.io.*;
10 import java.util.*;
11 import java.lang.reflect.*;
12
13 /** a node in the GSS */
14 final class StateNode
15     extends Node<ResultNode>
16     implements Invokable<Pos, ResultNode, Object> {
17
18     /** which GSS.Phase this StateNode belongs to */
19     public GSS.Phase phase() { return phase; }
20     public Iterator<ResultNode> iterator() { return predecessors.iterator(); }
21     public Parser.Table.State state() { return state; }
22
23     boolean destroyed = false;
24
25     public void check() {
26         if (destroyed) return;
27         boolean dead = true;
28         // - all nodes must have a predecessor
29         // - non-doomed nodes must either:
30         //      - be on the frontier or
31         //      - have a non-doomed node closer to the frontier than themself
32         if (phase.isFrontier()) dead = false;
33         else for(ResultNode r : successors)
34                  if (state.doomed) { if (r.usedByAnyNode()) { dead = false; break; } }
35                  else              { if (r.usedByNonDoomedNode()) { dead = false; break; } }
36         dead |= predecessors.size()==0;
37         if (!dead) return;
38         destroyed = true;
39         if (phase() != null && phase().hash != null)
40             phase().hash.remove(state, predPhase);
41         while(successors.size()>0)
42             for(ResultNode r : successors) {
43                 successors.remove(r);
44                 r.removePred(this);
45                 break;
46             }
47         while(predecessors.size()>0)
48             for(ResultNode r : predecessors) {
49                 predecessors.remove(r);
50                 r.removeSucc(this);
51                 break;
52             }
53         predecessors = null;
54         successors = null;
55     }
56
57     //////////////////////////////////////////////////////////////////////
58
59     private final GSS.Phase phase;
60     private final GSS.Phase predPhase;
61     private final Parser.Table.State state;
62     private  boolean fromEmptyReduction;
63
64     public final void invoke(Pos r, ResultNode only, Object o) {
65         boolean emptyProductions = only==null;
66         if (emptyProductions != (r.numPops()==0)) return;
67         if (r.numPops()!=0)  reduce(r, r.numPops()-1, phase(), only);
68         else {
69             Input.Region region = phase().getLocation().createRegion(phase().getLocation());
70             phase().newNodeFromReduction(r.rewrite(region), r, this);
71         }
72     }
73
74     private void reduce(Pos r, int pos, GSS.Phase target, ResultNode only) {
75         for(ResultNode res : predecessors)
76             if (only == null || res == only)
77                 for(StateNode pred : res)
78                     reduce2(r, pos, target, pred, res.getForest());
79     }
80
81     void reduce2(Pos r, int pos, GSS.Phase target, StateNode pred, Forest f) {
82         Forest[] holder = r.holder;
83         Forest old = pos >= holder.length ? null : holder[pos];
84         if (pos < holder.length) holder[pos] = f;
85         if (pos>0)  pred.reduce(r, pos-1, target, null);
86         else {
87             Input.Region region = pred.phase().getLocation().createRegion(target.getLocation());
88             new Reduction(pred, r, r.rewrite(region), target);
89         }
90         if (pos < holder.length) holder[pos] = old;
91     }
92
93     StateNode(GSS.Phase phase, Forest f, Pos reduction, StateNode pred, State state, boolean fromEmptyReduction) {
94         this(phase, new ResultNode(f, reduction, pred), state, fromEmptyReduction);
95     }
96     StateNode(GSS.Phase phase, ResultNode pred, State state, boolean fromEmptyReduction) {
97         this.phase = phase;
98         this.state = state;
99         this.fromEmptyReduction = fromEmptyReduction;
100         if (phase.hash.get(state, pred.phase()) != null) throw new Error("severe problem!");
101         this.predPhase = pred.phase();
102         phase.hash.put(state, pred.phase(), this);
103
104         predecessors.add(pred);
105         pred.addSucc(this);
106         if (!fromEmptyReduction)
107             state.invokeReductions(phase().getToken(), this, pred);
108
109         state.invokeEpsilonReductions(phase().token, this);
110     }
111
112     // Add/Remove Successors/Predecessors //////////////////////////////////////////////////////////////////////////////
113
114     public void removeSucc(ResultNode succ)   {
115         successors.remove(succ);
116         check();
117     }
118     public void removePred(ResultNode result) {
119         predecessors.remove(result);
120         check();
121     }
122     public void addSucc(ResultNode succ)      {
123         successors.add(succ);
124     }
125     public void addPred(Forest f, Pos reduction, StateNode pred) {
126         for(ResultNode r : predecessors)
127             if (r.predecessorsContains(pred)) {
128                 r.merge(f);
129                 return;
130             }
131         ResultNode result = new ResultNode(f, reduction, pred);
132         predecessors.add(result);
133         result.addSucc(this);
134         if (!this.fromEmptyReduction) state.invokeReductions(phase().getToken(), this, result);
135     }
136 }