Merge branch 'atnstate-reachability-test' of github.com:sharwell/antlr4

This commit is contained in:
Terence Parr 2012-03-27 15:05:39 -07:00
commit 8465920343
4 changed files with 61 additions and 1 deletions

View File

@ -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;
}

View File

@ -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; }

View File

@ -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());

View File

@ -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);
}
}