forked from jasder/antlr
Merge branch 'atnstate-reachability-test' of github.com:sharwell/antlr4
This commit is contained in:
commit
8465920343
|
@ -60,6 +60,10 @@ public abstract class ATNSimulator {
|
|||
int p = 0;
|
||||
atn.grammarType = toInt(data[p++]);
|
||||
atn.maxTokenType = toInt(data[p++]);
|
||||
|
||||
//
|
||||
// STATES
|
||||
//
|
||||
int nstates = toInt(data[p++]);
|
||||
for (int i=1; i<=nstates; i++) {
|
||||
int stype = toInt(data[p++]);
|
||||
|
@ -75,6 +79,10 @@ public abstract class ATNSimulator {
|
|||
}
|
||||
atn.addState(s);
|
||||
}
|
||||
|
||||
//
|
||||
// RULES
|
||||
//
|
||||
int nrules = toInt(data[p++]);
|
||||
if ( atn.grammarType == ATN.LEXER ) {
|
||||
atn.ruleToTokenType = new int[nrules];
|
||||
|
@ -92,11 +100,19 @@ public abstract class ATNSimulator {
|
|||
atn.ruleToActionIndex[i] = actionIndex;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// MODES
|
||||
//
|
||||
int nmodes = toInt(data[p++]);
|
||||
for (int i=0; i<nmodes; i++) {
|
||||
int s = toInt(data[p++]);
|
||||
atn.modeToStartState.add((TokensStartState)atn.states.get(s));
|
||||
}
|
||||
|
||||
//
|
||||
// SETS
|
||||
//
|
||||
int nsets = toInt(data[p++]);
|
||||
for (int i=1; i<=nsets; i++) {
|
||||
int nintervals = toInt(data[p]);
|
||||
|
@ -108,6 +124,10 @@ public abstract class ATNSimulator {
|
|||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// EDGES
|
||||
//
|
||||
int nedges = toInt(data[p++]);
|
||||
for (int i=1; i<=nedges; i++) {
|
||||
int src = toInt(data[p]);
|
||||
|
@ -125,6 +145,10 @@ public abstract class ATNSimulator {
|
|||
srcState.addTransition(trans);
|
||||
p += 6;
|
||||
}
|
||||
|
||||
//
|
||||
// DECISIONS
|
||||
//
|
||||
int ndecisions = toInt(data[p++]);
|
||||
for (int i=1; i<=ndecisions; i++) {
|
||||
int s = toInt(data[p++]);
|
||||
|
@ -134,6 +158,7 @@ public abstract class ATNSimulator {
|
|||
decState.decision = i-1;
|
||||
decState.isGreedy = isGreedy==1;
|
||||
}
|
||||
|
||||
return atn;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,13 @@ public abstract class Transition {
|
|||
@NotNull
|
||||
public ATNState target;
|
||||
|
||||
protected Transition(@NotNull ATNState target) { this.target = target; }
|
||||
protected Transition(@NotNull ATNState target) {
|
||||
if (target == null) {
|
||||
throw new NullPointerException("target cannot be null.");
|
||||
}
|
||||
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public int getSerializationType() { return 0; }
|
||||
|
||||
|
|
|
@ -133,6 +133,11 @@ public class ATNSerializer {
|
|||
if ( s==null ) continue; // might be optimized away
|
||||
for (int i=0; i<s.getNumberOfTransitions(); i++) {
|
||||
Transition t = s.transition(i);
|
||||
|
||||
if (atn.states.get(t.target.stateNumber) == null) {
|
||||
throw new IllegalStateException("Cannot serialize a transition to a removed state.");
|
||||
}
|
||||
|
||||
int src = s.stateNumber;
|
||||
int trg = t.target.stateNumber;
|
||||
int edgeType = Transition.serializationTypes.get(t.getClass());
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
package org.antlr.v4.test;
|
||||
|
||||
import org.antlr.v4.automata.ATNSerializer;
|
||||
import org.junit.Test;
|
||||
|
||||
/** test runtime parse errors */
|
||||
|
@ -253,4 +254,27 @@ public class TestParseErrors extends BaseTest {
|
|||
assertEquals(expecting, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a regression test for #45 "NullPointerException in ATNConfig.hashCode".
|
||||
* https://github.com/antlr/antlr4/issues/45
|
||||
*
|
||||
* The original cause of this issue was an error in the tool's ATN state optimization,
|
||||
* which is now detected early in {@link ATNSerializer} by ensuring that all
|
||||
* serialized transitions point to states which were not removed.
|
||||
*/
|
||||
@Test
|
||||
public void testInvalidATNStateRemoval() throws Exception {
|
||||
String grammar =
|
||||
"grammar T;\n" +
|
||||
"start : ID ':' expr;\n" +
|
||||
"expr : primary expr? {} | expr '->' ID;\n" +
|
||||
"primary : ID;\n" +
|
||||
"ID : [a-z]+;\n" +
|
||||
"\n";
|
||||
String result = execParser("T.g", grammar, "TParser", "TLexer", "start", "x:x", true);
|
||||
String expecting = "";
|
||||
assertEquals(expecting, result);
|
||||
assertNull(this.stderrDuringParse);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue