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:
parent
064501967e
commit
886baaf773
|
@ -41,8 +41,6 @@ import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class ATNSimulator {
|
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 */
|
/** Must distinguish between missing edge and edge we know leads nowhere */
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -117,12 +115,7 @@ public abstract class ATNSimulator {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean nonGreedy = (stype & SERIALIZED_NON_GREEDY_MASK) != 0;
|
|
||||||
stype &= SERIALIZED_STATE_TYPE_MASK;
|
|
||||||
ATNState s = stateFactory(stype, i);
|
ATNState s = stateFactory(stype, i);
|
||||||
if (s instanceof DecisionState) {
|
|
||||||
((DecisionState)s).nonGreedy = nonGreedy;
|
|
||||||
}
|
|
||||||
s.ruleIndex = toInt(data[p++]);
|
s.ruleIndex = toInt(data[p++]);
|
||||||
if ( stype == ATNState.LOOP_END ) { // special case
|
if ( stype == ATNState.LOOP_END ) { // special case
|
||||||
int loopBackStateNumber = toInt(data[p++]);
|
int loopBackStateNumber = toInt(data[p++]);
|
||||||
|
@ -144,6 +137,12 @@ public abstract class ATNSimulator {
|
||||||
pair.a.endState = (BlockEndState)atn.states.get(pair.b);
|
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
|
// RULES
|
||||||
//
|
//
|
||||||
|
|
|
@ -95,6 +95,7 @@ public class ATNSerializer {
|
||||||
int nedges = 0;
|
int nedges = 0;
|
||||||
|
|
||||||
// dump states, count edges and collect sets while doing so
|
// dump states, count edges and collect sets while doing so
|
||||||
|
IntegerList nonGreedyStates = new IntegerList();
|
||||||
data.add(atn.states.size());
|
data.add(atn.states.size());
|
||||||
for (ATNState s : atn.states) {
|
for (ATNState s : atn.states) {
|
||||||
if ( s==null ) { // might be optimized away
|
if ( s==null ) { // might be optimized away
|
||||||
|
@ -102,12 +103,11 @@ public class ATNSerializer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode the nongreedy bit with the state type
|
|
||||||
int stateType = s.getStateType();
|
int stateType = s.getStateType();
|
||||||
assert stateType >= 0;
|
|
||||||
if (s instanceof DecisionState && ((DecisionState)s).nonGreedy) {
|
if (s instanceof DecisionState && ((DecisionState)s).nonGreedy) {
|
||||||
stateType |= ATNSimulator.SERIALIZED_NON_GREEDY_MASK;
|
nonGreedyStates.add(s.stateNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.add(stateType);
|
data.add(stateType);
|
||||||
data.add(s.ruleIndex);
|
data.add(s.ruleIndex);
|
||||||
if ( s.getStateType() == ATNState.LOOP_END ) {
|
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;
|
int nrules = atn.ruleToStartState.length;
|
||||||
data.add(nrules);
|
data.add(nrules);
|
||||||
for (int r=0; r<nrules; r++) {
|
for (int r=0; r<nrules; r++) {
|
||||||
|
@ -248,7 +254,6 @@ public class ATNSerializer {
|
||||||
for (int i=1; i<=nstates; i++) {
|
for (int i=1; i<=nstates; i++) {
|
||||||
int stype = ATNSimulator.toInt(data[p++]);
|
int stype = ATNSimulator.toInt(data[p++]);
|
||||||
if ( stype==ATNState.INVALID_TYPE ) continue; // ignore bad type of states
|
if ( stype==ATNState.INVALID_TYPE ) continue; // ignore bad type of states
|
||||||
stype = stype & ATNSimulator.SERIALIZED_STATE_TYPE_MASK;
|
|
||||||
int ruleIndex = ATNSimulator.toInt(data[p++]);
|
int ruleIndex = ATNSimulator.toInt(data[p++]);
|
||||||
String arg = "";
|
String arg = "";
|
||||||
if ( stype == ATNState.LOOP_END ) {
|
if ( stype == ATNState.LOOP_END ) {
|
||||||
|
@ -263,6 +268,10 @@ public class ATNSerializer {
|
||||||
.append(ATNState.serializationNames.get(stype)).append(" ")
|
.append(ATNState.serializationNames.get(stype)).append(" ")
|
||||||
.append(ruleIndex).append(arg).append("\n");
|
.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++]);
|
int nrules = ATNSimulator.toInt(data[p++]);
|
||||||
for (int i=0; i<nrules; i++) {
|
for (int i=0; i<nrules; i++) {
|
||||||
int s = ATNSimulator.toInt(data[p++]);
|
int s = ATNSimulator.toInt(data[p++]);
|
||||||
|
|
Loading…
Reference in New Issue