v4: Reusable ATN simulator objects

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9448]
This commit is contained in:
sharwell 2011-11-23 06:42:31 -08:00
parent 89ebd369f9
commit 898138a5e2
13 changed files with 451 additions and 354 deletions

View File

@ -56,7 +56,8 @@ public abstract class BaseRecognizer<Symbol> extends Recognizer<Symbol, ParserAT
/** Did the recognizer encounter a syntax error? Track how many. */
protected int syntaxErrors = 0;
public BaseRecognizer(IntStream input) {
public BaseRecognizer(IntStream input, ParserATNSimulator<Symbol> interpreter) {
super(interpreter);
setInputStream(input);
}

View File

@ -93,8 +93,12 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
*/
public String text;
public Lexer(CharStream input) {
protected LexerATNSimulator.State state;
public Lexer(CharStream input, LexerATNSimulator interpreter) {
super(interpreter);
this.input = input;
this.state = new LexerATNSimulator.State(this);
}
public void reset() {
@ -116,7 +120,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
modeStack.clear();
}
getInterpreter().reset();
getInterpreter().reset(state);
}
/** Return a token from this source; i.e., match a token on the char
@ -131,8 +135,8 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
token = null;
channel = Token.DEFAULT_CHANNEL;
tokenStartCharIndex = input.index();
tokenStartCharPositionInLine = getInterpreter().getCharPositionInLine();
tokenStartLine = getInterpreter().getLine();
tokenStartCharPositionInLine = getInterpreter().getCharPositionInLine(state);
tokenStartLine = getInterpreter().getLine(state);
text = null;
do {
type = Token.INVALID_TYPE;
@ -141,7 +145,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
// " at index "+input.index());
int ttype;
try {
ttype = getInterpreter().match(input, mode);
ttype = getInterpreter().match(state, mode);
}
catch (LexerNoViableAltException e) {
notifyListeners(e); // report error
@ -259,12 +263,12 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
@Override
public int getLine() {
return getInterpreter().getLine();
return getInterpreter().getLine(state);
}
@Override
public int getCharPositionInLine() {
return getInterpreter().getCharPositionInLine();
return getInterpreter().getCharPositionInLine(state);
}
/** What is the index of the current character of lookahead? */
@ -279,7 +283,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
if ( text!=null ) {
return text;
}
return getInterpreter().getText(input);
return getInterpreter().getText(state);
// return ((CharStream)input).substring(tokenStartCharIndex,getCharIndex()-1);
}
@ -315,7 +319,7 @@ public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
}
public void recover(LexerNoViableAltException e) {
getInterpreter().consume(input); // skip a char and try again
getInterpreter().consume(state); // skip a char and try again
}
public void notifyListeners(LexerNoViableAltException e) {

View File

@ -28,6 +28,9 @@
*/
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.atn.ATNSimulator;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.ParserATNSimulator.State;
/** A parser for TokenStreams. "parser grammars" result in a subclass
* of this.
@ -35,10 +38,17 @@ package org.antlr.v4.runtime;
public class Parser extends BaseRecognizer<Token> {
protected TokenStream _input;
public Parser(TokenStream input) {
super(input);
protected ParserATNSimulator.State<Token> state;
public Parser(TokenStream input, ParserATNSimulator<Token> interpreter) {
super(input, interpreter);
state = new ParserATNSimulator.State<Token>(this);
}
public ParserATNSimulator.State<Token> getState() {
return state;
}
@Override
public void reset() {
super.reset(); // reset all recognizer state variables

View File

@ -47,7 +47,12 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
private static final ANTLRErrorListener[] EMPTY_LISTENERS = new ANTLRErrorListener[0];
protected ATNInterpreter _interp;
@NotNull
private final ATNInterpreter _interp;
protected Recognizer(@NotNull ATNInterpreter interpreter) {
this._interp = interpreter;
}
/** Used to print out token names like ID during debugging and
* error reporting. The generated parsers implement a method
@ -63,6 +68,7 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
public ATN getATN() { return null; }
@NotNull
public ATNInterpreter getInterpreter() { return _interp; }
/** What is the error header, normally line/character position information? */

View File

@ -89,98 +89,116 @@ public class LexerATNSimulator extends ATNSimulator {
}
}
@Nullable
protected final Lexer recog;
public static class State {
@Nullable
protected final Lexer recog;
/** The current token's starting index into the character stream.
* Shared across DFA to ATN simulation in case the ATN fails and the
* DFA did not have a previous accept state. In this case, we use the
* ATN-generated exception object.
*/
protected int startIndex = -1;
@Nullable
private final CharStream input;
/** line number 1..n within the input */
protected int line = 1;
/** The current token's starting index into the character stream.
* Shared across DFA to ATN simulation in case the ATN fails and the
* DFA did not have a previous accept state. In this case, we use the
* ATN-generated exception object.
*/
protected int startIndex = -1;
/** The index of the character relative to the beginning of the line 0..n-1 */
protected int charPositionInLine = 0;
/** line number 1..n within the input */
protected int line = 1;
/** The index of the character relative to the beginning of the line 0..n-1 */
protected int charPositionInLine = 0;
protected int mode = Lexer.DEFAULT_MODE;
/** Used during DFA/ATN exec to record the most recent accept configuration info */
@NotNull
protected final DFAExecState dfaPrevAccept = new DFAExecState();
@NotNull
protected final ATNExecState atnPrevAccept = new ATNExecState();
public State(@NotNull Lexer recog) {
this.recog = recog;
this.input = null;
}
public State(@NotNull CharStream input) {
this.recog = null;
this.input = input;
}
public CharStream getInput() {
if (recog != null) {
return recog.getInputStream();
}
return input;
}
}
@NotNull
protected DFA[] dfa;
protected int mode = Lexer.DEFAULT_MODE;
/** Used during DFA/ATN exec to record the most recent accept configuration info */
@NotNull
protected final DFAExecState dfaPrevAccept = new DFAExecState();
@NotNull
protected final ATNExecState atnPrevAccept = new ATNExecState();
public static int ATN_failover = 0;
public static int match_calls = 0;
public LexerATNSimulator(@NotNull ATN atn) {
this(null, atn);
}
public LexerATNSimulator(@Nullable Lexer recog, @NotNull ATN atn) {
super(atn);
dfa = new DFA[atn.modeToStartState.size()];
for (int i=0; i<atn.modeToStartState.size(); i++) {
dfa[i] = new DFA(atn.modeToStartState.get(i));
}
this.recog = recog;
}
public int match(@NotNull CharStream input, int mode) {
public int match(@NotNull State state, int mode) {
match_calls++;
this.mode = mode;
state.mode = mode;
if ( dfa[mode].s0==null ) {
return matchATN(input);
return matchATN(state);
}
else {
return exec(input, dfa[mode].s0);
return exec(state, dfa[mode].s0);
}
}
public void reset() {
dfaPrevAccept.reset();
atnPrevAccept.reset();
startIndex = -1;
line = 1;
charPositionInLine = 0;
mode = Lexer.DEFAULT_MODE;
public void reset(@NotNull State state) {
state.dfaPrevAccept.reset();
state.atnPrevAccept.reset();
state.startIndex = -1;
state.line = 1;
state.charPositionInLine = 0;
state.mode = Lexer.DEFAULT_MODE;
}
// only called from test code from outside
public int matchATN(@NotNull CharStream input) {
int mark = input.mark();
public int matchATN(@NotNull State state) {
int mark = state.getInput().mark();
try {
startIndex = input.index();
ATNState startState = atn.modeToStartState.get(mode);
if ( debug ) System.out.println("mode "+ mode +" start: "+startState);
OrderedHashSet<ATNConfig> s0_closure = computeStartState(input, startState);
int old_mode = mode;
dfa[mode].s0 = addDFAState(s0_closure);
int predict = exec(input, s0_closure);
state.startIndex = state.getInput().index();
ATNState startState = atn.modeToStartState.get(state.mode);
if ( debug ) System.out.println("mode "+ state.mode +" start: "+startState);
OrderedHashSet<ATNConfig> s0_closure = computeStartState(state, startState);
int old_mode = state.mode;
dfa[state.mode].s0 = addDFAState(state, s0_closure);
int predict = exec(state, s0_closure);
if ( debug ) System.out.println("DFA after matchATN: "+dfa[old_mode].toLexerString());
return predict;
}
finally {
if (mark >= 0) {
input.release(mark);
}
state.getInput().release(mark);
}
}
protected int exec(@NotNull CharStream input, @NotNull DFAState s0) {
if ( dfa_debug ) System.out.println("DFA[mode "+(recog==null?0:recog.mode)+"] exec LA(1)=="+
(char)input.LA(1));
protected int exec(@NotNull State state, @NotNull DFAState s0) {
if ( dfa_debug ) System.out.println("DFA[mode "+(state.recog==null?0:state.recog.mode)+"] exec LA(1)=="+
(char)state.getInput().LA(1));
//System.out.println("DFA start of execDFA: "+dfa[mode].toLexerString());
startIndex = input.index();
dfaPrevAccept.reset();
state.startIndex = state.getInput().index();
state.dfaPrevAccept.reset();
LexerNoViableAltException atnException = null;
DFAState s = s0;
int t = input.LA(1);
int t = state.getInput().LA(1);
loop:
while ( true ) {
if ( dfa_debug ) System.out.println("state "+s.stateNumber+" LA(1)=="+(char)t);
@ -190,7 +208,7 @@ public class LexerATNSimulator extends ATNSimulator {
{
try {
ATN_failover++;
return failOverToATN(input, s);
return failOverToATN(state, s);
}
catch (LexerNoViableAltException nvae) {
atnException = nvae;
@ -205,31 +223,31 @@ public class LexerATNSimulator extends ATNSimulator {
if ( s.isAcceptState ) {
if ( dfa_debug ) System.out.println("accept; predict "+s.prediction+
" in state "+s.stateNumber);
markAcceptState(dfaPrevAccept, input);
dfaPrevAccept.state = s;
markAcceptState(state.dfaPrevAccept, state);
state.dfaPrevAccept.state = s;
// keep going unless we're at EOF; check if something else could match
// EOF never in DFA
if ( t==CharStream.EOF ) break;
}
consume(input);
t = input.LA(1);
consume(state);
t = state.getInput().LA(1);
}
if ( dfaPrevAccept.state==null ) {
if ( state.dfaPrevAccept.state==null ) {
// if no accept and EOF is first char, return EOF
if ( t==CharStream.EOF && input.index()==startIndex ) {
if ( t==CharStream.EOF && state.getInput().index()==state.startIndex ) {
return Token.EOF;
}
if ( atnException!=null ) throw atnException;
throw new LexerNoViableAltException(recog, input, startIndex, s.configs);
throw new LexerNoViableAltException(state.recog, state.getInput(), state.startIndex, s.configs);
}
int ruleIndex = dfaPrevAccept.state.ruleIndex;
accept(input, ruleIndex, dfaPrevAccept);
return dfaPrevAccept.state.prediction;
int ruleIndex = state.dfaPrevAccept.state.ruleIndex;
accept(state, ruleIndex, state.dfaPrevAccept);
return state.dfaPrevAccept.state.prediction;
}
protected int exec(@NotNull CharStream input, @NotNull OrderedHashSet<ATNConfig> s0) {
protected int exec(@NotNull State state, @NotNull OrderedHashSet<ATNConfig> s0) {
//System.out.println("enter exec index "+input.index()+" from "+s0);
@NotNull
OrderedHashSet<ATNConfig> closure = new OrderedHashSet<ATNConfig>();
@ -238,22 +256,22 @@ public class LexerATNSimulator extends ATNSimulator {
@NotNull
OrderedHashSet<ATNConfig> reach = new OrderedHashSet<ATNConfig>();
atnPrevAccept.reset();
state.atnPrevAccept.reset();
int t = input.LA(1);
int t = state.getInput().LA(1);
do { // while more work
if ( debug ) System.out.println("in reach starting closure: " + closure);
for (int ci=0; ci<closure.size(); ci++) { // TODO: foreach
ATNConfig c = closure.get(ci);
if ( debug ) System.out.println("testing "+getTokenName(t)+" at "+c.toString(recog, true));
if ( debug ) System.out.println("testing "+getTokenName(t)+" at "+c.toString(state.recog, true));
int n = c.state.getNumberOfTransitions();
for (int ti=0; ti<n; ti++) { // for each transition
Transition trans = c.state.transition(ti);
ATNState target = getReachableTarget(trans, t);
if ( target!=null ) {
closure(new ATNConfig(c, target), reach);
closure(state, new ATNConfig(c, target), reach);
}
}
}
@ -262,7 +280,7 @@ public class LexerATNSimulator extends ATNSimulator {
// we reached state associated with closure for sure, so
// make sure it's defined. worst case, we define s0 from
// start state configs.
DFAState from = addDFAState(closure);
DFAState from = addDFAState(state, closure);
// we got nowhere on t, don't throw out this knowledge; it'd
// cause a failover from DFA later.
addDFAEdge(from, t, ERROR);
@ -270,11 +288,11 @@ public class LexerATNSimulator extends ATNSimulator {
}
// Did we hit a stop state during reach op?
processAcceptStates(input, reach);
processAcceptStates(state, reach);
consume(input);
addDFAEdge(closure, t, reach);
t = input.LA(1);
consume(state);
addDFAEdge(state, closure, t, reach);
t = state.getInput().LA(1);
// swap to avoid reallocating space
// TODO: faster to reallocate?
@ -286,37 +304,37 @@ public class LexerATNSimulator extends ATNSimulator {
} while ( true );
if ( atnPrevAccept.config==null ) {
if ( state.atnPrevAccept.config==null ) {
// if no accept and EOF is first char, return EOF
if ( t==CharStream.EOF && input.index()==startIndex ) {
if ( t==CharStream.EOF && state.getInput().index()==state.startIndex ) {
return Token.EOF;
}
throw new LexerNoViableAltException(recog, input, startIndex, reach);
throw new LexerNoViableAltException(state.recog, state.getInput(), state.startIndex, reach);
}
int ruleIndex = atnPrevAccept.config.state.ruleIndex;
accept(input, ruleIndex, atnPrevAccept);
int ruleIndex = state.atnPrevAccept.config.state.ruleIndex;
accept(state, ruleIndex, state.atnPrevAccept);
return atn.ruleToTokenType[ruleIndex];
}
protected void processAcceptStates(@NotNull CharStream input, @NotNull OrderedHashSet<ATNConfig> reach) {
protected void processAcceptStates(@NotNull State state, @NotNull OrderedHashSet<ATNConfig> reach) {
for (int ci=0; ci<reach.size(); ci++) {
ATNConfig c = reach.get(ci);
if ( c.state instanceof RuleStopState) {
if ( debug ) {
System.out.println("in reach we hit accept state "+c+" index "+
input.index()+", reach="+reach+
", prevAccept="+atnPrevAccept.config+
", prevIndex="+atnPrevAccept.index);
state.getInput().index()+", reach="+reach+
", prevAccept="+state.atnPrevAccept.config+
", prevIndex="+state.atnPrevAccept.index);
}
int index = input.index();
if ( index > atnPrevAccept.index ) {
int index = state.getInput().index();
if ( index > state.atnPrevAccept.index ) {
// will favor prev accept at same index so "int" is keyword not ID
markAcceptState(atnPrevAccept, input);
atnPrevAccept.config = c;
markAcceptState(state.atnPrevAccept, state);
state.atnPrevAccept.config = c;
if ( debug ) {
System.out.println("mark "+c+" @ index="+index+", "+
atnPrevAccept.line+":"+atnPrevAccept.charPos);
state.atnPrevAccept.line+":"+state.atnPrevAccept.charPos);
}
}
@ -331,21 +349,21 @@ public class LexerATNSimulator extends ATNSimulator {
}
}
protected void accept(@NotNull CharStream input, int ruleIndex, @NotNull ExecState prevAccept) {
protected void accept(@NotNull State state, int ruleIndex, @NotNull ExecState prevAccept) {
if ( debug ) {
if ( recog!=null ) System.out.println("ACTION "+
recog.getRuleNames()[ruleIndex]+
if ( state.recog!=null ) System.out.println("ACTION "+
state.recog.getRuleNames()[ruleIndex]+
":"+ruleIndex);
else System.out.println("ACTION "+ruleIndex+":"+ruleIndex);
}
int actionIndex = atn.ruleToActionIndex[ruleIndex];
if ( actionIndex>=0 && recog!=null ) recog.action(null, ruleIndex, actionIndex);
if ( actionIndex>=0 && state.recog!=null ) state.recog.action(null, ruleIndex, actionIndex);
// seek to after last char in token
input.seek(prevAccept.index);
line = prevAccept.line;
charPositionInLine = prevAccept.charPos;
consume(input);
state.getInput().seek(prevAccept.index);
state.line = prevAccept.line;
state.charPositionInLine = prevAccept.charPos;
consume(state);
}
@Nullable
@ -397,7 +415,7 @@ public class LexerATNSimulator extends ATNSimulator {
}
@NotNull
protected OrderedHashSet<ATNConfig> computeStartState(@NotNull IntStream input,
protected OrderedHashSet<ATNConfig> computeStartState(@NotNull State state,
@NotNull ATNState p)
{
RuleContext initialContext = RuleContext.EMPTY;
@ -405,22 +423,22 @@ public class LexerATNSimulator extends ATNSimulator {
for (int i=0; i<p.getNumberOfTransitions(); i++) {
ATNState target = p.transition(i).target;
ATNConfig c = new ATNConfig(target, i+1, initialContext);
closure(c, configs);
closure(state, c, configs);
}
return configs;
}
protected void closure(@NotNull ATNConfig config, @NotNull OrderedHashSet<ATNConfig> configs) {
protected void closure(@NotNull State state, @NotNull ATNConfig config, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( debug ) {
System.out.println("closure("+config.toString(recog, true)+")");
System.out.println("closure("+config.toString(state.recog, true)+")");
}
// TODO? if ( closure.contains(t) ) return;
if ( config.state instanceof RuleStopState ) {
if ( debug ) {
if ( recog!=null ) System.out.println("closure at "+
recog.getRuleNames()[config.state.ruleIndex]+
if ( state.recog!=null ) System.out.println("closure at "+
state.recog.getRuleNames()[config.state.ruleIndex]+
" rule stop "+config);
else System.out.println("closure at rule stop "+config);
}
@ -433,7 +451,7 @@ public class LexerATNSimulator extends ATNSimulator {
RuleTransition rt = (RuleTransition)invokingState.transition(0);
ATNState retState = rt.followState;
ATNConfig c = new ATNConfig(retState, config.alt, newContext);
closure(c, configs);
closure(state, c, configs);
return;
}
@ -445,13 +463,13 @@ public class LexerATNSimulator extends ATNSimulator {
ATNState p = config.state;
for (int i=0; i<p.getNumberOfTransitions(); i++) {
Transition t = p.transition(i);
ATNConfig c = getEpsilonTarget(config, t);
if ( c!=null ) closure(c, configs);
ATNConfig c = getEpsilonTarget(state, config, t);
if ( c!=null ) closure(state, c, configs);
}
}
@Nullable
public ATNConfig getEpsilonTarget(@NotNull ATNConfig config, @NotNull Transition t) {
public ATNConfig getEpsilonTarget(@NotNull State state, @NotNull ATNConfig config, @NotNull Transition t) {
ATNState p = config.state;
ATNConfig c = null;
if ( t.getClass() == RuleTransition.class ) {
@ -461,7 +479,7 @@ public class LexerATNSimulator extends ATNSimulator {
}
else if ( t.getClass() == PredicateTransition.class ) {
PredicateTransition pt = (PredicateTransition)t;
if ( recog.sempred(null, pt.ruleIndex, pt.predIndex) ) {
if ( state.recog.sempred(null, pt.ruleIndex, pt.predIndex) ) {
c = new ATNConfig(config, t.target);
c.traversedPredicate = true;
}
@ -476,37 +494,38 @@ public class LexerATNSimulator extends ATNSimulator {
return c;
}
int failOverToATN(@NotNull CharStream input, @NotNull DFAState s) {
if ( dfa_debug ) System.out.println("no edge for "+(char)input.LA(1));
int failOverToATN(@NotNull State state, @NotNull DFAState s) {
if ( dfa_debug ) System.out.println("no edge for "+(char)state.getInput().LA(1));
if ( dfa_debug ) {
System.out.println("ATN exec upon "+
input.substring(startIndex,input.index())+
state.getInput().substring(state.startIndex, state.getInput().index())+
" at DFA state "+s.stateNumber+" = "+s.configs);
}
int ttype = exec(input, s.configs);
int ttype = exec(state, s.configs);
if ( dfa_debug ) {
System.out.println("back from DFA update, ttype="+ttype+
", dfa[mode "+mode+"]=\n"+
dfa[mode].toLexerString());
", dfa[mode "+state.mode+"]=\n"+
dfa[state.mode].toLexerString());
}
// action already executed by ATN
// we've updated DFA, exec'd action, and have our deepest answer
return ttype;
}
protected void markAcceptState(@NotNull ExecState state, @NotNull CharStream input) {
state.index = input.index();
state.line = line;
state.charPos = charPositionInLine;
protected void markAcceptState(@NotNull ExecState execState, @NotNull State state) {
execState.index = state.getInput().index();
execState.line = state.line;
execState.charPos = state.charPositionInLine;
}
protected void addDFAEdge(@NotNull OrderedHashSet<ATNConfig> p,
protected void addDFAEdge(@NotNull State state,
@NotNull OrderedHashSet<ATNConfig> p,
int t,
@NotNull OrderedHashSet<ATNConfig> q)
{
// System.out.println("MOVE "+p+" -> "+q+" upon "+getTokenName(t));
DFAState from = addDFAState(p);
DFAState to = addDFAState(q);
DFAState from = addDFAState(state, p);
DFAState to = addDFAState(state, q);
addDFAEdge(from, t, to);
}
@ -547,9 +566,9 @@ public class LexerATNSimulator extends ATNSimulator {
test them, we cannot cash the DFA state target of ID.
*/
@Nullable
protected DFAState addDFAState(@NotNull OrderedHashSet<ATNConfig> configs) {
protected DFAState addDFAState(@NotNull State state, @NotNull OrderedHashSet<ATNConfig> configs) {
DFAState proposed = new DFAState(configs);
DFAState existing = dfa[mode].states.get(proposed);
DFAState existing = dfa[state.mode].states.get(proposed);
if ( existing!=null ) return existing;
DFAState newState = proposed;
@ -573,10 +592,10 @@ public class LexerATNSimulator extends ATNSimulator {
if ( traversedPredicate ) return null; // cannot cache
newState.stateNumber = dfa[mode].states.size();
newState.stateNumber = dfa[state.mode].states.size();
newState.configs = new OrderedHashSet<ATNConfig>();
newState.configs.addAll(configs);
dfa[mode].states.put(newState, newState);
dfa[state.mode].states.put(newState, newState);
return newState;
}
@ -587,27 +606,27 @@ public class LexerATNSimulator extends ATNSimulator {
/** Get the text of the current token */
@NotNull
public String getText(@NotNull CharStream input) {
return input.substring(this.startIndex, input.index());
public String getText(@NotNull State state) {
return state.getInput().substring(state.startIndex, state.getInput().index());
}
public int getLine() {
return line;
public int getLine(@NotNull State state) {
return state.line;
}
public int getCharPositionInLine() {
return charPositionInLine;
public int getCharPositionInLine(@NotNull State state) {
return state.charPositionInLine;
}
public void consume(@NotNull CharStream input) {
int curChar = input.LA(1);
public void consume(@NotNull State state) {
int curChar = state.getInput().LA(1);
if ( curChar=='\n' ) {
line++;
charPositionInLine=0;
state.line++;
state.charPositionInLine=0;
} else {
charPositionInLine++;
state.charPositionInLine++;
}
input.consume();
state.getInput().consume();
}
@NotNull

View File

@ -46,127 +46,151 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
public static int retry_with_context = 0;
public static int retry_with_context_indicates_no_conflict = 0;
@Nullable
protected final BaseRecognizer<Symbol> parser;
public static class State<Symbol> {
@Nullable
protected final BaseRecognizer<Symbol> parser;
private final SymbolStream<Symbol> input;
public boolean userWantsCtxSensitive = false;
/** This is the original context upon entry to the ATN simulator.
* ATNConfig objects carry on tracking the new context derived from
* the decision point. This field is used instead of passing the value
* around to the various functions, which would be confusing. Its
* value is reset upon prediction call to adaptivePredict() or the
* predictATN/DFA methods.
*
* The full stack at any moment is [config.outerContext + config.context].
*/
@NotNull
public RuleContext outerContext = RuleContext.EMPTY;
@Nullable
public ATNConfig prevAccept; // TODO Move down? used to avoid passing int down and back up in method calls
public int prevAcceptIndex = -1;
public State(@NotNull BaseRecognizer<Symbol> parser) {
this.parser = parser;
this.input = null;
}
public State(@NotNull SymbolStream<Symbol> input) {
this.parser = null;
this.input = input;
}
public BaseRecognizer<Symbol> getParser() {
return parser;
}
public SymbolStream<Symbol> getInput() {
if (parser != null) {
return parser.getInputStream();
} else {
return input;
}
}
}
@NotNull
public final Map<RuleContext, DFA[]> ctxToDFAs;
public Map<RuleContext, DFA>[] decisionToDFAPerCtx; // TODO: USE THIS ONE
@NotNull
public final DFA[] decisionToDFA;
protected boolean userWantsCtxSensitive = false;
/** This is the original context upon entry to the ATN simulator.
* ATNConfig objects carry on tracking the new context derived from
* the decision point. This field is used instead of passing the value
* around to the various functions, which would be confusing. Its
* value is reset upon prediction call to adaptivePredict() or the
* predictATN/DFA methods.
*
* The full stack at any moment is [config.outerContext + config.context].
*/
@NotNull
protected RuleContext outerContext = RuleContext.EMPTY;
@Nullable
protected ATNConfig prevAccept; // TODO Move down? used to avoid passing int down and back up in method calls
protected int prevAcceptIndex = -1;
public ParserATNSimulator(@NotNull ATN atn) {
this(null, atn);
}
public ParserATNSimulator(@Nullable BaseRecognizer<Symbol> parser, @NotNull ATN atn) {
super(atn);
this.parser = parser;
ctxToDFAs = new HashMap<RuleContext, DFA[]>();
// TODO (sam): why distinguish on parser != null?
decisionToDFA = new DFA[atn.getNumberOfDecisions() + (parser != null ? 1 : 0)];
decisionToDFA = new DFA[atn.getNumberOfDecisions() + 1];
// DOTGenerator dot = new DOTGenerator(null);
// System.out.println(dot.getDOT(atn.rules.get(0), parser.getRuleNames()));
// System.out.println(dot.getDOT(atn.rules.get(1), parser.getRuleNames()));
}
public int adaptivePredict(@NotNull SymbolStream<Symbol> input, int decision, @Nullable RuleContext outerContext) {
public int adaptivePredict(@NotNull State<Symbol> state, int decision, @Nullable RuleContext outerContext) {
predict_calls++;
DFA dfa = decisionToDFA[decision];
if ( dfa==null || dfa.s0==null ) {
ATNState startState = atn.decisionToState.get(decision);
decisionToDFA[decision] = dfa = new DFA(startState);
dfa.decision = decision;
return predictATN(dfa, input, outerContext, false);
return predictATN(dfa, state, outerContext, false);
}
else {
//dump(dfa);
// start with the DFA
int m = input.mark();
int index = input.index();
int m = state.getInput().mark();
int index = state.getInput().index();
try {
int alt = execDFA(input, dfa, dfa.s0, outerContext);
int alt = execDFA(state, dfa, dfa.s0, outerContext);
return alt;
}
finally {
input.seek(index);
input.release(m);
state.getInput().seek(index);
state.getInput().release(m);
}
}
}
public int predictATN(@NotNull DFA dfa, @NotNull SymbolStream<Symbol> input,
public int predictATN(@NotNull DFA dfa, @NotNull State<Symbol> state,
@Nullable RuleContext outerContext,
boolean useContext)
{
if ( outerContext==null ) outerContext = RuleContext.EMPTY;
this.outerContext = outerContext;
state.outerContext = outerContext;
if ( debug ) System.out.println("ATN decision "+dfa.decision+
" exec LA(1)=="+ getLookaheadName(input) +
", outerContext="+outerContext.toString(parser));
" exec LA(1)=="+ getLookaheadName(state) +
", outerContext="+outerContext.toString(state.parser));
RuleContext ctx = RuleContext.EMPTY;
if ( useContext ) ctx = outerContext;
OrderedHashSet<ATNConfig> s0_closure =
computeStartState(dfa.decision, dfa.atnStartState, ctx);
computeStartState(state, dfa.decision, dfa.atnStartState, ctx);
dfa.s0 = addDFAState(dfa, s0_closure);
if ( prevAccept!=null ) {
if ( state.prevAccept!=null ) {
dfa.s0.isAcceptState = true;
dfa.s0.prediction = prevAccept.alt;
dfa.s0.prediction = state.prevAccept.alt;
}
int alt = 0;
int m = input.mark();
int index = input.index();
int m = state.getInput().mark();
int index = state.getInput().index();
try {
alt = execATN(input, dfa, m, s0_closure, useContext);
alt = execATN(state, dfa, m, s0_closure, useContext);
}
catch (NoViableAltException nvae) {
if ( debug ) dumpDeadEndConfigs(nvae);
if ( debug ) dumpDeadEndConfigs(state, nvae);
throw nvae;
}
finally {
input.seek(index);
input.release(m);
state.getInput().seek(index);
state.getInput().release(m);
}
if ( debug ) System.out.println("DFA after predictATN: "+dfa.toString());
return alt;
}
// doesn't create DFA when matching
public int matchATN(@NotNull SymbolStream<Symbol> input, @NotNull ATNState startState) {
public int matchATN(@NotNull State<Symbol> state, @NotNull ATNState startState) {
DFA dfa = new DFA(startState);
RuleContext ctx = RuleContext.EMPTY;
OrderedHashSet<ATNConfig> s0_closure = computeStartState(dfa.decision, startState, ctx);
return execATN(input, dfa, input.index(), s0_closure, false);
OrderedHashSet<ATNConfig> s0_closure = computeStartState(state, dfa.decision, startState, ctx);
return execATN(state, dfa, state.getInput().index(), s0_closure, false);
}
public int execDFA(@NotNull SymbolStream<Symbol> input, @NotNull DFA dfa, @NotNull DFAState s0, @Nullable RuleContext outerContext) {
public int execDFA(@NotNull State<Symbol> state, @NotNull DFA dfa, @NotNull DFAState s0, @Nullable RuleContext outerContext) {
// dump(dfa);
if ( outerContext==null ) outerContext = RuleContext.EMPTY;
this.outerContext = outerContext;
state.outerContext = outerContext;
if ( dfa_debug ) System.out.println("DFA decision "+dfa.decision+
" exec LA(1)=="+ getLookaheadName(input) +
", outerContext="+outerContext.toString(parser));
" exec LA(1)=="+ getLookaheadName(state) +
", outerContext="+outerContext.toString(state.parser));
DFAState prevAcceptState = null;
DFAState s = s0;
int t = input.LA(1);
int startIndex = input.index();
int t = state.getInput().LA(1);
int startIndex = state.getInput().index();
loop:
while ( true ) {
if ( dfa_debug ) System.out.println("DFA state "+s.stateNumber+" LA(1)=="+t);
@ -178,9 +202,9 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
if ( predI!=null ) return predI;
// System.out.println("start all over with ATN; can't use DFA");
// start all over with ATN; can't use DFA
input.seek(startIndex);
state.getInput().seek(startIndex);
DFA throwAwayDFA = new DFA(dfa.atnStartState);
int alt = execATN(input, throwAwayDFA, startIndex, s0.configs, false);
int alt = execATN(state, throwAwayDFA, startIndex, s0.configs, false);
s.ctxToPrediction.put(outerContext, alt);
return alt;
}
@ -197,19 +221,19 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
int alt = -1;
if ( dfa_debug ) {
System.out.println("ATN exec upon "+
getInputString(input, startIndex) +
getInputString(state.getInput(), startIndex) +
" at DFA state "+s.stateNumber);
}
try {
alt = execATN(input, dfa, startIndex, s.configs, false);
alt = execATN(state, dfa, startIndex, s.configs, false);
// this adds edge even if next state is accept for
// same alt; e.g., s0-A->:s1=>2-B->:s2=>2
// TODO: This next stuff kills edge, but extra states remain. :(
if ( s.isAcceptState && alt!=-1 ) {
DFAState d = s.edges[input.LA(1)+1];
DFAState d = s.edges[state.getInput().LA(1)+1];
if ( d.isAcceptState && d.prediction==s.prediction ) {
// we can carve it out.
s.edges[input.LA(1)+1] = ERROR; // IGNORE really not error
s.edges[state.getInput().LA(1)+1] = ERROR; // IGNORE really not error
}
}
if ( dfa_debug ) {
@ -228,11 +252,11 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
DFAState target = s.edges[t+1];
if ( target == ERROR ) {
throw noViableAlt(input, outerContext, s.configs, startIndex);
throw noViableAlt(state, outerContext, s.configs, startIndex);
}
s = target;
input.consume();
t = input.LA(1);
state.getInput().consume();
t = state.getInput().LA(1);
}
if ( prevAcceptState==null ) {
if ( debug ) System.out.println("!!! no viable alt in dfa");
@ -253,13 +277,13 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
return "n/a";
}
public int execATN(@NotNull SymbolStream<Symbol> input,
public int execATN(@NotNull State<Symbol> state,
@NotNull DFA dfa,
int startIndex,
@NotNull OrderedHashSet<ATNConfig> s0,
boolean useContext)
{
if ( debug ) System.out.println("execATN decision "+dfa.decision+" exec LA(1)=="+ getLookaheadName(input));
if ( debug ) System.out.println("execATN decision "+dfa.decision+" exec LA(1)=="+ getLookaheadName(state));
ATN_failover++;
OrderedHashSet<ATNConfig> closure = new OrderedHashSet<ATNConfig>();
@ -267,18 +291,18 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
if ( debug ) System.out.println("start state closure="+closure);
int t = input.LA(1);
if ( t==Token.EOF && prevAccept!=null ) {
int t = state.getInput().LA(1);
if ( t==Token.EOF && state.prevAccept!=null ) {
// computeStartState must have reached end of rule
return prevAccept.alt;
return state.prevAccept.alt;
}
DecisionState decState = null;
if ( atn.decisionToState.size()>0 ) decState = atn.decisionToState.get(dfa.decision);
if ( debug ) System.out.println("decision state = "+decState);
prevAccept = null;
prevAcceptIndex = -1;
state.prevAccept = null;
state.prevAcceptIndex = -1;
OrderedHashSet<ATNConfig> reach = new OrderedHashSet<ATNConfig>();
do { // while more work
@ -286,39 +310,39 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
int ncl = closure.size();
for (int ci=0; ci<ncl; ci++) { // TODO: foreach
ATNConfig c = closure.get(ci);
if ( debug ) System.out.println("testing "+getTokenName(t)+" at "+c.toString());
if ( debug ) System.out.println("testing "+getTokenName(state, t)+" at "+c.toString());
int n = c.state.getNumberOfTransitions();
for (int ti=0; ti<n; ti++) { // for each transition
Transition trans = c.state.transition(ti);
ATNState target = getReachableTarget(trans, t);
if ( target!=null ) {
Set<ATNConfig> closureBusy = new HashSet<ATNConfig>();
closure(new ATNConfig(c, target), reach, decState, closureBusy);
closure(state, new ATNConfig(c, target), reach, decState, closureBusy);
}
}
}
// resolve ambig in DFAState for reach
Set<Integer> ambigAlts = getAmbiguousAlts(reach);
Set<Integer> ambigAlts = getAmbiguousAlts(state, reach);
if ( ambigAlts!=null ) {
if ( debug ) {
int i = -1;
if ( outerContext!=null && outerContext.s>=0 ) {
i = atn.states.get(outerContext.s).ruleIndex;
if ( state.outerContext!=null && state.outerContext.s>=0 ) {
i = atn.states.get(state.outerContext.s).ruleIndex;
}
String rname = getRuleName(i);
String rname = getRuleName(state, i);
System.out.println("AMBIG dec "+dfa.decision+" in "+rname+" for alt "+ambigAlts+" upon "+
getInputString(input, startIndex));
getInputString(state.getInput(), startIndex));
System.out.println("REACH="+reach);
}
dfa.conflict = true; // at least one DFA state is ambiguous
if ( !userWantsCtxSensitive ) reportConflict(startIndex, input.index(), ambigAlts, reach);
if ( !state.userWantsCtxSensitive ) reportConflict(state, startIndex, state.getInput().index(), ambigAlts, reach);
// ATNState loc = atn.states.get(outerContext.s);
// String rname = recog.getRuleNames()[loc.ruleIndex];
// System.out.println("AMBIG orig="+outerContext.toString((BaseRecognizer)recog)+" for alt "+ambigAlts+" upon "+
// input.toString(startIndex, input.index()));
if ( !userWantsCtxSensitive || useContext ) {
if ( !state.userWantsCtxSensitive || useContext ) {
// resolve ambiguity
if ( decState.isGreedy ) {
// if greedy, resolve in favor of alt coming first
@ -331,7 +355,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
}
else {
return retryWithContext(input, dfa, startIndex, outerContext,
return retryWithContext(state, dfa, startIndex, state.outerContext,
closure, t, reach, ambigAlts);
}
}
@ -342,7 +366,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
if ( uniqueAlt!=ATN.INVALID_ALT_NUMBER ) {
if ( debug ) System.out.println("PREDICT alt "+uniqueAlt+
" decision "+dfa.decision+
" at index "+input.index());
" at index "+state.getInput().index());
addDFAEdge(dfa, closure, t, reach);
makeAcceptState(dfa, reach, uniqueAlt);
return uniqueAlt;
@ -354,8 +378,8 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
ATNConfig cstop = configWithAltAtStopState(reach, exitAlt);
if ( cstop!=null ) {
if ( debug ) System.out.println("nongreedy at stop state for exit branch");
prevAccept = cstop;
prevAcceptIndex = input.index();
state.prevAccept = cstop;
state.prevAcceptIndex = state.getInput().index();
break;
}
}
@ -366,9 +390,9 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
// If we matched t anywhere, need to consume and add closer-t->reach DFA edge
// else error if no previous accept
input.consume();
state.getInput().consume();
addDFAEdge(dfa, closure, t, reach);
t = input.LA(1);
t = state.getInput().LA(1);
// swap to avoid reallocating space
OrderedHashSet<ATNConfig> tmp = reach;
@ -377,13 +401,13 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
reach.clear(); // TODO: THIS MIGHT BE SLOW! kills each element; realloc might be faster
} while ( true );
if ( prevAccept==null ) {
if ( state.prevAccept==null ) {
// System.out.println("no viable token at input "+ getLookaheadName(input) +", index "+input.index());
throw noViableAlt(input, outerContext, closure, startIndex);
throw noViableAlt(state, state.outerContext, closure, startIndex);
}
if ( debug ) System.out.println("PREDICT " + prevAccept + " index " + prevAccept.alt);
return prevAccept.alt;
if ( debug ) System.out.println("PREDICT " + state.prevAccept + " index " + state.prevAccept.alt);
return state.prevAccept.alt;
}
protected int resolveToMinAlt(@NotNull OrderedHashSet<ATNConfig> reach, @NotNull Set<Integer> ambigAlts) {
@ -407,7 +431,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
return exitAlt;
}
public int retryWithContext(@NotNull SymbolStream<Symbol> input,
public int retryWithContext(@NotNull State<Symbol> state,
@NotNull DFA dfa,
int startIndex,
@NotNull RuleContext originalContext,
@ -418,39 +442,39 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
{
// ASSUMES PREDICT ONLY
retry_with_context++;
int old_k = input.index();
int old_k = state.getInput().index();
// retry using context, if any; if none, kill all but min as before
if ( debug ) System.out.println("RETRY "+ getInputString(input, startIndex) +
if ( debug ) System.out.println("RETRY "+ getInputString(state.getInput(), startIndex) +
" with ctx="+ originalContext);
int min = getMinAlt(ambigAlts);
if ( originalContext==RuleContext.EMPTY ) {
// no point in retrying with ctx since it's same.
// this implies that we have a true ambiguity
reportAmbiguity(startIndex, input.index(), ambigAlts, reach);
reportAmbiguity(state, startIndex, state.getInput().index(), ambigAlts, reach);
return min;
}
// otherwise we have to retry with context, filling in tmp DFA.
// if it comes back with conflict, we have a true ambiguity
input.seek(startIndex); // rewind
state.getInput().seek(startIndex); // rewind
DFA ctx_dfa = new DFA(dfa.atnStartState);
int ctx_alt = predictATN(ctx_dfa, input, originalContext, true);
int ctx_alt = predictATN(ctx_dfa, state, originalContext, true);
if ( debug ) System.out.println("retry predicts "+ctx_alt+" vs "+getMinAlt(ambigAlts)+
" with conflict="+ctx_dfa.conflict+
" dfa="+ctx_dfa);
if ( ctx_dfa.conflict ) {
// System.out.println("retry gives ambig for "+input.toString(startIndex, input.index()));
reportAmbiguity(startIndex, input.index(), ambigAlts, reach);
// System.out.println("retry gives ambig for "+state.getInput().toString(startIndex, state.getInput().index()));
reportAmbiguity(state, startIndex, state.getInput().index(), ambigAlts, reach);
}
else {
// System.out.println("NO ambig for "+input.toString(startIndex, input.index()));
// System.out.println("NO ambig for "+state.getInput().toString(startIndex, state.getInput().index()));
// System.out.println(ctx_dfa.toString(parser.getTokenNames()));
if ( old_k != input.index() ) {
System.out.println("ACK!!!!!!!! diff k; old="+(old_k-startIndex+1)+", new="+(input.index()-startIndex+1));
if ( old_k != state.getInput().index() ) {
System.out.println("ACK!!!!!!!! diff k; old="+(old_k-startIndex+1)+", new="+(state.getInput().index()-startIndex+1));
}
retry_with_context_indicates_no_conflict++;
reportContextSensitivity(startIndex, input.index(), ambigAlts, reach);
reportContextSensitivity(state, startIndex, state.getInput().index(), ambigAlts, reach);
}
// it's not context-sensitive; true ambig. fall thru to strip dead alts
@ -469,11 +493,11 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
@NotNull
public OrderedHashSet<ATNConfig> computeStartState(int decision, @NotNull ATNState p, @Nullable RuleContext ctx) {
public OrderedHashSet<ATNConfig> computeStartState(@NotNull State<Symbol> state, int decision, @NotNull ATNState p, @Nullable RuleContext ctx) {
RuleContext initialContext = ctx; // always at least the implicit call to start rule
OrderedHashSet<ATNConfig> configs = new OrderedHashSet<ATNConfig>();
prevAccept = null; // might reach end rule; track
prevAcceptIndex = -1;
state.prevAccept = null; // might reach end rule; track
state.prevAcceptIndex = -1;
DecisionState decState = null;
if ( atn.decisionToState.size()>0 ) decState = atn.decisionToState.get(decision);
@ -482,7 +506,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
ATNState target = p.transition(i).target;
ATNConfig c = new ATNConfig(target, i+1, initialContext);
Set<ATNConfig> closureBusy = new HashSet<ATNConfig>();
closure(c, configs, decState, closureBusy);
closure(state, c, configs, decState, closureBusy);
}
return configs;
@ -520,7 +544,8 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
ambig detection thought :(
*/
protected void closure(@NotNull ATNConfig config,
protected void closure(@NotNull State<Symbol> state,
@NotNull ATNConfig config,
@NotNull OrderedHashSet<ATNConfig> configs,
@Nullable DecisionState decState,
@NotNull Set<ATNConfig> closureBusy)
@ -542,7 +567,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
// gotten that context AFTER having fallen off a rule.
// Make sure we track that we are now out of context.
c.reachesIntoOuterContext = config.reachesIntoOuterContext;
closure(c, configs, decState, closureBusy);
closure(state, c, configs, decState, closureBusy);
return;
}
else {
@ -550,13 +575,13 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
if ( decState!=null && !decState.isGreedy ) {
if ( debug ) System.out.println("nongreedy decision state = "+decState);
if ( debug ) System.out.println("NONGREEDY at stop state of "+
getRuleName(config.state.ruleIndex));
getRuleName(state, config.state.ruleIndex));
// don't purse past end of a rule for any nongreedy decision
configs.add(config);
return;
}
if ( debug ) System.out.println("FALLING off rule "+
getRuleName(config.state.ruleIndex));
getRuleName(state, config.state.ruleIndex));
}
}
@ -567,7 +592,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
for (int i=0; i<p.getNumberOfTransitions(); i++) {
Transition t = p.transition(i);
boolean ignorePreds = config.traversedAction;
ATNConfig c = getEpsilonTarget(config, t, ignorePreds);
ATNConfig c = getEpsilonTarget(state, config, t, ignorePreds);
if ( c!=null ) {
if ( config.state instanceof RuleStopState ) {
// fell off end of rule.
@ -576,24 +601,24 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
// preds if this is > 0.
c.reachesIntoOuterContext++;
}
closure(c, configs, decState, closureBusy);
closure(state, c, configs, decState, closureBusy);
}
}
}
@NotNull
private String getRuleName(int index) {
if ( parser!=null && index>=0 ) return parser.getRuleNames()[index];
private String getRuleName(State<Symbol> state, int index) {
if ( state.parser!=null && index>=0 ) return state.parser.getRuleNames()[index];
return "<rule "+index+">";
}
@Nullable
public ATNConfig getEpsilonTarget(@NotNull ATNConfig config, @NotNull Transition t, boolean ignorePreds) {
public ATNConfig getEpsilonTarget(@NotNull State<Symbol> state, @NotNull ATNConfig config, @NotNull Transition t, boolean ignorePreds) {
if ( t instanceof RuleTransition ) {
return ruleTransition(config, t);
return ruleTransition(state, config, t);
}
else if ( t instanceof PredicateTransition ) {
return predTransition(config, (PredicateTransition)t, ignorePreds);
return predTransition(state, config, (PredicateTransition)t, ignorePreds);
}
else if ( t instanceof ActionTransition ) {
return actionTransition(config, (ActionTransition)t);
@ -618,14 +643,14 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
@Nullable
public ATNConfig predTransition(@NotNull ATNConfig config, @NotNull PredicateTransition pt,
public ATNConfig predTransition(@NotNull State<Symbol> state, @NotNull ATNConfig config, @NotNull PredicateTransition pt,
boolean ignorePreds)
{
if ( debug ) {
System.out.println("PRED (ignore="+ignorePreds+") "+pt.ruleIndex+":"+pt.predIndex+
", ctx dependent="+pt.isCtxDependent);
if ( parser != null ) System.out.println("rule surrounding pred is "+
parser.getRuleNames()[pt.ruleIndex]);
if ( state.parser != null ) System.out.println("rule surrounding pred is "+
state.parser.getRuleNames()[pt.ruleIndex]);
}
// We know the correct context and exactly one spot: in the original
// rule that invokes the ATN simulation. We know we are in this rule
@ -634,7 +659,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
boolean inContext =
config.context==RuleContext.EMPTY && config.reachesIntoOuterContext==0;
RuleContext ctx = null;
if ( inContext ) ctx = outerContext;
if ( inContext ) ctx = state.outerContext;
// We see through the predicate if:
// 1) we are ignoring them
@ -645,8 +670,8 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
ATNConfig c = null;
boolean seeThroughPred =
ignorePreds ||
(!ignorePreds&&!pt.isCtxDependent&&parser.sempred(ctx, pt.ruleIndex, pt.predIndex))||
(!ignorePreds&&pt.isCtxDependent&&inContext&&parser.sempred(ctx, pt.ruleIndex, pt.predIndex));
(!ignorePreds&&!pt.isCtxDependent&&state.parser.sempred(ctx, pt.ruleIndex, pt.predIndex))||
(!ignorePreds&&pt.isCtxDependent&&inContext&&state.parser.sempred(ctx, pt.ruleIndex, pt.predIndex));
if ( seeThroughPred ) {
c = new ATNConfig(config, pt.target);
c.traversedPredicate = true;
@ -655,9 +680,9 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
@NotNull
public ATNConfig ruleTransition(@NotNull ATNConfig config, @NotNull Transition t) {
public ATNConfig ruleTransition(@NotNull State<Symbol> state, @NotNull ATNConfig config, @NotNull Transition t) {
if ( debug ) {
System.out.println("CALL rule "+getRuleName(t.target.ruleIndex)+
System.out.println("CALL rule "+getRuleName(state, t.target.ruleIndex)+
", ctx="+config.context);
}
ATNState p = config.state;
@ -666,17 +691,17 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
return new ATNConfig(config, t.target, newContext);
}
public void reportConflict(int startIndex, int stopIndex, @NotNull Set<Integer> alts, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( parser!=null ) parser.reportConflict(startIndex, stopIndex, alts, configs);
public void reportConflict(@NotNull State<Symbol> state, int startIndex, int stopIndex, @NotNull Set<Integer> alts, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( state.parser!=null ) state.parser.reportConflict(startIndex, stopIndex, alts, configs);
}
public void reportContextSensitivity(int startIndex, int stopIndex, @NotNull Set<Integer> alts, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( parser!=null ) parser.reportContextSensitivity(startIndex, stopIndex, alts, configs);
public void reportContextSensitivity(@NotNull State<Symbol> state, int startIndex, int stopIndex, @NotNull Set<Integer> alts, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( state.parser!=null ) state.parser.reportContextSensitivity(startIndex, stopIndex, alts, configs);
}
/** If context sensitive parsing, we know it's ambiguity not conflict */
public void reportAmbiguity(int startIndex, int stopIndex, @NotNull Set<Integer> alts, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( parser!=null ) parser.reportAmbiguity(startIndex, stopIndex, alts, configs);
public void reportAmbiguity(@NotNull State<Symbol> state, int startIndex, int stopIndex, @NotNull Set<Integer> alts, @NotNull OrderedHashSet<ATNConfig> configs) {
if ( state.parser!=null ) state.parser.reportAmbiguity(startIndex, stopIndex, alts, configs);
}
public static int getUniqueAlt(@NotNull Collection<ATNConfig> configs) {
@ -705,7 +730,7 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
@Nullable
public Set<Integer> getAmbiguousAlts(@NotNull OrderedHashSet<ATNConfig> configs) {
public Set<Integer> getAmbiguousAlts(@NotNull State<Symbol> state, @NotNull OrderedHashSet<ATNConfig> configs) {
// System.err.println("check ambiguous "+configs);
Set<Integer> ambigAlts = null;
int numConfigs = configs.size();
@ -732,9 +757,9 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
if ( debug ) {
System.out.println("we reach state "+c.state.stateNumber+
" in rule "+
(parser !=null ? getRuleName(c.state.ruleIndex) :"n/a")+
" alts "+goal.alt+","+c.alt+" from ctx "+goal.context.toString(parser)
+" and "+ c.context.toString(parser));
(state.parser !=null ? getRuleName(state, c.state.ruleIndex) :"n/a")+
" alts "+goal.alt+","+c.alt+" from ctx "+goal.context.toString(state.parser)
+" and "+ c.context.toString(state.parser));
}
if ( ambigAlts==null ) ambigAlts = new HashSet<Integer>();
ambigAlts.add(goal.alt);
@ -820,13 +845,13 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
}
@NotNull
public String getTokenName(int t) {
public String getTokenName(@NotNull State<Symbol> state, int t) {
if ( t==-1 ) return "EOF";
if ( parser!=null && parser.getTokenNames()!=null ) {
String[] tokensNames = parser.getTokenNames();
if ( state.parser!=null && state.parser.getTokenNames()!=null ) {
String[] tokensNames = state.parser.getTokenNames();
if ( t>=tokensNames.length ) {
System.err.println(t+" ttype out of range: "+Arrays.toString(tokensNames));
System.err.println(((CommonTokenStream)parser.getInputStream()).getTokens());
System.err.println(((CommonTokenStream)state.parser.getInputStream()).getTokens());
}
else {
return tokensNames[t]+"<"+t+">";
@ -835,52 +860,52 @@ public class ParserATNSimulator<Symbol> extends ATNSimulator {
return String.valueOf(t);
}
public String getLookaheadName(SymbolStream<Symbol> input) {
return getTokenName(input.LA(1));
public String getLookaheadName(State<Symbol> state) {
return getTokenName(state, state.getInput().LA(1));
}
public void setContextSensitive(boolean ctxSensitive) {
this.userWantsCtxSensitive = ctxSensitive;
public void setContextSensitive(@NotNull State<Symbol> state, boolean ctxSensitive) {
state.userWantsCtxSensitive = ctxSensitive;
}
public void dumpDeadEndConfigs(@NotNull NoViableAltException nvae) {
public void dumpDeadEndConfigs(@NotNull State<Symbol> state, @NotNull NoViableAltException nvae) {
System.err.println("dead end configs: ");
for (ATNConfig c : nvae.deadEndConfigs) {
Transition t = c.state.transition(0);
String trans = "";
if ( t instanceof AtomTransition) {
AtomTransition at = (AtomTransition)t;
trans = "Atom "+getTokenName(at.label);
trans = "Atom "+getTokenName(state, at.label);
}
else if ( t instanceof SetTransition ) {
SetTransition st = (SetTransition)t;
boolean not = st instanceof NotSetTransition;
trans = (not?"~":"")+"Set "+st.set.toString();
}
System.err.println(c.toString(parser, true)+":"+trans);
System.err.println(c.toString(state.parser, true)+":"+trans);
}
}
@NotNull
public NoViableAltException noViableAlt(@NotNull SymbolStream<Symbol> input, @NotNull RuleContext outerContext,
public NoViableAltException noViableAlt(@NotNull State<Symbol> state, @NotNull RuleContext outerContext,
@NotNull OrderedHashSet<ATNConfig> configs, int startIndex)
{
if ( parser instanceof TreeParser) {
if ( state.parser instanceof TreeParser) {
Symbol startNode = null;
if ( input instanceof BufferedASTNodeStream ) {
startNode = input.get(startIndex);
if ( state.getInput() instanceof BufferedASTNodeStream ) {
startNode = state.getInput().get(startIndex);
}
return new NoViableTreeGrammarAltException(parser,
(ASTNodeStream<Symbol>)input,
return new NoViableTreeGrammarAltException(state.parser,
(ASTNodeStream<Symbol>)state.getInput(),
startNode,
input.LT(1),
state.getInput().LT(1),
configs, outerContext);
}
else {
return new NoViableAltException(parser, input,
(Token)input.get(startIndex),
(Token)input.LT(1),
input.LT(1),
return new NoViableAltException(state.parser, state.getInput(),
(Token)state.getInput().get(startIndex),
(Token)state.getInput().LT(1),
state.getInput().LT(1),
configs, outerContext);
}
}

View File

@ -30,6 +30,7 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
/**
Cut-n-paste from material I'm not using in the book anymore (edit later
@ -83,8 +84,8 @@ public class TreeFilter<T> extends TreeParser<T> {
protected TokenStream originalTokenStream;
protected ASTAdaptor<T> originalAdaptor;
public TreeFilter(ASTNodeStream<T> input) {
super(input);
public TreeFilter(ASTNodeStream<T> input, ParserATNSimulator<T> interpreter) {
super(input, interpreter);
originalAdaptor = input.getTreeAdaptor();
originalTokenStream = input.getTokenStream();
}

View File

@ -30,6 +30,7 @@
package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import java.util.regex.*;
@ -51,9 +52,16 @@ public class TreeParser<T> extends BaseRecognizer<T> {
protected ASTNodeStream<T> _input;
public TreeParser(ASTNodeStream<T> input) {
super(input);
protected ParserATNSimulator.State<T> state;
public TreeParser(ASTNodeStream<T> input, ParserATNSimulator<T> interpreter) {
super(input, interpreter);
_errHandler = new DefaultTreeGrammarErrorStrategy<T>();
state = new ParserATNSimulator.State<T>(this);
}
public ParserATNSimulator.State<T> getState() {
return state;
}
@Override

View File

@ -143,15 +143,21 @@ case <f.ruleIndex> : return <f.name>_sempred((<f.ctxType>)_localctx, predIndex);
parser_ctor(p) ::= <<
public <p.name>(TokenStream input) {
super(input);
_interp = new ParserATNSimulator\<Token>(this,_ATN);
this(input, new ParserATNSimulator\<Token>(_ATN));
}
public <p.name>(TokenStream input, ParserATNSimulator\<Token> interpreter) {
super(input, interpreter);
}
>>
treeparser_ctor(p) ::= <<
public <p.name>(ASTNodeStream\<<ASTLabelType()>\> input) {
super(input);
_interp = new ParserATNSimulator\<<ASTLabelType()>\>(this,_ATN);
this(input, new ParserATNSimulator\<<ASTLabelType()>\>(_ATN));
}
public <p.name>(ASTNodeStream\<<ASTLabelType()>\> input, ParserATNSimulator\<<ASTLabelType()>\> interpreter) {
super(input, interpreter);
}
>>
@ -319,7 +325,7 @@ setState(<choice.stateNumber>);
_errHandler.sync(this);
<if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif>
<preamble; separator="\n">
switch ( getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx) ) {
switch ( getInterpreter().adaptivePredict(state,<choice.decision>,_ctx) ) {
<alts:{alt |
case <i>:
<alt>
@ -330,7 +336,7 @@ case <i>:
OptionalBlock(choice, alts, error) ::= <<
setState(<choice.stateNumber>);
_errHandler.sync(this);
switch ( getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx) ) {
switch ( getInterpreter().adaptivePredict(state,<choice.decision>,_ctx) ) {
<alts:{alt |
case <i>:
<alt>
@ -343,7 +349,7 @@ case <i>:
StarBlock(choice, alts, sync) ::= <<
setState(<choice.stateNumber>);
_errHandler.sync(this);
int _alt<choice.uniqueID> = getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx);
int _alt<choice.uniqueID> = getInterpreter().adaptivePredict(state,<choice.decision>,_ctx);
while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 ) {
switch ( _alt<choice.uniqueID> ) {
<alts:{alt|
@ -353,14 +359,14 @@ case <i>:
}
setState(<choice.loopBackStateNumber>);
_errHandler.sync(this);
_alt<choice.uniqueID> = getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx);
_alt<choice.uniqueID> = getInterpreter().adaptivePredict(state,<choice.decision>,_ctx);
}
>>
PlusBlock(choice, alts, error) ::= <<
setState(<choice.blockStartStateNumber>); <! alt block decision !>
_errHandler.sync(this);
int _alt<choice.uniqueID> = getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx);
int _alt<choice.uniqueID> = getInterpreter().adaptivePredict(state,<choice.decision>,_ctx);
do {
switch ( _alt<choice.uniqueID> ) {
<alts:{alt|
@ -372,7 +378,7 @@ case <i>:
}
setState(<choice.loopBackStateNumber>); <! loopback/exit decision !>
_errHandler.sync(this);
_alt<choice.uniqueID> = getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx);
_alt<choice.uniqueID> = getInterpreter().adaptivePredict(state,<choice.decision>,_ctx);
} while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 );
>>
@ -754,8 +760,11 @@ public class <lexer.name> extends Lexer {
<namedActions.members>
public <lexer.name>(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN);
this(input, new LexerATNSimulator(_ATN));
}
public <lexer.name>(CharStream input, LexerATNSimulator interpreter) {
super(input, interpreter);
}
public String getGrammarFileName() { return "<lexerFile.fileName>"; }

View File

@ -37,7 +37,7 @@ import org.antlr.v4.tool.LexerGrammar;
public class LexerInterpreter implements TokenSource {
protected LexerGrammar g;
protected LexerATNSimulator interp;
protected CharStream input;
protected LexerATNSimulator.State state;
public LexerInterpreter(LexerGrammar g, String inputString) {
this(g);
@ -51,11 +51,11 @@ public class LexerInterpreter implements TokenSource {
}
public void setInput(String inputString) {
input = new ANTLRInputStream(inputString);
setInput(new ANTLRInputStream(inputString));
}
public void setInput(CharStream input) {
this.input = input;
this.state = new LexerATNSimulator.State(input);
}
public String getSourceName() { return g.name; }
@ -69,16 +69,16 @@ public class LexerInterpreter implements TokenSource {
}
public CharStream getInputStream() {
return input;
return state.getInput();
}
public Token nextToken() {
// TODO: Deal with off channel tokens
int start = input.index();
int tokenStartCharPositionInLine = interp.getCharPositionInLine();
int tokenStartLine = interp.getLine();
int ttype = interp.match(input, Lexer.DEFAULT_MODE);
int stop = input.index()-1;
int start = state.getInput().index();
int tokenStartCharPositionInLine = interp.getCharPositionInLine(state);
int tokenStartLine = interp.getLine(state);
int ttype = interp.match(state, Lexer.DEFAULT_MODE);
int stop = state.getInput().index()-1;
WritableToken t = new CommonToken(this, ttype, Token.DEFAULT_CHANNEL, start, stop);
t.setLine(tokenStartLine);
t.setCharPositionInLine(tokenStartCharPositionInLine);

View File

@ -56,6 +56,7 @@ import java.util.*;
public abstract class BaseTest {
public static boolean FORCE_ATN = false;
public static final String newline = System.getProperty("line.separator");
public static final String pathSep = System.getProperty("path.separator");
@ -90,14 +91,18 @@ public abstract class BaseTest {
}
protected org.antlr.v4.Tool newTool(String[] args) {
protected org.antlr.v4.Tool newTool(String... args) {
Tool tool = new Tool(args);
return tool;
}
protected Tool newTool() {
org.antlr.v4.Tool tool = new Tool(new String[] {"-o", tmpdir});
return tool;
if (FORCE_ATN) {
return newTool("-Xforceatn", "-o", tmpdir);
}
else {
return newTool("-o", tmpdir);
}
}
ATN createATN(Grammar g) {
@ -152,10 +157,11 @@ public abstract class BaseTest {
public List<Integer> getTokenTypesViaATN(String input, LexerATNSimulator lexerATN) {
ANTLRInputStream in = new ANTLRInputStream(input);
LexerATNSimulator.State state = new LexerATNSimulator.State(in);
List<Integer> tokenTypes = new ArrayList<Integer>();
int ttype = 0;
do {
ttype = lexerATN.matchATN(in);
ttype = lexerATN.matchATN(state);
tokenTypes.add(ttype);
} while ( ttype!= Token.EOF );
return tokenTypes;
@ -167,6 +173,7 @@ public abstract class BaseTest {
boolean adaptive)
{
LexerATNSimulator interp = new LexerATNSimulator(atn);
LexerATNSimulator.State state = new LexerATNSimulator.State(input);
List<String> tokenTypes = new ArrayList<String>();
int ttype;
boolean hitEOF = false;
@ -176,8 +183,8 @@ public abstract class BaseTest {
break;
}
int t = input.LA(1);
if ( adaptive ) ttype = interp.match(input, Lexer.DEFAULT_MODE);
else ttype = interp.matchATN(input);
if ( adaptive ) ttype = interp.match(state, Lexer.DEFAULT_MODE);
else ttype = interp.matchATN(state);
if ( ttype == Token.EOF ) {
tokenTypes.add("EOF");
}

View File

@ -277,8 +277,9 @@ public class TestATNInterpreter extends BaseTest {
ParserATNFactory f = new ParserATNFactory(g);
ATN atn = f.createATN();
ParserATNSimulator interp = new ParserATNSimulator(atn);
ParserATNSimulator<Token> interp = new ParserATNSimulator<Token>(atn);
TokenStream input = new IntTokenStream(types);
ParserATNSimulator.State<Token> state = new ParserATNSimulator.State<Token>(input);
ATNState startState = atn.ruleToStartState[g.getRule("a").index];
if ( startState.transition(0).target instanceof BlockStartState ) {
startState = startState.transition(0).target;
@ -289,7 +290,7 @@ public class TestATNInterpreter extends BaseTest {
Rule r = g.getRule("e");
if ( r!=null ) System.out.println(dot.getDOT(atn.ruleToStartState[r.index]));
int result = interp.matchATN(input, startState);
int result = interp.matchATN(state, startState);
assertEquals(expected, result);
}
}

View File

@ -285,12 +285,13 @@ public class TestATNParserPrediction extends BaseTest {
RuleContext a_e_ctx = new RuleContext(a_ctx, a_e_invoke.stateNumber, bStart.stateNumber);
RuleContext b_e_ctx = new RuleContext(b_ctx, b_e_invoke.stateNumber, bStart.stateNumber);
ParserATNSimulator interp = new ParserATNSimulator(atn);
interp.setContextSensitive(true);
ParserATNSimulator<Token> interp = new ParserATNSimulator<Token>(atn);
List<Integer> types = getTokenTypesViaATN("ab", lexInterp);
System.out.println(types);
TokenStream input = new IntTokenStream(types);
int alt = interp.adaptivePredict(input, 0, b_e_ctx);
ParserATNSimulator.State<Token> state = new ParserATNSimulator.State<Token>(input);
interp.setContextSensitive(state, true);
int alt = interp.adaptivePredict(state, 0, b_e_ctx);
assertEquals(alt, 2);
DFA dfa = interp.decisionToDFA[0];
String expecting =
@ -299,7 +300,7 @@ public class TestATNParserPrediction extends BaseTest {
"s2-EOF->:s3@{[10]=2}\n";
assertEquals(expecting, dfa.toString(g.getTokenDisplayNames()));
alt = interp.adaptivePredict(input, 0, b_e_ctx); // cached
alt = interp.adaptivePredict(state, 0, b_e_ctx); // cached
assertEquals(alt, 2);
expecting =
"s0-'a'->s1\n" +
@ -307,7 +308,7 @@ public class TestATNParserPrediction extends BaseTest {
"s2-EOF->:s3@{[10]=2}\n";
assertEquals(expecting, dfa.toString(g.getTokenDisplayNames()));
alt = interp.adaptivePredict(input, 0, a_e_ctx); // forces new context-sens ATN match
alt = interp.adaptivePredict(state, 0, a_e_ctx); // forces new context-sens ATN match
assertEquals(alt, 1);
expecting =
"s0-'a'->s1\n" +
@ -315,7 +316,7 @@ public class TestATNParserPrediction extends BaseTest {
"s2-EOF->:s3@{[10]=2, [6]=1}\n";
assertEquals(expecting, dfa.toString(g.getTokenDisplayNames()));
alt = interp.adaptivePredict(input, 0, b_e_ctx); // cached
alt = interp.adaptivePredict(state, 0, b_e_ctx); // cached
assertEquals(alt, 2);
expecting =
"s0-'a'->s1\n" +
@ -323,7 +324,7 @@ public class TestATNParserPrediction extends BaseTest {
"s2-EOF->:s3@{[10]=2, [6]=1}\n";
assertEquals(expecting, dfa.toString(g.getTokenDisplayNames()));
alt = interp.adaptivePredict(input, 0, a_e_ctx); // cached
alt = interp.adaptivePredict(state, 0, a_e_ctx); // cached
assertEquals(alt, 1);
expecting =
"s0-'a'->s1\n" +
@ -334,7 +335,8 @@ public class TestATNParserPrediction extends BaseTest {
types = getTokenTypesViaATN("b", lexInterp);
System.out.println(types);
input = new IntTokenStream(types);
alt = interp.adaptivePredict(input, 0, null); // ctx irrelevant
state = new ParserATNSimulator.State<Token>(input);
alt = interp.adaptivePredict(state, 0, null); // ctx irrelevant
assertEquals(alt, 2);
expecting =
"s0-'a'->s1\n" +
@ -346,7 +348,8 @@ public class TestATNParserPrediction extends BaseTest {
types = getTokenTypesViaATN("aab", lexInterp);
System.out.println(types);
input = new IntTokenStream(types);
alt = interp.adaptivePredict(input, 0, null);
state = new ParserATNSimulator.State<Token>(input);
alt = interp.adaptivePredict(state, 0, null);
assertEquals(alt, 1);
expecting =
"s0-'a'->s1\n" +
@ -512,11 +515,12 @@ public class TestATNParserPrediction extends BaseTest {
if ( r!=null) System.out.println(dot.getDOT(atn.ruleToStartState[r.index]));
// Check ATN prediction
ParserATNSimulator interp = new ParserATNSimulator(atn);
ParserATNSimulator<Token> interp = new ParserATNSimulator<Token>(atn);
TokenStream input = new IntTokenStream(types);
ATNState startState = atn.decisionToState.get(decision);
DFA dfa = new DFA(startState);
int alt = interp.predictATN(dfa, input, RuleContext.EMPTY, false);
ParserATNSimulator.State<Token> state = new ParserATNSimulator.State<Token>(input);
int alt = interp.predictATN(dfa, state, RuleContext.EMPTY, false);
System.out.println(dot.getDOT(dfa, false));
@ -524,11 +528,11 @@ public class TestATNParserPrediction extends BaseTest {
// Check adaptive prediction
input.seek(0);
alt = interp.adaptivePredict(input, decision, null);
alt = interp.adaptivePredict(state, decision, null);
assertEquals(expectedAlt, alt);
// run 2x; first time creates DFA in atn
input.seek(0);
alt = interp.adaptivePredict(input, decision, null);
alt = interp.adaptivePredict(state, decision, null);
assertEquals(expectedAlt, alt);
}
@ -551,16 +555,17 @@ public class TestATNParserPrediction extends BaseTest {
// System.out.println(dot.getDOT(atn.ruleToStartState.get(g.getRule("b"))));
// System.out.println(dot.getDOT(atn.ruleToStartState.get(g.getRule("e"))));
ParserATNSimulator interp = new ParserATNSimulator(atn);
ParserATNSimulator<Token> interp = new ParserATNSimulator<Token>(atn);
List<Integer> types = getTokenTypesViaATN(inputString, lexInterp);
System.out.println(types);
TokenStream input = new IntTokenStream(types);
ParserATNSimulator.State<Token> state = new ParserATNSimulator.State<Token>(input);
try {
ATNState startState = atn.decisionToState.get(0);
DFA dfa = new DFA(startState);
// Rule r = g.getRule(ruleName);
//ATNState startState = atn.ruleToStartState.get(r);
interp.predictATN(dfa, input, ctx, false);
interp.predictATN(dfa, state, ctx, false);
}
catch (NoViableAltException nvae) {
nvae.printStackTrace(System.err);
@ -582,14 +587,15 @@ public class TestATNParserPrediction extends BaseTest {
ParserATNFactory f = new ParserATNFactory(g);
ATN atn = f.createATN();
ParserATNSimulator interp = new ParserATNSimulator(atn);
ParserATNSimulator<Token> interp = new ParserATNSimulator<Token>(atn);
for (int i=0; i<inputString.length; i++) {
// Check DFA
List<Integer> types = getTokenTypesViaATN(inputString[i], lexInterp);
System.out.println(types);
TokenStream input = new IntTokenStream(types);
ParserATNSimulator.State<Token> state = new ParserATNSimulator.State<Token>(input);
try {
interp.adaptivePredict(input, decision, RuleContext.EMPTY);
interp.adaptivePredict(state, decision, RuleContext.EMPTY);
}
catch (NoViableAltException nvae) {
nvae.printStackTrace(System.err);