/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. * Use of this file is governed by the BSD 3-clause license that * can be found in the LICENSE.txt file in the project root. */ #include "atn/LL1Analyzer.h" #include "Token.h" #include "atn/RuleTransition.h" #include "misc/IntervalSet.h" #include "RuleContext.h" #include "atn/DecisionState.h" #include "Recognizer.h" #include "atn/ATNType.h" #include "Exceptions.h" #include "support/CPPUtils.h" #include "atn/ATN.h" using namespace antlr4; using namespace antlr4::atn; using namespace antlrcpp; ATN::ATN() : ATN(ATNType::LEXER, 0) { } ATN::ATN(ATN &&other) { // All source vectors are implicitly cleared by the moves. states = std::move(other.states); decisionToState = std::move(other.decisionToState); ruleToStartState = std::move(other.ruleToStartState); ruleToStopState = std::move(other.ruleToStopState); grammarType = std::move(other.grammarType); maxTokenType = std::move(other.maxTokenType); ruleToTokenType = std::move(other.ruleToTokenType); lexerActions = std::move(other.lexerActions); modeToStartState = std::move(other.modeToStartState); } ATN::ATN(ATNType grammarType_, size_t maxTokenType_) : grammarType(grammarType_), maxTokenType(maxTokenType_) { } ATN::~ATN() { for (ATNState *state : states) { delete state; } } /** * Required to be defined (even though not used) as we have an explicit move assignment operator. */ ATN& ATN::operator = (ATN &other) NOEXCEPT { states = other.states; decisionToState = other.decisionToState; ruleToStartState = other.ruleToStartState; ruleToStopState = other.ruleToStopState; grammarType = other.grammarType; maxTokenType = other.maxTokenType; ruleToTokenType = other.ruleToTokenType; lexerActions = other.lexerActions; modeToStartState = other.modeToStartState; return *this; } /** * Explicit move assignment operator to make this the preferred assignment. With implicit copy/move assignment * operators it seems the copy operator is preferred causing trouble when releasing the allocated ATNState instances. */ ATN& ATN::operator = (ATN &&other) NOEXCEPT { // All source vectors are implicitly cleared by the moves. states = std::move(other.states); decisionToState = std::move(other.decisionToState); ruleToStartState = std::move(other.ruleToStartState); ruleToStopState = std::move(other.ruleToStopState); grammarType = std::move(other.grammarType); maxTokenType = std::move(other.maxTokenType); ruleToTokenType = std::move(other.ruleToTokenType); lexerActions = std::move(other.lexerActions); modeToStartState = std::move(other.modeToStartState); return *this; } misc::IntervalSet ATN::nextTokens(ATNState *s, RuleContext *ctx) const { LL1Analyzer analyzer(*this); return analyzer.LOOK(s, ctx); } misc::IntervalSet const& ATN::nextTokens(ATNState *s) const { if (!s->_nextTokenUpdated) { std::unique_lock lock { _mutex }; if (!s->_nextTokenUpdated) { s->_nextTokenWithinRule = nextTokens(s, nullptr); s->_nextTokenUpdated = true; } } return s->_nextTokenWithinRule; } void ATN::addState(ATNState *state) { if (state != nullptr) { //state->atn = this; state->stateNumber = static_cast(states.size()); } states.push_back(state); } void ATN::removeState(ATNState *state) { delete states.at(state->stateNumber);// just free mem, don't shift states in list states.at(state->stateNumber) = nullptr; } int ATN::defineDecisionState(DecisionState *s) { decisionToState.push_back(s); s->decision = static_cast(decisionToState.size() - 1); return s->decision; } DecisionState *ATN::getDecisionState(size_t decision) const { if (!decisionToState.empty()) { return decisionToState[decision]; } return nullptr; } size_t ATN::getNumberOfDecisions() const { return decisionToState.size(); } misc::IntervalSet ATN::getExpectedTokens(size_t stateNumber, RuleContext *context) const { if (stateNumber == ATNState::INVALID_STATE_NUMBER || stateNumber >= states.size()) { throw IllegalArgumentException("Invalid state number."); } RuleContext *ctx = context; ATNState *s = states.at(stateNumber); misc::IntervalSet following = nextTokens(s); if (!following.contains(Token::EPSILON)) { return following; } misc::IntervalSet expected; expected.addAll(following); expected.remove(Token::EPSILON); while (ctx && ctx->invokingState != ATNState::INVALID_STATE_NUMBER && following.contains(Token::EPSILON)) { ATNState *invokingState = states.at(ctx->invokingState); RuleTransition *rt = static_cast(invokingState->transitions[0]); following = nextTokens(rt->followState); expected.addAll(following); expected.remove(Token::EPSILON); if (ctx->parent == nullptr) { break; } ctx = static_cast(ctx->parent); } if (following.contains(Token::EPSILON)) { expected.add(Token::EOF); } return expected; } std::string ATN::toString() const { std::stringstream ss; std::string type; switch (grammarType) { case ATNType::LEXER: type = "LEXER "; break; case ATNType::PARSER: type = "PARSER "; break; default: break; } ss << "(" << type << "ATN " << std::hex << this << std::dec << ") maxTokenType: " << maxTokenType << std::endl; ss << "states (" << states.size() << ") {" << std::endl; size_t index = 0; for (auto *state : states) { if (state == nullptr) { ss << " " << index++ << ": nul" << std::endl; } else { std::string text = state->toString(); ss << " " << index++ << ": " << indent(text, " ", false) << std::endl; } } index = 0; for (auto *state : decisionToState) { if (state == nullptr) { ss << " " << index++ << ": nul" << std::endl; } else { std::string text = state->toString(); ss << " " << index++ << ": " << indent(text, " ", false) << std::endl; } } ss << "}"; return ss.str(); }