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;
|
int p = 0;
|
||||||
atn.grammarType = toInt(data[p++]);
|
atn.grammarType = toInt(data[p++]);
|
||||||
atn.maxTokenType = toInt(data[p++]);
|
atn.maxTokenType = toInt(data[p++]);
|
||||||
|
|
||||||
|
//
|
||||||
|
// STATES
|
||||||
|
//
|
||||||
int nstates = toInt(data[p++]);
|
int nstates = toInt(data[p++]);
|
||||||
for (int i=1; i<=nstates; i++) {
|
for (int i=1; i<=nstates; i++) {
|
||||||
int stype = toInt(data[p++]);
|
int stype = toInt(data[p++]);
|
||||||
|
@ -75,6 +79,10 @@ public abstract class ATNSimulator {
|
||||||
}
|
}
|
||||||
atn.addState(s);
|
atn.addState(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// RULES
|
||||||
|
//
|
||||||
int nrules = toInt(data[p++]);
|
int nrules = toInt(data[p++]);
|
||||||
if ( atn.grammarType == ATN.LEXER ) {
|
if ( atn.grammarType == ATN.LEXER ) {
|
||||||
atn.ruleToTokenType = new int[nrules];
|
atn.ruleToTokenType = new int[nrules];
|
||||||
|
@ -92,11 +100,19 @@ public abstract class ATNSimulator {
|
||||||
atn.ruleToActionIndex[i] = actionIndex;
|
atn.ruleToActionIndex[i] = actionIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// MODES
|
||||||
|
//
|
||||||
int nmodes = toInt(data[p++]);
|
int nmodes = toInt(data[p++]);
|
||||||
for (int i=0; i<nmodes; i++) {
|
for (int i=0; i<nmodes; i++) {
|
||||||
int s = toInt(data[p++]);
|
int s = toInt(data[p++]);
|
||||||
atn.modeToStartState.add((TokensStartState)atn.states.get(s));
|
atn.modeToStartState.add((TokensStartState)atn.states.get(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SETS
|
||||||
|
//
|
||||||
int nsets = toInt(data[p++]);
|
int nsets = toInt(data[p++]);
|
||||||
for (int i=1; i<=nsets; i++) {
|
for (int i=1; i<=nsets; i++) {
|
||||||
int nintervals = toInt(data[p]);
|
int nintervals = toInt(data[p]);
|
||||||
|
@ -108,6 +124,10 @@ public abstract class ATNSimulator {
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// EDGES
|
||||||
|
//
|
||||||
int nedges = toInt(data[p++]);
|
int nedges = toInt(data[p++]);
|
||||||
for (int i=1; i<=nedges; i++) {
|
for (int i=1; i<=nedges; i++) {
|
||||||
int src = toInt(data[p]);
|
int src = toInt(data[p]);
|
||||||
|
@ -125,6 +145,10 @@ public abstract class ATNSimulator {
|
||||||
srcState.addTransition(trans);
|
srcState.addTransition(trans);
|
||||||
p += 6;
|
p += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// DECISIONS
|
||||||
|
//
|
||||||
int ndecisions = toInt(data[p++]);
|
int ndecisions = toInt(data[p++]);
|
||||||
for (int i=1; i<=ndecisions; i++) {
|
for (int i=1; i<=ndecisions; i++) {
|
||||||
int s = toInt(data[p++]);
|
int s = toInt(data[p++]);
|
||||||
|
@ -134,6 +158,7 @@ public abstract class ATNSimulator {
|
||||||
decState.decision = i-1;
|
decState.decision = i-1;
|
||||||
decState.isGreedy = isGreedy==1;
|
decState.isGreedy = isGreedy==1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return atn;
|
return atn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,13 @@ public abstract class Transition {
|
||||||
@NotNull
|
@NotNull
|
||||||
public ATNState target;
|
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; }
|
public int getSerializationType() { return 0; }
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,11 @@ public class ATNSerializer {
|
||||||
if ( s==null ) continue; // might be optimized away
|
if ( s==null ) continue; // might be optimized away
|
||||||
for (int i=0; i<s.getNumberOfTransitions(); i++) {
|
for (int i=0; i<s.getNumberOfTransitions(); i++) {
|
||||||
Transition t = s.transition(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 src = s.stateNumber;
|
||||||
int trg = t.target.stateNumber;
|
int trg = t.target.stateNumber;
|
||||||
int edgeType = Transition.serializationTypes.get(t.getClass());
|
int edgeType = Transition.serializationTypes.get(t.getClass());
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
package org.antlr.v4.test;
|
package org.antlr.v4.test;
|
||||||
|
|
||||||
|
import org.antlr.v4.automata.ATNSerializer;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/** test runtime parse errors */
|
/** test runtime parse errors */
|
||||||
|
@ -253,4 +254,27 @@ public class TestParseErrors extends BaseTest {
|
||||||
assertEquals(expecting, result);
|
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