#include "dfa/DFA.h"
#include "NoViableAltException.h"
#include "atn/DecisionState.h"
#include "ParserRuleContext.h"
#include "misc/IntervalSet.h"
#include "Parser.h"
#include "CommonTokenStream.h"
#include "atn/NotSetTransition.h"
#include "atn/AtomTransition.h"
#include "atn/RuleTransition.h"
#include "atn/PredicateTransition.h"
#include "atn/PrecedencePredicateTransition.h"
#include "atn/SingletonPredictionContext.h"
#include "atn/ActionTransition.h"
#include "atn/EpsilonTransition.h"
#include "atn/RuleStopState.h"
#include "atn/ATNConfigSet.h"
#include "atn/ATNConfig.h"
#include "internal/Synchronization.h"
#include "atn/StarLoopEntryState.h"
#include "atn/BlockStartState.h"
#include "atn/BlockEndState.h"
#include "misc/Interval.h"
#include "ANTLRErrorListener.h"
#include "Vocabulary.h"
#include "support/Arrays.h"
#include "support/Casts.h"
#include "atn/ParserATNSimulator.h"
#ifndef DEBUG_ATN
#define DEBUG_ATN 0
#endif
#ifndef TRACE_ATN_SIM
#define TRACE_ATN_SIM 0
#endif
#ifndef DFA_DEBUG
#define DFA_DEBUG 0
#endif
#ifndef RETRY_DEBUG
#define RETRY_DEBUG 0
#endif
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlr4::internal;
using namespace antlrcpp;
const bool ParserATNSimulator::TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT = ParserATNSimulator::getLrLoopSetting();
ParserATNSimulator::ParserATNSimulator(const ATN &atn, std::vector<dfa::DFA> &decisionToDFA,
PredictionContextCache &sharedContextCache)
: ParserATNSimulator(nullptr, atn, decisionToDFA, sharedContextCache) {
}
ParserATNSimulator::ParserATNSimulator(Parser *parser, const ATN &atn, std::vector<dfa::DFA> &decisionToDFA,
PredictionContextCache &sharedContextCache)
: ParserATNSimulator(parser, atn, decisionToDFA, sharedContextCache, ParserATNSimulatorOptions()) {}
ParserATNSimulator::ParserATNSimulator(Parser *parser, const ATN &atn, std::vector<dfa::DFA> &decisionToDFA,
PredictionContextCache &sharedContextCache,
const ParserATNSimulatorOptions &options)
: ATNSimulator(atn, sharedContextCache), decisionToDFA(decisionToDFA), parser(parser),
mergeCache(options.getPredictionContextMergeCacheOptions()) {
InitializeInstanceFields();
}
void ParserATNSimulator::reset() {
}
void ParserATNSimulator::clearDFA() {
int size = (int)decisionToDFA.size();
decisionToDFA.clear();
for (int d = 0; d < size; ++d) {
decisionToDFA.push_back(dfa::DFA(atn.getDecisionState(d), d));
}
}
size_t ParserATNSimulator::adaptivePredict(TokenStream *input, size_t decision, ParserRuleContext *outerContext) {
#if DEBUG_ATN == 1 || TRACE_ATN_SIM == 1
std::cout << "adaptivePredict decision " << decision << " exec LA(1)==" << getLookaheadName(input) << " line "
<< input->LT(1)->getLine() << ":" << input->LT(1)->getCharPositionInLine() << std::endl;
#endif
_input = input;
_startIndex = input->index();
_outerContext = outerContext;
dfa::DFA &dfa = decisionToDFA[decision];
_dfa = &dfa;
ssize_t m = input->mark();
size_t index = _startIndex;
auto onExit = finally([this, input, index, m] {
if (mergeCache.getOptions().getClearEveryN() != 0) {
if (++_mergeCacheCounter == mergeCache.getOptions().getClearEveryN()) {
mergeCache.clear();
_mergeCacheCounter = 0;
}
}
_dfa = nullptr;
input->seek(index);
input->release(m);
});
dfa::DFAState *s0;
{
SharedLock<SharedMutex> stateLock(atn._stateMutex);
if (dfa.isPrecedenceDfa()) {
SharedLock<SharedMutex> edgeLock(atn._edgeMutex);
s0 = dfa.getPrecedenceStartState(parser->getPrecedence());
} else {
s0 = dfa.s0;
}
}
if (s0 == nullptr) {
auto s0_closure = computeStartState(dfa.atnStartState, &ParserRuleContext::EMPTY, false);
std::unique_ptr<dfa::DFAState> newState;
std::unique_ptr<dfa::DFAState> oldState;
UniqueLock<SharedMutex> stateLock(atn._stateMutex);
dfa::DFAState* ds0 = dfa.s0;
if (dfa.isPrecedenceDfa()) {
ds0->configs = std::move(s0_closure); newState = std::make_unique<dfa::DFAState>(applyPrecedenceFilter(ds0->configs.get()));
s0 = addDFAState(dfa, newState.get());
UniqueLock<SharedMutex> edgeLock(atn._edgeMutex);
dfa.setPrecedenceStartState(parser->getPrecedence(), s0);
} else {
newState = std::make_unique<dfa::DFAState>(std::move(s0_closure));
s0 = addDFAState(dfa, newState.get());
if (ds0 != s0) {
oldState.reset(ds0);
dfa.s0 = s0;
}
}
if (s0 == newState.get()) {
newState.release();
}
}
size_t alt = execATN(dfa, s0, input, index, outerContext != nullptr ? outerContext : &ParserRuleContext::EMPTY);
return alt;
}
size_t ParserATNSimulator::execATN(dfa::DFA &dfa, dfa::DFAState *s0, TokenStream *input, size_t startIndex,
ParserRuleContext *outerContext) {
#if DEBUG_ATN == 1 || TRACE_ATN_SIM == 1
std::cout << "execATN decision " << dfa.decision << ", DFA state " << s0->toString() <<
", LA(1)==" << getLookaheadName(input) <<
" line " << input->LT(1)->getLine() << ":" << input->LT(1)->getCharPositionInLine() << std::endl;
#endif
dfa::DFAState *previousD = s0;
#if DEBUG_ATN == 1
std::cout << "s0 = " << s0->toString() << std::endl;
#endif
size_t t = input->LA(1);
while (true) { dfa::DFAState *D = getExistingTargetState(previousD, t);
if (D == nullptr) {
D = computeTargetState(dfa, previousD, t);
}
if (D == ERROR.get()) {
NoViableAltException e = noViableAlt(input, outerContext, previousD->configs.get(), startIndex, false);
input->seek(startIndex);
size_t alt = getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD->configs.get(), outerContext);
if (alt != ATN::INVALID_ALT_NUMBER) {
return alt;
}
throw e;
}
if (D->requiresFullContext && _mode != PredictionMode::SLL) {
BitSet conflictingAlts;
if (D->predicates.size() != 0) {
#if DEBUG_ATN == 1
std::cout << "DFA state has preds in DFA sim LL failover" << std::endl;
#endif
size_t conflictIndex = input->index();
if (conflictIndex != startIndex) {
input->seek(startIndex);
}
conflictingAlts = evalSemanticContext(D->predicates, outerContext, true);
if (conflictingAlts.count() == 1) {
#if DEBUG_ATN == 1
std::cout << "Full LL avoided" << std::endl;
#endif
return conflictingAlts.nextSetBit(0);
}
if (conflictIndex != startIndex) {
input->seek(conflictIndex);
}
}
#if DFA_DEBUG == 1
std::cout << "ctx sensitive state " << outerContext << " in " << D << std::endl;
#endif
bool fullCtx = true;
std::unique_ptr<ATNConfigSet> s0_closure = computeStartState(dfa.atnStartState, outerContext, fullCtx);
reportAttemptingFullContext(dfa, conflictingAlts, D->configs.get(), startIndex, input->index());
size_t alt = execATNWithFullContext(dfa, D, s0_closure.get(), input, startIndex, outerContext);
return alt;
}
if (D->isAcceptState) {
if (D->predicates.empty()) {
return D->prediction;
}
size_t stopIndex = input->index();
input->seek(startIndex);
BitSet alts = evalSemanticContext(D->predicates, outerContext, true);
switch (alts.count()) {
case 0:
throw noViableAlt(input, outerContext, D->configs.get(), startIndex, false);
case 1:
return alts.nextSetBit(0);
default:
reportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D->configs.get());
return alts.nextSetBit(0);
}
}
previousD = D;
if (t != Token::EOF) {
input->consume();
t = input->LA(1);
}
}
}
dfa::DFAState *ParserATNSimulator::getExistingTargetState(dfa::DFAState *previousD, size_t t) {
dfa::DFAState* retval;
SharedLock<SharedMutex> edgeLock(atn._edgeMutex);
auto iterator = previousD->edges.find(t);
retval = (iterator == previousD->edges.end()) ? nullptr : iterator->second;
return retval;
}
dfa::DFAState *ParserATNSimulator::computeTargetState(dfa::DFA &dfa, dfa::DFAState *previousD, size_t t) {
std::unique_ptr<ATNConfigSet> reach = computeReachSet(previousD->configs.get(), t, false);
if (reach == nullptr) {
addDFAEdge(dfa, previousD, t, ERROR.get());
return ERROR.get();
}
dfa::DFAState *D = new dfa::DFAState(std::move(reach));
size_t predictedAlt = getUniqueAlt(D->configs.get());
if (predictedAlt != ATN::INVALID_ALT_NUMBER) {
D->isAcceptState = true;
D->configs->uniqueAlt = predictedAlt;
D->prediction = predictedAlt;
} else if (PredictionModeClass::hasSLLConflictTerminatingPrediction(_mode, D->configs.get())) {
D->configs->conflictingAlts = getConflictingAlts(D->configs.get());
D->requiresFullContext = true;
D->isAcceptState = true;
D->prediction = D->configs->conflictingAlts.nextSetBit(0);
}
if (D->isAcceptState && D->configs->hasSemanticContext) {
predicateDFAState(D, atn.getDecisionState(dfa.decision));
if (D->predicates.size() != 0) {
D->prediction = ATN::INVALID_ALT_NUMBER;
}
}
dfa::DFAState *state = addDFAEdge(dfa, previousD, t, D);
if (state != D) {
delete D; }
return state;
}
void ParserATNSimulator::predicateDFAState(dfa::DFAState *dfaState, DecisionState *decisionState) {
size_t nalts = decisionState->transitions.size();
BitSet altsToCollectPredsFrom = getConflictingAltsOrUniqueAlt(dfaState->configs.get());
std::vector<Ref<const SemanticContext>> altToPred = getPredsForAmbigAlts(altsToCollectPredsFrom, dfaState->configs.get(), nalts);
if (!altToPred.empty()) {
dfaState->predicates = getPredicatePredictions(altsToCollectPredsFrom, altToPred);
dfaState->prediction = ATN::INVALID_ALT_NUMBER; } else {
dfaState->prediction = altsToCollectPredsFrom.nextSetBit(0);
}
}
size_t ParserATNSimulator::execATNWithFullContext(dfa::DFA &dfa, dfa::DFAState *D, ATNConfigSet *s0,
TokenStream *input, size_t startIndex, ParserRuleContext *outerContext) {
#if TRACE_ATN_SIM == 1
std::cout << "execATNWithFullContext " << s0->toString() << std::endl;
#endif
bool fullCtx = true;
bool foundExactAmbig = false;
std::unique_ptr<ATNConfigSet> reach;
ATNConfigSet *previous = s0;
input->seek(startIndex);
size_t t = input->LA(1);
size_t predictedAlt;
while (true) {
reach = computeReachSet(previous, t, fullCtx);
if (reach == nullptr) {
NoViableAltException e = noViableAlt(input, outerContext, previous, startIndex, previous != s0);
input->seek(startIndex);
size_t alt = getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext);
if (alt != ATN::INVALID_ALT_NUMBER) {
return alt;
}
throw e;
}
if (previous != s0) delete previous;
previous = nullptr;
std::vector<BitSet> altSubSets = PredictionModeClass::getConflictingAltSubsets(reach.get());
reach->uniqueAlt = getUniqueAlt(reach.get());
if (reach->uniqueAlt != ATN::INVALID_ALT_NUMBER) {
predictedAlt = reach->uniqueAlt;
break;
}
if (_mode != PredictionMode::LL_EXACT_AMBIG_DETECTION) {
predictedAlt = PredictionModeClass::resolvesToJustOneViableAlt(altSubSets);
if (predictedAlt != ATN::INVALID_ALT_NUMBER) {
break;
}
} else {
if (PredictionModeClass::allSubsetsConflict(altSubSets) && PredictionModeClass::allSubsetsEqual(altSubSets)) {
foundExactAmbig = true;
predictedAlt = PredictionModeClass::getSingleViableAlt(altSubSets);
break;
}
}
previous = reach.release();
if (t != Token::EOF) {
input->consume();
t = input->LA(1);
}
}
if (reach->uniqueAlt != ATN::INVALID_ALT_NUMBER) {
reportContextSensitivity(dfa, predictedAlt, reach.get(), startIndex, input->index());
return predictedAlt;
}
reportAmbiguity(dfa, D, startIndex, input->index(), foundExactAmbig, reach->getAlts(), reach.get());
return predictedAlt;
}
std::unique_ptr<ATNConfigSet> ParserATNSimulator::computeReachSet(ATNConfigSet *closure_, size_t t, bool fullCtx) {
std::unique_ptr<ATNConfigSet> intermediate(new ATNConfigSet(fullCtx));
std::vector<Ref<ATNConfig>> skippedStopStates;
for (const auto &c : closure_->configs) {
if (RuleStopState::is(c->state)) {
assert(c->context->isEmpty());
if (fullCtx || t == Token::EOF) {
skippedStopStates.push_back(c);
}
continue;
}
size_t n = c->state->transitions.size();
for (size_t ti = 0; ti < n; ti++) { const Transition *trans = c->state->transitions[ti].get();
ATNState *target = getReachableTarget(trans, (int)t);
if (target != nullptr) {
intermediate->add(std::make_shared<ATNConfig>(*c, target), &mergeCache);
}
}
}
std::unique_ptr<ATNConfigSet> reach;
if (skippedStopStates.empty() && t != Token::EOF) {
if (intermediate->size() == 1) {
reach = std::move(intermediate);
} else if (getUniqueAlt(intermediate.get()) != ATN::INVALID_ALT_NUMBER) {
reach = std::move(intermediate);
}
}
if (reach == nullptr) {
reach.reset(new ATNConfigSet(fullCtx));
ATNConfig::Set closureBusy;
bool treatEofAsEpsilon = t == Token::EOF;
for (const auto &c : intermediate->configs) {
closure(c, reach.get(), closureBusy, false, fullCtx, treatEofAsEpsilon);
}
}
if (t == IntStream::EOF) {
ATNConfigSet *temp = removeAllConfigsNotInRuleStopState(reach.get(), *reach == *intermediate);
if (temp != reach.get())
reach.reset(temp); }
if (skippedStopStates.size() > 0 && (!fullCtx || !PredictionModeClass::hasConfigInRuleStopState(reach.get()))) {
assert(!skippedStopStates.empty());
for (const auto &c : skippedStopStates) {
reach->add(c, &mergeCache);
}
}
#if DEBUG_ATN == 1 || TRACE_ATN_SIM == 1
std::cout << "computeReachSet " << closure_->toString() << " -> " << reach->toString() << std::endl;
#endif
if (reach->isEmpty()) {
return nullptr;
}
return reach;
}
ATNConfigSet* ParserATNSimulator::removeAllConfigsNotInRuleStopState(ATNConfigSet *configs,
bool lookToEndOfRule) {
if (PredictionModeClass::allConfigsInRuleStopStates(configs)) {
return configs;
}
ATNConfigSet *result = new ATNConfigSet(configs->fullCtx);
for (const auto &config : configs->configs) {
if (config->state != nullptr && config->state->getStateType() == ATNStateType::RULE_STOP) {
result->add(config, &mergeCache);
continue;
}
if (lookToEndOfRule && config->state->epsilonOnlyTransitions) {
misc::IntervalSet nextTokens = atn.nextTokens(config->state);
if (nextTokens.contains(Token::EPSILON)) {
ATNState *endOfRuleState = atn.ruleToStopState[config->state->ruleIndex];
result->add(std::make_shared<ATNConfig>(*config, endOfRuleState), &mergeCache);
}
}
}
return result;
}
std::unique_ptr<ATNConfigSet> ParserATNSimulator::computeStartState(ATNState *p, RuleContext *ctx, bool fullCtx) {
Ref<const PredictionContext> initialContext = PredictionContext::fromRuleContext(atn, ctx);
std::unique_ptr<ATNConfigSet> configs(new ATNConfigSet(fullCtx));
#if DEBUG_ATN == 1 || TRACE_ATN_SIM == 1
std::cout << "computeStartState from ATN state " << p->toString() << " initialContext=" << initialContext->toString() << std::endl;
#endif
for (size_t i = 0; i < p->transitions.size(); i++) {
ATNState *target = p->transitions[i]->target;
Ref<ATNConfig> c = std::make_shared<ATNConfig>(target, (int)i + 1, initialContext);
ATNConfig::Set closureBusy;
closure(c, configs.get(), closureBusy, true, fullCtx, false);
}
return configs;
}
std::unique_ptr<ATNConfigSet> ParserATNSimulator::applyPrecedenceFilter(ATNConfigSet *configs) {
std::map<size_t, Ref<const PredictionContext>> statesFromAlt1;
std::unique_ptr<ATNConfigSet> configSet(new ATNConfigSet(configs->fullCtx));
for (const auto &config : configs->configs) {
if (config->alt != 1) {
continue;
}
Ref<const SemanticContext> updatedContext = config->semanticContext->evalPrecedence(parser, _outerContext);
if (updatedContext == nullptr) {
continue;
}
statesFromAlt1[config->state->stateNumber] = config->context;
if (updatedContext != config->semanticContext) {
configSet->add(std::make_shared<ATNConfig>(*config, updatedContext), &mergeCache);
}
else {
configSet->add(config, &mergeCache);
}
}
for (const auto &config : configs->configs) {
if (config->alt == 1) {
continue;
}
if (!config->isPrecedenceFilterSuppressed()) {
auto iterator = statesFromAlt1.find(config->state->stateNumber);
if (iterator != statesFromAlt1.end() && *iterator->second == *config->context) {
continue;
}
}
configSet->add(config, &mergeCache);
}
return configSet;
}
atn::ATNState* ParserATNSimulator::getReachableTarget(const Transition *trans, size_t ttype) {
if (trans->matches(ttype, 0, atn.maxTokenType)) {
return trans->target;
}
return nullptr;
}
std::vector<Ref<const SemanticContext>> ParserATNSimulator::getPredsForAmbigAlts(const BitSet &ambigAlts,
ATNConfigSet *configs, size_t nalts) {
std::vector<Ref<const SemanticContext>> altToPred(nalts + 1);
for (const auto &c : configs->configs) {
if (ambigAlts.test(c->alt)) {
altToPred[c->alt] = SemanticContext::Or(altToPred[c->alt], c->semanticContext);
}
}
size_t nPredAlts = 0;
for (size_t i = 1; i <= nalts; i++) {
if (altToPred[i] == nullptr) {
altToPred[i] = SemanticContext::Empty::Instance;
} else if (altToPred[i] != SemanticContext::Empty::Instance) {
nPredAlts++;
}
}
if (nPredAlts == 0) {
altToPred.clear();
}
#if DEBUG_ATN == 1
std::cout << "getPredsForAmbigAlts result " << Arrays::toString(altToPred) << std::endl;
#endif
return altToPred;
}
std::vector<dfa::DFAState::PredPrediction> ParserATNSimulator::getPredicatePredictions(const antlrcpp::BitSet &ambigAlts,
const std::vector<Ref<const SemanticContext>> &altToPred) {
bool containsPredicate = std::find_if(altToPred.begin(), altToPred.end(), [](const Ref<const SemanticContext> &context) {
return context != SemanticContext::Empty::Instance;
}) != altToPred.end();
std::vector<dfa::DFAState::PredPrediction> pairs;
if (containsPredicate) {
for (size_t i = 1; i < altToPred.size(); i++) {
const auto &pred = altToPred[i];
assert(pred != nullptr); if (ambigAlts.test(i)) {
pairs.emplace_back(pred, static_cast<int>(i));
}
}
}
return pairs;
}
size_t ParserATNSimulator::getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(ATNConfigSet *configs,
ParserRuleContext *outerContext)
{
std::pair<ATNConfigSet *, ATNConfigSet *> sets = splitAccordingToSemanticValidity(configs, outerContext);
std::unique_ptr<ATNConfigSet> semValidConfigs(sets.first);
std::unique_ptr<ATNConfigSet> semInvalidConfigs(sets.second);
size_t alt = getAltThatFinishedDecisionEntryRule(semValidConfigs.get());
if (alt != ATN::INVALID_ALT_NUMBER) { return alt;
}
if (!semInvalidConfigs->configs.empty()) {
alt = getAltThatFinishedDecisionEntryRule(semInvalidConfigs.get());
if (alt != ATN::INVALID_ALT_NUMBER) { return alt;
}
}
return ATN::INVALID_ALT_NUMBER;
}
size_t ParserATNSimulator::getAltThatFinishedDecisionEntryRule(ATNConfigSet *configs) {
misc::IntervalSet alts;
for (const auto &c : configs->configs) {
if (c->getOuterContextDepth() > 0 || (c->state != nullptr && c->state->getStateType() == ATNStateType::RULE_STOP && c->context->hasEmptyPath())) {
alts.add(c->alt);
}
}
if (alts.size() == 0) {
return ATN::INVALID_ALT_NUMBER;
}
return alts.getMinElement();
}
std::pair<ATNConfigSet *, ATNConfigSet *> ParserATNSimulator::splitAccordingToSemanticValidity(ATNConfigSet *configs,
ParserRuleContext *outerContext) {
ATNConfigSet *succeeded(new ATNConfigSet(configs->fullCtx));
ATNConfigSet *failed(new ATNConfigSet(configs->fullCtx));
for (const auto &c : configs->configs) {
if (c->semanticContext != SemanticContext::Empty::Instance) {
bool predicateEvaluationResult = evalSemanticContext(c->semanticContext, outerContext, c->alt, configs->fullCtx);
if (predicateEvaluationResult) {
succeeded->add(c);
} else {
failed->add(c);
}
} else {
succeeded->add(c);
}
}
return { succeeded, failed };
}
BitSet ParserATNSimulator::evalSemanticContext(const std::vector<dfa::DFAState::PredPrediction> &predPredictions,
ParserRuleContext *outerContext, bool complete) {
BitSet predictions;
for (const auto &prediction : predPredictions) {
if (prediction.pred == SemanticContext::Empty::Instance) {
predictions.set(prediction.alt);
if (!complete) {
break;
}
continue;
}
bool fullCtx = false; bool predicateEvaluationResult = evalSemanticContext(prediction.pred, outerContext, prediction.alt, fullCtx);
#if DEBUG_ATN == 1 || DFA_DEBUG == 1
std::cout << "eval pred " << prediction.toString() << " = " << predicateEvaluationResult << std::endl;
#endif
if (predicateEvaluationResult) {
#if DEBUG_ATN == 1 || DFA_DEBUG == 1
std::cout << "PREDICT " << prediction.alt << std::endl;
#endif
predictions.set(prediction.alt);
if (!complete) {
break;
}
}
}
return predictions;
}
bool ParserATNSimulator::evalSemanticContext(Ref<const SemanticContext> const& pred, ParserRuleContext *parserCallStack,
size_t , bool ) {
return pred->eval(parser, parserCallStack);
}
void ParserATNSimulator::closure(Ref<ATNConfig> const& config, ATNConfigSet *configs, ATNConfig::Set &closureBusy,
bool collectPredicates, bool fullCtx, bool treatEofAsEpsilon) {
const int initialDepth = 0;
closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, initialDepth, treatEofAsEpsilon);
assert(!fullCtx || !configs->dipsIntoOuterContext);
}
void ParserATNSimulator::closureCheckingStopState(Ref<ATNConfig> const& config, ATNConfigSet *configs,
ATNConfig::Set &closureBusy, bool collectPredicates, bool fullCtx, int depth, bool treatEofAsEpsilon) {
#if TRACE_ATN_SIM == 1
std::cout << "closure(" << config->toString(true) << ")" << std::endl;
#endif
if (config->state != nullptr && config->state->getStateType() == ATNStateType::RULE_STOP) {
if (!config->context->isEmpty()) {
for (size_t i = 0; i < config->context->size(); i++) {
if (config->context->getReturnState(i) == PredictionContext::EMPTY_RETURN_STATE) {
if (fullCtx) {
configs->add(std::make_shared<ATNConfig>(*config, config->state, PredictionContext::EMPTY), &mergeCache);
continue;
} else {
#if DEBUG_ATN == 1
std::cout << "FALLING off rule " << getRuleName(config->state->ruleIndex) << std::endl;
#endif
closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon);
}
continue;
}
ATNState *returnState = atn.states[config->context->getReturnState(i)];
Ref<const PredictionContext> newContext = config->context->getParent(i); Ref<ATNConfig> c = std::make_shared<ATNConfig>(returnState, config->alt, newContext, config->semanticContext);
c->reachesIntoOuterContext = config->reachesIntoOuterContext;
assert(depth > INT_MIN);
closureCheckingStopState(c, configs, closureBusy, collectPredicates, fullCtx, depth - 1, treatEofAsEpsilon);
}
return;
} else if (fullCtx) {
configs->add(config, &mergeCache);
return;
} else {
}
}
closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon);
}
void ParserATNSimulator::closure_(Ref<ATNConfig> const& config, ATNConfigSet *configs, ATNConfig::Set &closureBusy,
bool collectPredicates, bool fullCtx, int depth, bool treatEofAsEpsilon) {
ATNState *p = config->state;
if (!p->epsilonOnlyTransitions) {
configs->add(config, &mergeCache);
}
for (size_t i = 0; i < p->transitions.size(); i++) {
if (i == 0 && canDropLoopEntryEdgeInLeftRecursiveRule(config.get()))
continue;
const Transition *t = p->transitions[i].get();
bool continueCollecting = !(t != nullptr && t->getTransitionType() == TransitionType::ACTION) && collectPredicates;
Ref<ATNConfig> c = getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx, treatEofAsEpsilon);
if (c != nullptr) {
int newDepth = depth;
if (config->state != nullptr && config->state->getStateType() == ATNStateType::RULE_STOP) {
assert(!fullCtx);
if (closureBusy.count(c) > 0) {
continue;
}
closureBusy.insert(c);
if (_dfa != nullptr && _dfa->isPrecedenceDfa()) {
size_t outermostPrecedenceReturn = downCast<const EpsilonTransition *>(t)->outermostPrecedenceReturn();
if (outermostPrecedenceReturn == _dfa->atnStartState->ruleIndex) {
c->setPrecedenceFilterSuppressed(true);
}
}
c->reachesIntoOuterContext++;
if (!t->isEpsilon()) {
if (closureBusy.count(c) == 0) {
closureBusy.insert(c);
} else {
continue;
}
}
configs->dipsIntoOuterContext = true; assert(newDepth > INT_MIN);
newDepth--;
#if DFA_DEBUG == 1
std::cout << "dips into outer ctx: " << c << std::endl;
#endif
} else if (!t->isEpsilon()) {
if (closureBusy.count(c) == 0) {
closureBusy.insert(c);
} else {
continue;
}
}
if (t != nullptr && t->getTransitionType() == TransitionType::RULE) {
if (newDepth >= 0) {
newDepth++;
}
}
closureCheckingStopState(c, configs, closureBusy, continueCollecting, fullCtx, newDepth, treatEofAsEpsilon);
}
}
}
bool ParserATNSimulator::canDropLoopEntryEdgeInLeftRecursiveRule(ATNConfig *config) const {
if (TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT)
return false;
ATNState *p = config->state;
if (p->getStateType() != ATNStateType::STAR_LOOP_ENTRY ||
!((StarLoopEntryState *)p)->isPrecedenceDecision || config->context->isEmpty() || config->context->hasEmptyPath())
{
return false;
}
size_t numCtxs = config->context->size();
for (size_t i = 0; i < numCtxs; i++) { ATNState *returnState = atn.states[config->context->getReturnState(i)];
if (returnState->ruleIndex != p->ruleIndex)
return false;
}
BlockStartState *decisionStartState = (BlockStartState *)p->transitions[0]->target;
size_t blockEndStateNum = decisionStartState->endState->stateNumber;
BlockEndState *blockEndState = (BlockEndState *)atn.states[blockEndStateNum];
for (size_t i = 0; i < numCtxs; i++) { size_t returnStateNumber = config->context->getReturnState(i);
ATNState *returnState = atn.states[returnStateNumber];
if (returnState->transitions.size() != 1 || !returnState->transitions[0]->isEpsilon())
{
return false;
}
ATNState *returnStateTarget = returnState->transitions[0]->target;
if (returnState->getStateType() == ATNStateType::BLOCK_END && returnStateTarget == p) {
continue;
}
if (returnState == blockEndState) {
continue;
}
if (returnStateTarget == blockEndState) {
continue;
}
if (returnStateTarget->getStateType() == ATNStateType::BLOCK_END &&
returnStateTarget->transitions.size() == 1 &&
returnStateTarget->transitions[0]->isEpsilon() &&
returnStateTarget->transitions[0]->target == p)
{
continue;
}
return false;
}
return true;
}
std::string ParserATNSimulator::getRuleName(size_t index) {
if (parser != nullptr) {
return parser->getRuleNames()[index];
}
return "<rule " + std::to_string(index) + ">";
}
Ref<ATNConfig> ParserATNSimulator::getEpsilonTarget(Ref<ATNConfig> const& config, const Transition *t, bool collectPredicates,
bool inContext, bool fullCtx, bool treatEofAsEpsilon) {
switch (t->getTransitionType()) {
case TransitionType::RULE:
return ruleTransition(config, static_cast<const RuleTransition*>(t));
case TransitionType::PRECEDENCE:
return precedenceTransition(config, static_cast<const PrecedencePredicateTransition*>(t), collectPredicates, inContext, fullCtx);
case TransitionType::PREDICATE:
return predTransition(config, static_cast<const PredicateTransition*>(t), collectPredicates, inContext, fullCtx);
case TransitionType::ACTION:
return actionTransition(config, static_cast<const ActionTransition*>(t));
case TransitionType::EPSILON:
return std::make_shared<ATNConfig>(*config, t->target);
case TransitionType::ATOM:
case TransitionType::RANGE:
case TransitionType::SET:
if (treatEofAsEpsilon) {
if (t->matches(Token::EOF, 0, 1)) {
return std::make_shared<ATNConfig>(*config, t->target);
}
}
return nullptr;
default:
return nullptr;
}
}
Ref<ATNConfig> ParserATNSimulator::actionTransition(Ref<ATNConfig> const& config, const ActionTransition *t) {
#if DFA_DEBUG == 1
std::cout << "ACTION edge " << t->ruleIndex << ":" << t->actionIndex << std::endl;
#endif
return std::make_shared<ATNConfig>(*config, t->target);
}
Ref<ATNConfig> ParserATNSimulator::precedenceTransition(Ref<ATNConfig> const& config, const PrecedencePredicateTransition *pt,
bool collectPredicates, bool inContext, bool fullCtx) {
#if DFA_DEBUG == 1
std::cout << "PRED (collectPredicates=" << collectPredicates << ") " << pt->getPrecedence() << ">=_p" << ", ctx dependent=true" << std::endl;
if (parser != nullptr) {
std::cout << "context surrounding pred is " << Arrays::listToString(parser->getRuleInvocationStack(), ", ") << std::endl;
}
#endif
Ref<ATNConfig> c;
if (collectPredicates && inContext) {
const auto &predicate = pt->getPredicate();
if (fullCtx) {
size_t currentPosition = _input->index();
_input->seek(_startIndex);
bool predSucceeds = evalSemanticContext(predicate, _outerContext, config->alt, fullCtx);
_input->seek(currentPosition);
if (predSucceeds) {
c = std::make_shared<ATNConfig>(*config, pt->target); }
} else {
Ref<const SemanticContext> newSemCtx = SemanticContext::And(config->semanticContext, predicate);
c = std::make_shared<ATNConfig>(*config, pt->target, std::move(newSemCtx));
}
} else {
c = std::make_shared<ATNConfig>(*config, pt->target);
}
#if DFA_DEBUG == 1
std::cout << "config from pred transition=" << c << std::endl;
#endif
return c;
}
Ref<ATNConfig> ParserATNSimulator::predTransition(Ref<ATNConfig> const& config, const PredicateTransition *pt,
bool collectPredicates, bool inContext, bool fullCtx) {
#if DFA_DEBUG == 1
std::cout << "PRED (collectPredicates=" << collectPredicates << ") " << pt->getRuleIndex() << ":" << pt->getPredIndex() << ", ctx dependent=" << pt->isCtxDependent() << std::endl;
if (parser != nullptr) {
std::cout << "context surrounding pred is " << Arrays::listToString(parser->getRuleInvocationStack(), ", ") << std::endl;
}
#endif
Ref<ATNConfig> c = nullptr;
if (collectPredicates && (!pt->isCtxDependent() || (pt->isCtxDependent() && inContext))) {
const auto &predicate = pt->getPredicate();
if (fullCtx) {
size_t currentPosition = _input->index();
_input->seek(_startIndex);
bool predSucceeds = evalSemanticContext(predicate, _outerContext, config->alt, fullCtx);
_input->seek(currentPosition);
if (predSucceeds) {
c = std::make_shared<ATNConfig>(*config, pt->target); }
} else {
Ref<const SemanticContext> newSemCtx = SemanticContext::And(config->semanticContext, predicate);
c = std::make_shared<ATNConfig>(*config, pt->target, std::move(newSemCtx));
}
} else {
c = std::make_shared<ATNConfig>(*config, pt->target);
}
#if DFA_DEBUG == 1
std::cout << "config from pred transition=" << c << std::endl;
#endif
return c;
}
Ref<ATNConfig> ParserATNSimulator::ruleTransition(Ref<ATNConfig> const& config, const RuleTransition *t) {
#if DFA_DEBUG == 1
std::cout << "CALL rule " << getRuleName(t->target->ruleIndex) << ", ctx=" << config->context << std::endl;
#endif
atn::ATNState *returnState = t->followState;
Ref<const PredictionContext> newContext = SingletonPredictionContext::create(config->context, returnState->stateNumber);
return std::make_shared<ATNConfig>(*config, t->target, newContext);
}
BitSet ParserATNSimulator::getConflictingAlts(ATNConfigSet *configs) {
std::vector<BitSet> altsets = PredictionModeClass::getConflictingAltSubsets(configs);
return PredictionModeClass::getAlts(altsets);
}
BitSet ParserATNSimulator::getConflictingAltsOrUniqueAlt(ATNConfigSet *configs) {
BitSet conflictingAlts;
if (configs->uniqueAlt != ATN::INVALID_ALT_NUMBER) {
conflictingAlts.set(configs->uniqueAlt);
} else {
conflictingAlts = configs->conflictingAlts;
}
return conflictingAlts;
}
std::string ParserATNSimulator::getTokenName(size_t t) {
if (t == Token::EOF) {
return "EOF";
}
const dfa::Vocabulary &vocabulary = parser != nullptr ? parser->getVocabulary() : dfa::Vocabulary();
std::string displayName = vocabulary.getDisplayName(t);
if (displayName == std::to_string(t)) {
return displayName;
}
return displayName + "<" + std::to_string(t) + ">";
}
std::string ParserATNSimulator::getLookaheadName(TokenStream *input) {
return getTokenName(input->LA(1));
}
void ParserATNSimulator::dumpDeadEndConfigs(NoViableAltException &nvae) {
std::cerr << "dead end configs: ";
for (const auto &c : nvae.getDeadEndConfigs()->configs) {
std::string trans = "no edges";
if (c->state->transitions.size() > 0) {
const Transition *t = c->state->transitions[0].get();
if (t != nullptr && t->getTransitionType() == TransitionType::ATOM) {
const AtomTransition *at = static_cast<const AtomTransition*>(t);
trans = "Atom " + getTokenName(at->_label);
} else if (t != nullptr && t->getTransitionType() == TransitionType::SET) {
const SetTransition *st = static_cast<const SetTransition*>(t);
trans = "Set ";
trans += st->set.toString();
} else if (t != nullptr && t->getTransitionType() == TransitionType::NOT_SET) {
const SetTransition *st = static_cast<const NotSetTransition*>(t);
trans = "~Set ";
trans += st->set.toString();
}
}
std::cerr << c->toString(true) + ":" + trans;
}
}
NoViableAltException ParserATNSimulator::noViableAlt(TokenStream *input, ParserRuleContext *outerContext,
ATNConfigSet *configs, size_t startIndex, bool deleteConfigs) {
return NoViableAltException(parser, input, input->get(startIndex), input->LT(1), configs, outerContext, deleteConfigs);
}
size_t ParserATNSimulator::getUniqueAlt(ATNConfigSet *configs) {
size_t alt = ATN::INVALID_ALT_NUMBER;
for (const auto &c : configs->configs) {
if (alt == ATN::INVALID_ALT_NUMBER) {
alt = c->alt; } else if (c->alt != alt) {
return ATN::INVALID_ALT_NUMBER;
}
}
return alt;
}
dfa::DFAState *ParserATNSimulator::addDFAEdge(dfa::DFA &dfa, dfa::DFAState *from, ssize_t t, dfa::DFAState *to) {
#if DFA_DEBUG == 1
std::cout << "EDGE " << from << " -> " << to << " upon " << getTokenName(t) << std::endl;
#endif
if (to == nullptr) {
return nullptr;
}
{
UniqueLock<SharedMutex> stateLock(atn._stateMutex);
to = addDFAState(dfa, to); }
if (from == nullptr || t > (int)atn.maxTokenType) {
return to;
}
{
UniqueLock<SharedMutex> edgeLock(atn._edgeMutex);
from->edges[t] = to; }
#if DFA_DEBUG == 1
std::string dfaText;
if (parser != nullptr) {
dfaText = dfa.toString(parser->getVocabulary());
} else {
dfaText = dfa.toString(dfa::Vocabulary());
}
std::cout << "DFA=\n" << dfaText << std::endl;
#endif
return to;
}
dfa::DFAState *ParserATNSimulator::addDFAState(dfa::DFA &dfa, dfa::DFAState *D) {
if (D == ERROR.get()) {
return D;
}
auto [existing, inserted] = dfa.states.insert(D);
if (!inserted) {
#if TRACE_ATN_SIM == 1
std::cout << "addDFAState " << D->toString() << " exists" << std::endl;
#endif
return *existing;
}
D->stateNumber = static_cast<int>(dfa.states.size() - 1);
#if TRACE_ATN_SIM == 1
std::cout << "addDFAState new " << D->toString() << std::endl;
#endif
if (!D->configs->isReadonly()) {
D->configs->optimizeConfigs(this);
D->configs->setReadonly(true);
}
#if DFA_DEBUG == 1
std::cout << "adding new DFA state: " << D << std::endl;
#endif
return D;
}
void ParserATNSimulator::reportAttemptingFullContext(dfa::DFA &dfa, const antlrcpp::BitSet &conflictingAlts,
ATNConfigSet *configs, size_t startIndex, size_t stopIndex) {
#if DFA_DEBUG == 1 || RETRY_DEBUG == 1
misc::Interval interval = misc::Interval((int)startIndex, (int)stopIndex);
std::cout << "reportAttemptingFullContext decision=" << dfa.decision << ":" << configs << ", input=" << parser->getTokenStream()->getText(interval) << std::endl;
#endif
if (parser != nullptr) {
parser->getErrorListenerDispatch().reportAttemptingFullContext(parser, dfa, startIndex, stopIndex, conflictingAlts, configs);
}
}
void ParserATNSimulator::reportContextSensitivity(dfa::DFA &dfa, size_t prediction, ATNConfigSet *configs,
size_t startIndex, size_t stopIndex) {
#if DFA_DEBUG == 1 || RETRY_DEBUG == 1
misc::Interval interval = misc::Interval(startIndex, stopIndex);
std::cout << "reportContextSensitivity decision=" << dfa.decision << ":" << configs << ", input=" << parser->getTokenStream()->getText(interval) << std::endl;
#endif
if (parser != nullptr) {
parser->getErrorListenerDispatch().reportContextSensitivity(parser, dfa, startIndex, stopIndex, prediction, configs);
}
}
void ParserATNSimulator::reportAmbiguity(dfa::DFA &dfa, dfa::DFAState * , size_t startIndex, size_t stopIndex,
bool exact, const antlrcpp::BitSet &ambigAlts, ATNConfigSet *configs) {
#if DFA_DEBUG == 1 || RETRY_DEBUG == 1
misc::Interval interval = misc::Interval((int)startIndex, (int)stopIndex);
std::cout << "reportAmbiguity " << ambigAlts << ":" << configs << ", input=" << parser->getTokenStream()->getText(interval) << std::endl;
#endif
if (parser != nullptr) {
parser->getErrorListenerDispatch().reportAmbiguity(parser, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
}
}
void ParserATNSimulator::setPredictionMode(PredictionMode newMode) {
_mode = newMode;
}
atn::PredictionMode ParserATNSimulator::getPredictionMode() {
return _mode;
}
Parser* ParserATNSimulator::getParser() {
return parser;
}
#ifdef _MSC_VER
#pragma warning (disable:4996)
#endif
bool ParserATNSimulator::getLrLoopSetting() {
char *var = std::getenv("TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT");
if (var == nullptr)
return false;
std::string value(var);
return value == "true" || value == "1";
}
#ifdef _MSC_VER
#pragma warning (default:4996)
#endif
void ParserATNSimulator::InitializeInstanceFields() {
_mode = PredictionMode::LL;
_startIndex = 0;
}