-
- Node n = new Node(parent, pending, state, fromEmptyReduction); // ALLOC
- n.queueEmptyReductions();
- if (!fromEmptyReduction) n.queueReductions(parent);
- return true;
- }
-
- 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
- for(Sequence seq : r.position.owner().hated) {
- if (performed.contains(p,seq)) {
- inhibited.clear();
- inhibited.add(p, seq);
- resets++;
- throw new Reset();
- }
- inhibited.add(p, seq);
- }
- }
-
- /** perform all reduction operations */
- public void reduce() {
- try {
- reducing = true;
- if (reducing_list==null || reducing_list.length < hash.size())
- reducing_list = new Phase.Node[hash.size() * 4];
- Collection<Node> hv = hash.values();
- hv.toArray(reducing_list);
- int num = hv.size();
- for(int i=0; i<num; i++) {
- Node n = reducing_list[i];
- n.queueEmptyReductions();
- // INVARIANT: we never "see" a node until its parent-set is complete, modulo merges
- }
- for(int i=0; i<num; i++) {
- Node n = reducing_list[i];
- reducing_list[i] = null;
- n.queueReductions();
- }
- } catch (Reset r) {
- reset();
- reduce();
- }
- }
-
- class Reset extends RuntimeException { }
-
- public void invoke(State st, Forest result, Node n) {
- good |= next.newNode(n, result, st, false);
- }
-
- /** perform all shift operations, adding promoted nodes to <tt>next</tt> */
- public void shift(Phase next, Forest result) throws Parser.Failed {
- if (prev!=null) prev.hash = null;
- this.next = next;
- closed = true;
- Forest res = null;
- boolean ok = false;
- for(Phase.Node n : hash.values()) {
- if (n.holder==null) continue;
- n.holder.resolve();
- if (token == null && n.state.isAccepting()) {
- if (finalResult==null) finalResult = new Forest.Ref();
- finalResult.merge(n.holder);
- }
- if (!n.holder.valid()) continue;
- if (token == null) continue;
- n.state.invokeShifts(token, this, result, n);
- }
-
- if (!good && token!=null)
- throw new Parser.Failed(error(red("unexpected character")+" "+purple(token)+" encountered at "+green(getLocation())+"\n"),
- getLocation());
- if (token==null && finalResult==null)
- throw new Parser.Failed(error(red("unexpected end of file\n")),
- getLocation());
-
- // this massively improves GC performance
- //hash = null;
+ Node n = new Node(Phase.this, result, state, fromEmptyReduction); // ALLOC
+ /** FIXME: this null-result can be used to notice bogus/dead states */
+ for(Object s : state.conjunctStates)
+ newNode(new Result(null, n, null), (State)s, fromEmptyReduction);
+ return !n.state().doomed();