Move primary implementation of getExpectedTokens to ATN, fixes #191
This commit is contained in:
parent
4f29c2fe3d
commit
bc17cd4a28
|
@ -550,31 +550,15 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Compute the set of valid tokens reachable from the current
|
||||
* position in the parse.
|
||||
/**
|
||||
* Computes the set of input symbols which could follow the current parser
|
||||
* state and context, as given by {@link #getState} and {@link #getContext},
|
||||
* respectively.
|
||||
*
|
||||
* @see ATN#getExpectedTokens(int, RuleContext)
|
||||
*/
|
||||
public IntervalSet getExpectedTokens() {
|
||||
ATN atn = getInterpreter().atn;
|
||||
ParserRuleContext ctx = _ctx;
|
||||
ATNState s = atn.states.get(getState());
|
||||
IntervalSet following = atn.nextTokens(s);
|
||||
// System.out.println("following "+s+"="+following);
|
||||
if ( !following.contains(Token.EPSILON) ) return following;
|
||||
IntervalSet expected = new IntervalSet();
|
||||
expected.addAll(following);
|
||||
expected.remove(Token.EPSILON);
|
||||
while ( ctx!=null && ctx.invokingState>=0 && following.contains(Token.EPSILON) ) {
|
||||
ATNState invokingState = atn.states.get(ctx.invokingState);
|
||||
RuleTransition rt = (RuleTransition)invokingState.transition(0);
|
||||
following = atn.nextTokens(rt.followState);
|
||||
expected.addAll(following);
|
||||
expected.remove(Token.EPSILON);
|
||||
ctx = (ParserRuleContext)ctx.parent;
|
||||
}
|
||||
if ( following.contains(Token.EPSILON) ) {
|
||||
expected.add(Token.EOF);
|
||||
}
|
||||
return expected;
|
||||
return getATN().getExpectedTokens(getState(), getContext());
|
||||
}
|
||||
|
||||
public IntervalSet getExpectedTokensWithinCurrentRule() {
|
||||
|
|
|
@ -92,10 +92,10 @@ public class RecognitionException extends RuntimeException {
|
|||
}
|
||||
|
||||
public IntervalSet getExpectedTokens() {
|
||||
// TODO: do we really need this type check?
|
||||
if ( recognizer!=null && recognizer instanceof Parser) {
|
||||
return ((Parser) recognizer).getExpectedTokens();
|
||||
if (recognizer != null) {
|
||||
return recognizer.getATN().getExpectedTokens(offendingState, ctx);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -155,4 +155,55 @@ public class ATN {
|
|||
public int getNumberOfDecisions() {
|
||||
return decisionToState.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the set of input symbols which could follow ATN state number
|
||||
* {@code stateNumber} in the specified full {@code context}. This method
|
||||
* considers the complete parser context, but does not evaluate semantic
|
||||
* predicates (i.e. all predicates encountered during the calculation are
|
||||
* assumed true). If a path in the ATN exists from the starting state to the
|
||||
* {@link RuleStopState} of the outermost context without matching any
|
||||
* symbols, {@link Token#EOF} is added to the returned set.
|
||||
* <p/>
|
||||
* If {@code context} is {@code null}, it is treated as
|
||||
* {@link ParserRuleContext#EMPTY}.
|
||||
*
|
||||
* @param stateNumber the ATN state number
|
||||
* @param context the full parse context
|
||||
* @return The set of potentially valid input symbols which could follow the
|
||||
* specified state in the specified context.
|
||||
* @throws IllegalArgumentException if the ATN does not contain a state with
|
||||
* number {@code stateNumber}
|
||||
*/
|
||||
@NotNull
|
||||
public IntervalSet getExpectedTokens(int stateNumber, @Nullable RuleContext context) {
|
||||
if (stateNumber < 0 || stateNumber >= states.size()) {
|
||||
throw new IllegalArgumentException("Invalid state number.");
|
||||
}
|
||||
|
||||
RuleContext ctx = context;
|
||||
ATNState s = states.get(stateNumber);
|
||||
IntervalSet following = nextTokens(s);
|
||||
if (!following.contains(Token.EPSILON)) {
|
||||
return following;
|
||||
}
|
||||
|
||||
IntervalSet expected = new IntervalSet();
|
||||
expected.addAll(following);
|
||||
expected.remove(Token.EPSILON);
|
||||
while (ctx != null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {
|
||||
ATNState invokingState = states.get(ctx.invokingState);
|
||||
RuleTransition rt = (RuleTransition)invokingState.transition(0);
|
||||
following = nextTokens(rt.followState);
|
||||
expected.addAll(following);
|
||||
expected.remove(Token.EPSILON);
|
||||
ctx = ctx.parent;
|
||||
}
|
||||
|
||||
if (following.contains(Token.EPSILON)) {
|
||||
expected.add(Token.EOF);
|
||||
}
|
||||
|
||||
return expected;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue