Use separate lists in the serialized ATN for non-greedy states (cleaner, allows ATNs with twice as many states), resolves antlr/antlr4#96

This commit is contained in:
Sam Harwell 2012-12-05 18:55:58 -06:00
parent 064501967e
commit 886baaf773
2 changed files with 19 additions and 11 deletions

View File

@ -41,8 +41,6 @@ import java.util.IdentityHashMap;
import java.util.List;
public abstract class ATNSimulator {
public static final int SERIALIZED_NON_GREEDY_MASK = 0x8000;
public static final int SERIALIZED_STATE_TYPE_MASK = 0x7FFF;
/** Must distinguish between missing edge and edge we know leads nowhere */
@NotNull
@ -117,12 +115,7 @@ public abstract class ATNSimulator {
continue;
}
boolean nonGreedy = (stype & SERIALIZED_NON_GREEDY_MASK) != 0;
stype &= SERIALIZED_STATE_TYPE_MASK;
ATNState s = stateFactory(stype, i);
if (s instanceof DecisionState) {
((DecisionState)s).nonGreedy = nonGreedy;
}
s.ruleIndex = toInt(data[p++]);
if ( stype == ATNState.LOOP_END ) { // special case
int loopBackStateNumber = toInt(data[p++]);
@ -144,6 +137,12 @@ public abstract class ATNSimulator {
pair.a.endState = (BlockEndState)atn.states.get(pair.b);
}
int numNonGreedyStates = toInt(data[p++]);
for (int i = 0; i < numNonGreedyStates; i++) {
int stateNumber = toInt(data[p++]);
((DecisionState)atn.states.get(stateNumber)).nonGreedy = true;
}
//
// RULES
//

View File

@ -95,6 +95,7 @@ public class ATNSerializer {
int nedges = 0;
// dump states, count edges and collect sets while doing so
IntegerList nonGreedyStates = new IntegerList();
data.add(atn.states.size());
for (ATNState s : atn.states) {
if ( s==null ) { // might be optimized away
@ -102,12 +103,11 @@ public class ATNSerializer {
continue;
}
// encode the nongreedy bit with the state type
int stateType = s.getStateType();
assert stateType >= 0;
if (s instanceof DecisionState && ((DecisionState)s).nonGreedy) {
stateType |= ATNSimulator.SERIALIZED_NON_GREEDY_MASK;
nonGreedyStates.add(s.stateNumber);
}
data.add(stateType);
data.add(s.ruleIndex);
if ( s.getStateType() == ATNState.LOOP_END ) {
@ -132,6 +132,12 @@ public class ATNSerializer {
}
}
// non-greedy states
data.add(nonGreedyStates.size());
for (int i = 0; i < nonGreedyStates.size(); i++) {
data.add(nonGreedyStates.get(i));
}
int nrules = atn.ruleToStartState.length;
data.add(nrules);
for (int r=0; r<nrules; r++) {
@ -248,7 +254,6 @@ public class ATNSerializer {
for (int i=1; i<=nstates; i++) {
int stype = ATNSimulator.toInt(data[p++]);
if ( stype==ATNState.INVALID_TYPE ) continue; // ignore bad type of states
stype = stype & ATNSimulator.SERIALIZED_STATE_TYPE_MASK;
int ruleIndex = ATNSimulator.toInt(data[p++]);
String arg = "";
if ( stype == ATNState.LOOP_END ) {
@ -263,6 +268,10 @@ public class ATNSerializer {
.append(ATNState.serializationNames.get(stype)).append(" ")
.append(ruleIndex).append(arg).append("\n");
}
int numNonGreedyStates = ATNSimulator.toInt(data[p++]);
for (int i = 0; i < numNonGreedyStates; i++) {
int stateNumber = ATNSimulator.toInt(data[p++]);
}
int nrules = ATNSimulator.toInt(data[p++]);
for (int i=0; i<nrules; i++) {
int s = ATNSimulator.toInt(data[p++]);