use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class DefaultErrorStrategy method singleTokenInsertion.
/**
* This method implements the single-token insertion inline error recovery
* strategy. It is called by {@link #recoverInline} if the single-token
* deletion strategy fails to recover from the mismatched input. If this
* method returns {@code true}, {@code recognizer} will be in error recovery
* mode.
*
* <p>This method determines whether or not single-token insertion is viable by
* checking if the {@code LA(1)} input symbol could be successfully matched
* if it were instead the {@code LA(2)} symbol. If this method returns
* {@code true}, the caller is responsible for creating and inserting a
* token with the correct type to produce this behavior.</p>
*
* @param recognizer the parser instance
* @return {@code true} if single-token insertion is a viable recovery
* strategy for the current mismatched input, otherwise {@code false}
*/
protected boolean singleTokenInsertion(@NotNull Parser recognizer) {
int currentSymbolType = recognizer.getInputStream().LA(1);
// if current token is consistent with what could come after current
// ATN state, then we know we're missing a token; error recovery
// is free to conjure up and insert the missing token
ATNState currentState = recognizer.getInterpreter().atn.states.get(recognizer.getState());
ATNState next = currentState.transition(0).target;
ATN atn = recognizer.getInterpreter().atn;
IntervalSet expectingAtLL2 = atn.nextTokens(next, PredictionContext.fromRuleContext(atn, recognizer._ctx));
// System.out.println("LT(2) set="+expectingAtLL2.toString(recognizer.getTokenNames()));
if (expectingAtLL2.contains(currentSymbolType)) {
reportMissingToken(recognizer);
return true;
}
return false;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ATN method getExpectedTokens.
/**
* 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}.</p>
*
* <p>Note that this does NOT give you the set of all tokens that could
* appear at a given token position in the input phrase. In other words, it
* does not answer:</p>
*
* <quote>"Given a specific partial input phrase, return the set of all
* tokens that can follow the last token in the input phrase."</quote>
*
* <p>The big difference is that with just the input, the parser could land
* right in the middle of a lookahead decision. Getting all
* <em>possible</em> tokens given a partial input stream is a separate
* computation. See https://github.com/antlr/antlr4/issues/1428</p>
*
* <p>For this function, we are specifying an ATN state and call stack to
* compute what token(s) can come next and specifically: outside of a
* lookahead decision. That is what you want for error reporting and
* recovery upon parse error.</p>
*
* @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;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ATN method nextTokens.
/**
* Compute the set of valid tokens that can occur starting in state {@code s}.
* If {@code ctx} is {@link PredictionContext#EMPTY_LOCAL}, the set of tokens will not include what can follow
* the rule surrounding {@code s}. In other words, the set will be
* restricted to tokens reachable staying within {@code s}'s rule.
*/
@NotNull
public IntervalSet nextTokens(ATNState s, @NotNull PredictionContext ctx) {
Args.notNull("ctx", ctx);
LL1Analyzer anal = new LL1Analyzer(this);
IntervalSet next = anal.LOOK(s, ctx);
return next;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ATNOptimizer method optimizeStates.
private static void optimizeStates(ATN atn) {
List<ATNState> states = atn.states;
int current = 0;
for (int i = 0; i < states.size(); i++) {
ATNState state = states.get(i);
if (state == null) {
continue;
}
if (i != current) {
state.stateNumber = current;
states.set(current, state);
states.set(i, null);
}
current++;
}
// System.out.println("ATN optimizer removed " + (states.size() - current) + " null states.");
states.subList(current, states.size()).clear();
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ATNPrinter method asString.
public String asString() {
if (start == null)
return null;
marked = new HashSet<ATNState>();
work = new ArrayList<ATNState>();
work.add(start);
StringBuilder buf = new StringBuilder();
ATNState s;
while (!work.isEmpty()) {
s = work.remove(0);
if (marked.contains(s))
continue;
int n = s.getNumberOfTransitions();
// System.out.println("visit "+s+"; edges="+n);
marked.add(s);
for (int i = 0; i < n; i++) {
Transition t = s.transition(i);
if (!(s instanceof RuleStopState)) {
// don't add follow states to work
if (t instanceof RuleTransition)
work.add(((RuleTransition) t).followState);
else
work.add(t.target);
}
buf.append(getStateString(s));
if (t instanceof EpsilonTransition) {
buf.append("->").append(getStateString(t.target)).append('\n');
} else if (t instanceof RuleTransition) {
buf.append("-").append(g.getRule(((RuleTransition) t).ruleIndex).name).append("->").append(getStateString(t.target)).append('\n');
} else if (t instanceof ActionTransition) {
ActionTransition a = (ActionTransition) t;
buf.append("-").append(a.toString()).append("->").append(getStateString(t.target)).append('\n');
} else if (t instanceof SetTransition) {
SetTransition st = (SetTransition) t;
boolean not = st instanceof NotSetTransition;
if (g.isLexer()) {
buf.append("-").append(not ? "~" : "").append(st.toString()).append("->").append(getStateString(t.target)).append('\n');
} else {
buf.append("-").append(not ? "~" : "").append(st.label().toString(g.getVocabulary())).append("->").append(getStateString(t.target)).append('\n');
}
} else if (t instanceof AtomTransition) {
AtomTransition a = (AtomTransition) t;
String label = g.getTokenDisplayName(a.label);
buf.append("-").append(label).append("->").append(getStateString(t.target)).append('\n');
} else {
buf.append("-").append(t.toString()).append("->").append(getStateString(t.target)).append('\n');
}
}
}
return buf.toString();
}
Aggregations