use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class RuleDependencyProcessor method extractRuleRelations.
private RuleRelations extractRuleRelations(TypeMirror recognizer) {
String serializedATN = getSerializedATN(recognizer);
if (serializedATN == null) {
return null;
}
ATN atn = new ATNDeserializer().deserialize(serializedATN.toCharArray());
RuleRelations relations = new RuleRelations(atn.ruleToStartState.length);
for (ATNState state : atn.states) {
if (!state.epsilonOnlyTransitions) {
continue;
}
for (Transition transition : state.getTransitions()) {
if (transition.getSerializationType() != Transition.RULE) {
continue;
}
RuleTransition ruleTransition = (RuleTransition) transition;
relations.addRuleInvocation(state.ruleIndex, ruleTransition.target.ruleIndex);
}
}
return relations;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class ParserATNSimulator method computeTargetState.
/**
* Compute a target state for an edge in the DFA, and attempt to add the
* computed state and corresponding edge to the DFA.
*
* @param dfa
* @param s The current DFA state
* @param remainingGlobalContext
* @param t The next input symbol
* @param useContext
* @param contextCache
*
* @return The computed target DFA state for the given input symbol
* {@code t}. If {@code t} does not lead to a valid DFA state, this method
* returns {@link #ERROR}.
*/
@NotNull
protected Tuple2<DFAState, ParserRuleContext> computeTargetState(@NotNull DFA dfa, @NotNull DFAState s, ParserRuleContext remainingGlobalContext, int t, boolean useContext, PredictionContextCache contextCache) {
List<ATNConfig> closureConfigs = new ArrayList<ATNConfig>(s.configs);
IntegerList contextElements = null;
ATNConfigSet reach = new ATNConfigSet();
boolean stepIntoGlobal;
do {
boolean hasMoreContext = !useContext || remainingGlobalContext != null;
if (!hasMoreContext) {
reach.setOutermostConfigSet(true);
}
ATNConfigSet reachIntermediate = new ATNConfigSet();
/* Configurations already in a rule stop state indicate reaching the end
* of the decision rule (local context) or end of the start rule (full
* context). Once reached, these configurations are never updated by a
* closure operation, so they are handled separately for the performance
* advantage of having a smaller intermediate set when calling closure.
*
* For full-context reach operations, separate handling is required to
* ensure that the alternative matching the longest overall sequence is
* chosen when multiple such configurations can match the input.
*/
List<ATNConfig> skippedStopStates = null;
for (ATNConfig c : closureConfigs) {
if (debug)
System.out.println("testing " + getTokenName(t) + " at " + c.toString());
if (c.getState() instanceof RuleStopState) {
assert c.getContext().isEmpty();
if (useContext && !c.getReachesIntoOuterContext() || t == IntStream.EOF) {
if (skippedStopStates == null) {
skippedStopStates = new ArrayList<ATNConfig>();
}
skippedStopStates.add(c);
}
continue;
}
int n = c.getState().getNumberOfOptimizedTransitions();
for (int ti = 0; ti < n; ti++) {
// for each optimized transition
Transition trans = c.getState().getOptimizedTransition(ti);
ATNState target = getReachableTarget(c, trans, t);
if (target != null) {
reachIntermediate.add(c.transform(target, false), contextCache);
}
}
}
/* This block optimizes the reach operation for intermediate sets which
* trivially indicate a termination state for the overall
* adaptivePredict operation.
*
* The conditions assume that intermediate
* contains all configurations relevant to the reach set, but this
* condition is not true when one or more configurations have been
* withheld in skippedStopStates, or when the current symbol is EOF.
*/
if (optimize_unique_closure && skippedStopStates == null && t != Token.EOF && reachIntermediate.getUniqueAlt() != ATN.INVALID_ALT_NUMBER) {
reachIntermediate.setOutermostConfigSet(reach.isOutermostConfigSet());
reach = reachIntermediate;
break;
}
/* If the reach set could not be trivially determined, perform a closure
* operation on the intermediate set to compute its initial value.
*/
final boolean collectPredicates = false;
boolean treatEofAsEpsilon = t == Token.EOF;
closure(reachIntermediate, reach, collectPredicates, hasMoreContext, contextCache, treatEofAsEpsilon);
stepIntoGlobal = reach.getDipsIntoOuterContext();
if (t == IntStream.EOF) {
/* After consuming EOF no additional input is possible, so we are
* only interested in configurations which reached the end of the
* decision rule (local context) or end of the start rule (full
* context). Update reach to contain only these configurations. This
* handles both explicit EOF transitions in the grammar and implicit
* EOF transitions following the end of the decision or start rule.
*
* This is handled before the configurations in skippedStopStates,
* because any configurations potentially added from that list are
* already guaranteed to meet this condition whether or not it's
* required.
*/
reach = removeAllConfigsNotInRuleStopState(reach, contextCache);
}
/* If skippedStopStates is not null, then it contains at least one
* configuration. For full-context reach operations, these
* configurations reached the end of the start rule, in which case we
* only add them back to reach if no configuration during the current
* closure operation reached such a state. This ensures adaptivePredict
* chooses an alternative matching the longest overall sequence when
* multiple alternatives are viable.
*/
if (skippedStopStates != null && (!useContext || !PredictionMode.hasConfigInRuleStopState(reach))) {
assert !skippedStopStates.isEmpty();
for (ATNConfig c : skippedStopStates) {
reach.add(c, contextCache);
}
}
if (useContext && stepIntoGlobal) {
reach.clear();
remainingGlobalContext = skipTailCalls(remainingGlobalContext);
int nextContextElement = getReturnState(remainingGlobalContext);
if (contextElements == null) {
contextElements = new IntegerList();
}
if (remainingGlobalContext.isEmpty()) {
remainingGlobalContext = null;
} else {
remainingGlobalContext = remainingGlobalContext.getParent();
}
contextElements.add(nextContextElement);
if (nextContextElement != PredictionContext.EMPTY_FULL_STATE_KEY) {
for (int i = 0; i < closureConfigs.size(); i++) {
closureConfigs.set(i, closureConfigs.get(i).appendContext(nextContextElement, contextCache));
}
}
}
} while (useContext && stepIntoGlobal);
if (reach.isEmpty()) {
addDFAEdge(s, t, ERROR);
return Tuple.create(ERROR, remainingGlobalContext);
}
DFAState result = addDFAEdge(dfa, s, t, contextElements, reach, contextCache);
return Tuple.create(result, remainingGlobalContext);
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class LL1Analyzer method LOOK.
/**
* Compute set of tokens that can follow {@code s} in the ATN in the
* specified {@code ctx}.
*
* <p>If {@code ctx} is {@code null} and the end of the rule containing
* {@code s} is reached, {@link Token#EPSILON} is added to the result set.
* If {@code ctx} is not {@code PredictionContext#EMPTY_LOCAL} and the end of the outermost rule is
* reached, {@link Token#EOF} is added to the result set.</p>
*
* @param s the ATN state
* @param stopState the ATN state to stop at. This can be a
* {@link BlockEndState} to detect epsilon paths through a closure.
* @param ctx the complete parser context, or {@code null} if the context
* should be ignored
*
* @return The set of tokens that can follow {@code s} in the ATN in the
* specified {@code ctx}.
*/
@NotNull
public IntervalSet LOOK(@NotNull ATNState s, @Nullable ATNState stopState, @NotNull PredictionContext ctx) {
IntervalSet r = new IntervalSet();
// ignore preds; get all lookahead
final boolean seeThruPreds = true;
final boolean addEOF = true;
_LOOK(s, stopState, ctx, r, new HashSet<ATNConfig>(), new BitSet(), seeThruPreds, addEOF);
return r;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class LexerATNSimulator method matchATN.
protected int matchATN(@NotNull CharStream input) {
ATNState startState = atn.modeToStartState.get(mode);
if (debug) {
System.out.format(Locale.getDefault(), "matchATN mode %d start: %s\n", mode, startState);
}
int old_mode = mode;
ATNConfigSet s0_closure = computeStartState(input, startState);
boolean suppressEdge = s0_closure.hasSemanticContext();
if (suppressEdge) {
s0_closure.clearExplicitSemanticContext();
}
DFAState next = addDFAState(s0_closure);
if (!suppressEdge) {
if (!atn.modeToDFA[mode].s0.compareAndSet(null, next)) {
next = atn.modeToDFA[mode].s0.get();
}
}
int predict = execATN(input, next);
if (debug) {
System.out.format(Locale.getDefault(), "DFA after matchATN: %s\n", atn.modeToDFA[old_mode].toLexerString());
}
return predict;
}
use of org.antlr.v4.runtime.atn.ATNState in project antlr4 by tunnelvisionlabs.
the class GrammarParserInterpreter method findOuterMostDecisionStates.
/**
* identify the ATN states where we need to set the outer alt number.
* For regular rules, that's the block at the target to rule start state.
* For left-recursive rules, we track the primary block, which looks just
* like a regular rule's outer block, and the star loop block (always
* there even if 1 alt).
*/
public BitSet findOuterMostDecisionStates() {
BitSet track = new BitSet(atn.states.size());
int numberOfDecisions = atn.getNumberOfDecisions();
for (int i = 0; i < numberOfDecisions; i++) {
DecisionState decisionState = atn.getDecisionState(i);
RuleStartState startState = atn.ruleToStartState[decisionState.ruleIndex];
// Look for StarLoopEntryState that is in any left recursive rule
if (decisionState instanceof StarLoopEntryState) {
StarLoopEntryState loopEntry = (StarLoopEntryState) decisionState;
if (loopEntry.precedenceRuleDecision) {
// Recursive alts always result in a (...)* in the transformed
// left recursive rule and that always has a BasicBlockStartState
// even if just 1 recursive alt exists.
ATNState blockStart = loopEntry.transition(0).target;
// track the StarBlockStartState associated with the recursive alternatives
track.set(blockStart.stateNumber);
}
} else if (startState.transition(0).target == decisionState) {
// always track outermost block for any rule if it exists
track.set(decisionState.stateNumber);
}
}
return track;
}
Aggregations