use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by tunnelvisionlabs.
the class ParserATNSimulator method computeStartState.
@NotNull
protected SimulatorState computeStartState(DFA dfa, ParserRuleContext globalContext, boolean useContext) {
DFAState s0 = dfa.isPrecedenceDfa() ? dfa.getPrecedenceStartState(parser.getPrecedence(), useContext) : useContext ? dfa.s0full.get() : dfa.s0.get();
if (s0 != null) {
if (!useContext) {
return new SimulatorState(globalContext, s0, useContext, globalContext);
}
s0.setContextSensitive(atn);
}
final int decision = dfa.decision;
@NotNull final ATNState p = dfa.atnStartState;
int previousContext = 0;
ParserRuleContext remainingGlobalContext = globalContext;
// always at least the implicit call to start rule
PredictionContext initialContext = useContext ? PredictionContext.EMPTY_FULL : PredictionContext.EMPTY_LOCAL;
PredictionContextCache contextCache = new PredictionContextCache();
if (useContext) {
if (!enable_global_context_dfa) {
while (remainingGlobalContext != null) {
if (remainingGlobalContext.isEmpty()) {
previousContext = PredictionContext.EMPTY_FULL_STATE_KEY;
remainingGlobalContext = null;
} else {
previousContext = getReturnState(remainingGlobalContext);
initialContext = initialContext.appendContext(previousContext, contextCache);
remainingGlobalContext = remainingGlobalContext.getParent();
}
}
}
while (s0 != null && s0.isContextSensitive() && remainingGlobalContext != null) {
DFAState next;
remainingGlobalContext = skipTailCalls(remainingGlobalContext);
if (remainingGlobalContext.isEmpty()) {
next = s0.getContextTarget(PredictionContext.EMPTY_FULL_STATE_KEY);
previousContext = PredictionContext.EMPTY_FULL_STATE_KEY;
remainingGlobalContext = null;
} else {
previousContext = getReturnState(remainingGlobalContext);
next = s0.getContextTarget(previousContext);
initialContext = initialContext.appendContext(previousContext, contextCache);
remainingGlobalContext = remainingGlobalContext.getParent();
}
if (next == null) {
break;
}
s0 = next;
}
}
if (s0 != null && !s0.isContextSensitive()) {
return new SimulatorState(globalContext, s0, useContext, remainingGlobalContext);
}
ATNConfigSet configs = new ATNConfigSet();
while (true) {
ATNConfigSet reachIntermediate = new ATNConfigSet();
int n = p.getNumberOfTransitions();
for (int ti = 0; ti < n; ti++) {
// for each transition
ATNState target = p.transition(ti).target;
reachIntermediate.add(ATNConfig.create(target, ti + 1, initialContext));
}
boolean hasMoreContext = remainingGlobalContext != null;
if (!hasMoreContext) {
configs.setOutermostConfigSet(true);
}
final boolean collectPredicates = true;
closure(reachIntermediate, configs, collectPredicates, hasMoreContext, contextCache, false);
boolean stepIntoGlobal = configs.getDipsIntoOuterContext();
DFAState next;
if (useContext && !enable_global_context_dfa) {
s0 = addDFAState(dfa, configs, contextCache);
break;
} else if (s0 == null) {
if (!dfa.isPrecedenceDfa()) {
AtomicReference<DFAState> reference = useContext ? dfa.s0full : dfa.s0;
next = addDFAState(dfa, configs, contextCache);
if (!reference.compareAndSet(null, next)) {
next = reference.get();
}
} else {
/* If this is a precedence DFA, we use applyPrecedenceFilter
* to convert the computed start state to a precedence start
* state. We then use DFA.setPrecedenceStartState to set the
* appropriate start state for the precedence level rather
* than simply setting DFA.s0.
*/
configs = applyPrecedenceFilter(configs, globalContext, contextCache);
next = addDFAState(dfa, configs, contextCache);
dfa.setPrecedenceStartState(parser.getPrecedence(), useContext, next);
}
} else {
if (dfa.isPrecedenceDfa()) {
configs = applyPrecedenceFilter(configs, globalContext, contextCache);
}
next = addDFAState(dfa, configs, contextCache);
s0.setContextTarget(previousContext, next);
}
s0 = next;
if (!useContext || !stepIntoGlobal) {
break;
}
// TODO: make sure it distinguishes empty stack states
next.setContextSensitive(atn);
configs.clear();
remainingGlobalContext = skipTailCalls(remainingGlobalContext);
int nextContextElement = getReturnState(remainingGlobalContext);
if (remainingGlobalContext.isEmpty()) {
remainingGlobalContext = null;
} else {
remainingGlobalContext = remainingGlobalContext.getParent();
}
if (nextContextElement != PredictionContext.EMPTY_FULL_STATE_KEY) {
initialContext = initialContext.appendContext(nextContextElement, contextCache);
}
previousContext = nextContextElement;
}
return new SimulatorState(globalContext, s0, useContext, remainingGlobalContext);
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by tunnelvisionlabs.
the class ParserATNSimulator method addDFAEdge.
@NotNull
protected DFAState addDFAEdge(@NotNull DFA dfa, @NotNull DFAState fromState, int t, IntegerList contextTransitions, @NotNull ATNConfigSet toConfigs, PredictionContextCache contextCache) {
assert contextTransitions == null || contextTransitions.isEmpty() || dfa.isContextSensitive();
DFAState from = fromState;
DFAState to = addDFAState(dfa, toConfigs, contextCache);
if (contextTransitions != null) {
for (int context : contextTransitions.toArray()) {
if (context == PredictionContext.EMPTY_FULL_STATE_KEY) {
if (from.configs.isOutermostConfigSet()) {
continue;
}
}
from.setContextSensitive(atn);
from.setContextSymbol(t);
DFAState next = from.getContextTarget(context);
if (next != null) {
from = next;
continue;
}
next = addDFAContextState(dfa, from.configs, context, contextCache);
assert context != PredictionContext.EMPTY_FULL_STATE_KEY || next.configs.isOutermostConfigSet();
from.setContextTarget(context, next);
from = next;
}
}
if (debug)
System.out.println("EDGE " + from + " -> " + to + " upon " + getTokenName(t));
addDFAEdge(from, t, to);
if (debug)
System.out.println("DFA=\n" + dfa.toString(parser != null ? parser.getVocabulary() : VocabularyImpl.EMPTY_VOCABULARY, parser != null ? parser.getRuleNames() : null));
return to;
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by tunnelvisionlabs.
the class LexerATNSimulator method execATN.
protected int execATN(@NotNull CharStream input, @NotNull DFAState ds0) {
// System.out.println("enter exec index "+input.index()+" from "+ds0.configs);
if (debug) {
System.out.format(Locale.getDefault(), "start state closure=%s\n", ds0.configs);
}
if (ds0.isAcceptState()) {
// allow zero-length tokens
captureSimState(prevAccept, input, ds0);
}
int t = input.LA(1);
@NotNull DFAState // s is current/from DFA state
s = ds0;
while (true) {
// while more work
if (debug) {
System.out.format(Locale.getDefault(), "execATN loop starting closure: %s\n", s.configs);
}
// As we move src->trg, src->trg, we keep track of the previous trg to
// avoid looking up the DFA state again, which is expensive.
// If the previous target was already part of the DFA, we might
// be able to avoid doing a reach operation upon t. If s!=null,
// it means that semantic predicates didn't prevent us from
// creating a DFA state. Once we know s!=null, we check to see if
// the DFA state has an edge already for t. If so, we can just reuse
// it's configuration set; there's no point in re-computing it.
// This is kind of like doing DFA simulation within the ATN
// simulation because DFA simulation is really just a way to avoid
// computing reach/closure sets. Technically, once we know that
// we have a previously added DFA state, we could jump over to
// the DFA simulator. But, that would mean popping back and forth
// a lot and making things more complicated algorithmically.
// This optimization makes a lot of sense for loops within DFA.
// A character will take us back to an existing DFA state
// that already has lots of edges out of it. e.g., .* in comments.
DFAState target = getExistingTargetState(s, t);
if (target == null) {
target = computeTargetState(input, s, t);
}
if (target == ERROR) {
break;
}
// end of the token.
if (t != IntStream.EOF) {
consume(input);
}
if (target.isAcceptState()) {
captureSimState(prevAccept, input, target);
if (t == IntStream.EOF) {
break;
}
}
t = input.LA(1);
// flip; current DFA target becomes new src/from state
s = target;
}
return failOrAccept(prevAccept, input, s.configs, t);
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by tunnelvisionlabs.
the class LexerATNSimulator method match.
public int match(@NotNull CharStream input, int mode) {
match_calls++;
this.mode = mode;
int mark = input.mark();
try {
this.startIndex = input.index();
this.prevAccept.reset();
DFAState s0 = atn.modeToDFA[mode].s0.get();
if (s0 == null) {
return matchATN(input);
} else {
return execATN(input, s0);
}
} finally {
input.release(mark);
}
}
use of org.antlr.v4.runtime.dfa.DFAState in project antlr4 by tunnelvisionlabs.
the class DFASerializer method getStateString.
String getStateString(DFAState s) {
if (s == ATNSimulator.ERROR) {
return "ERROR";
}
int n = s.stateNumber;
String stateStr = "s" + n;
if (s.isAcceptState()) {
if (s.predicates != null) {
stateStr = ":s" + n + "=>" + Arrays.toString(s.predicates);
} else {
stateStr = ":s" + n + "=>" + s.getPrediction();
}
}
if (s.isContextSensitive()) {
stateStr += "*";
for (ATNConfig config : s.configs) {
if (config.getReachesIntoOuterContext()) {
stateStr += "*";
break;
}
}
}
return stateStr;
}
Aggregations