X-Git-Url: https://gitweb.ps.run/toc/blobdiff_plain/9f94b672a5dc32da5ad01742bd4e976315a30d9c..c6ad2948bb98d42f8e0883ef82cd14cd2d5eda60:/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/ATN.cpp?ds=inline diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/ATN.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/ATN.cpp new file mode 100644 index 0000000..2334e6b --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/ATN.cpp @@ -0,0 +1,209 @@ +/* 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(); +} +