From 91b6504bb4f9ff536d8b16152a71bb0f8025c858 Mon Sep 17 00:00:00 2001 From: Justin King Date: Wed, 30 Mar 2022 13:12:07 -0700 Subject: [PATCH] [C++] Add T::is for type hierarchy checks and remove some dynamic_cast --- runtime/Cpp/runtime/src/ParserRuleContext.cpp | 33 ++++++------ runtime/Cpp/runtime/src/ParserRuleContext.h | 40 +++++++------- runtime/Cpp/runtime/src/RuleContext.h | 4 ++ .../Cpp/runtime/src/atn/ATNDeserializer.cpp | 54 +++++++++---------- .../Cpp/runtime/src/atn/ActionTransition.h | 4 ++ .../runtime/src/atn/ArrayPredictionContext.h | 4 ++ runtime/Cpp/runtime/src/atn/AtomTransition.h | 4 ++ .../runtime/src/atn/BasicBlockStartState.h | 4 ++ runtime/Cpp/runtime/src/atn/BasicState.h | 4 ++ runtime/Cpp/runtime/src/atn/BlockEndState.h | 4 ++ runtime/Cpp/runtime/src/atn/BlockStartState.h | 9 ++++ runtime/Cpp/runtime/src/atn/DecisionState.h | 12 +++++ .../Cpp/runtime/src/atn/EpsilonTransition.h | 4 ++ .../Cpp/runtime/src/atn/LexerATNConfig.cpp | 3 +- .../Cpp/runtime/src/atn/LexerChannelAction.h | 4 ++ .../Cpp/runtime/src/atn/LexerCustomAction.h | 4 ++ runtime/Cpp/runtime/src/atn/LexerModeAction.h | 4 ++ runtime/Cpp/runtime/src/atn/LexerMoreAction.h | 4 ++ .../Cpp/runtime/src/atn/LexerPopModeAction.h | 4 ++ .../Cpp/runtime/src/atn/LexerPushModeAction.h | 4 ++ runtime/Cpp/runtime/src/atn/LexerSkipAction.h | 4 ++ runtime/Cpp/runtime/src/atn/LexerTypeAction.h | 4 ++ runtime/Cpp/runtime/src/atn/LoopEndState.h | 4 ++ .../Cpp/runtime/src/atn/NotSetTransition.cpp | 3 +- .../Cpp/runtime/src/atn/NotSetTransition.h | 4 ++ .../Cpp/runtime/src/atn/PlusBlockStartState.h | 4 ++ .../Cpp/runtime/src/atn/PlusLoopbackState.h | 4 ++ .../src/atn/PrecedencePredicateTransition.h | 4 ++ .../Cpp/runtime/src/atn/PredicateTransition.h | 4 ++ runtime/Cpp/runtime/src/atn/RangeTransition.h | 4 ++ runtime/Cpp/runtime/src/atn/RuleStopState.h | 4 ++ runtime/Cpp/runtime/src/atn/RuleTransition.h | 4 ++ runtime/Cpp/runtime/src/atn/SemanticContext.h | 23 ++++++++ runtime/Cpp/runtime/src/atn/SetTransition.cpp | 4 +- runtime/Cpp/runtime/src/atn/SetTransition.h | 9 +++- .../src/atn/SingletonPredictionContext.h | 5 +- .../Cpp/runtime/src/atn/StarBlockStartState.h | 4 ++ .../Cpp/runtime/src/atn/StarLoopEntryState.h | 4 ++ .../Cpp/runtime/src/atn/StarLoopbackState.h | 4 ++ .../Cpp/runtime/src/atn/TokensStartState.h | 4 ++ .../Cpp/runtime/src/atn/WildcardTransition.h | 4 ++ runtime/Cpp/runtime/src/tree/ErrorNode.h | 5 ++ .../src/tree/IterativeParseTreeWalker.cpp | 41 ++++++-------- .../Cpp/runtime/src/tree/ParseTreeWalker.cpp | 17 +++--- .../Cpp/runtime/src/tree/ParseTreeWalker.h | 8 +-- runtime/Cpp/runtime/src/tree/TerminalNode.h | 7 +++ 46 files changed, 283 insertions(+), 110 deletions(-) diff --git a/runtime/Cpp/runtime/src/ParserRuleContext.cpp b/runtime/Cpp/runtime/src/ParserRuleContext.cpp index 3e5d30b96c1..e57eda6e43a 100755 --- a/runtime/Cpp/runtime/src/ParserRuleContext.cpp +++ b/runtime/Cpp/runtime/src/ParserRuleContext.cpp @@ -77,39 +77,36 @@ void ParserRuleContext::removeLastChild() { } } -tree::TerminalNode* ParserRuleContext::getToken(size_t ttype, size_t i) { +tree::TerminalNode* ParserRuleContext::getToken(size_t ttype, size_t i) const { if (i >= children.size()) { return nullptr; } - size_t j = 0; // what token with ttype have we found? - for (auto *o : children) { - if (o->getTreeType() == ParseTreeType::TERMINAL || o->getTreeType() == ParseTreeType::ERROR) { - tree::TerminalNode *tnode = downCast(o); - Token *symbol = tnode->getSymbol(); + for (auto *child : children) { + if (TerminalNode::is(child)) { + tree::TerminalNode *typedChild = downCast(child); + Token *symbol = typedChild->getSymbol(); if (symbol->getType() == ttype) { if (j++ == i) { - return tnode; + return typedChild; } } } } - return nullptr; } -std::vector ParserRuleContext::getTokens(size_t ttype) { - std::vector tokens; - for (auto &o : children) { - if (o->getTreeType() == ParseTreeType::TERMINAL || o->getTreeType() == ParseTreeType::ERROR) { - tree::TerminalNode *tnode = downCast(o); - Token *symbol = tnode->getSymbol(); +std::vector ParserRuleContext::getTokens(size_t ttype) const { + std::vector tokens; + for (auto *child : children) { + if (TerminalNode::is(child)) { + tree::TerminalNode *typedChild = downCast(child); + Token *symbol = typedChild->getSymbol(); if (symbol->getType() == ttype) { - tokens.push_back(tnode); + tokens.push_back(typedChild); } } } - return tokens; } @@ -124,11 +121,11 @@ misc::Interval ParserRuleContext::getSourceInterval() { return misc::Interval(start->getTokenIndex(), stop->getTokenIndex()); } -Token* ParserRuleContext::getStart() { +Token* ParserRuleContext::getStart() const { return start; } -Token* ParserRuleContext::getStop() { +Token* ParserRuleContext::getStop() const { return stop; } diff --git a/runtime/Cpp/runtime/src/ParserRuleContext.h b/runtime/Cpp/runtime/src/ParserRuleContext.h index c9ffe177909..43528a2e918 100755 --- a/runtime/Cpp/runtime/src/ParserRuleContext.h +++ b/runtime/Cpp/runtime/src/ParserRuleContext.h @@ -67,7 +67,6 @@ namespace antlr4 { ParserRuleContext(); ParserRuleContext(ParserRuleContext *parent, size_t invokingStateNumber); - virtual ~ParserRuleContext() {} /** COPY a ctx (I'm deliberately not using copy constructor) to avoid * confusion with creating node with parent. Does not copy children @@ -88,23 +87,22 @@ namespace antlr4 { /// Used by enterOuterAlt to toss out a RuleContext previously added as /// we entered a rule. If we have # label, we will need to remove /// generic ruleContext object. - virtual void removeLastChild(); + void removeLastChild(); - virtual tree::TerminalNode* getToken(size_t ttype, std::size_t i); + tree::TerminalNode* getToken(size_t ttype, std::size_t i) const; - virtual std::vector getTokens(size_t ttype); + std::vector getTokens(size_t ttype) const; template - T* getRuleContext(size_t i) { - if (children.empty()) { - return nullptr; - } - + T* getRuleContext(size_t i) const { + static_assert(std::is_base_of_v, "T must be derived from RuleContext"); size_t j = 0; // what element have we found with ctxType? - for (auto &child : children) { - if (antlrcpp::is(child)) { - if (j++ == i) { - return dynamic_cast(child); + for (auto *child : children) { + if (RuleContext::is(child)) { + if (auto *typedChild = dynamic_cast(child); typedChild != nullptr) { + if (j++ == i) { + return typedChild; + } } } } @@ -112,14 +110,16 @@ namespace antlr4 { } template - std::vector getRuleContexts() { - std::vector contexts; + std::vector getRuleContexts() const { + static_assert(std::is_base_of_v, "T must be derived from RuleContext"); + std::vector contexts; for (auto *child : children) { - if (antlrcpp::is(child)) { - contexts.push_back(dynamic_cast(child)); + if (RuleContext::is(child)) { + if (auto *typedChild = dynamic_cast(child); typedChild != nullptr) { + contexts.push_back(typedChild); + } } } - return contexts; } @@ -130,14 +130,14 @@ namespace antlr4 { * Note that the range from start to stop is inclusive, so for rules that do not consume anything * (for example, zero length or error productions) this token may exceed stop. */ - virtual Token *getStart(); + Token* getStart() const; /** * Get the final token in this context. * Note that the range from start to stop is inclusive, so for rules that do not consume anything * (for example, zero length or error productions) this token may precede start. */ - virtual Token *getStop(); + Token* getStop() const; /// /// Used for rule context info debugging during parse-time, not so much for ATN debugging diff --git a/runtime/Cpp/runtime/src/RuleContext.h b/runtime/Cpp/runtime/src/RuleContext.h index 6a6d495c219..117f90b2d62 100755 --- a/runtime/Cpp/runtime/src/RuleContext.h +++ b/runtime/Cpp/runtime/src/RuleContext.h @@ -61,6 +61,10 @@ namespace antlr4 { */ class ANTLR4CPP_PUBLIC RuleContext : public tree::ParseTree { public: + static bool is(const tree::ParseTree &parseTree) { return parseTree.getTreeType() == tree::ParseTreeType::RULE; } + + static bool is(const tree::ParseTree *parseTree) { return parseTree != nullptr && is(*parseTree); } + /// What state invoked the rule associated with this context? /// The "return address" is the followState of invokingState /// If parent is null, this should be -1 and this context object represents the start rule. diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp index 3b5563c975b..aaca0405e43 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp @@ -82,7 +82,7 @@ namespace { */ void markPrecedenceDecisions(const ATN &atn) { for (ATNState *state : atn.states) { - if (!is(state)) { + if (!StarLoopEntryState::is(state)) { continue; } @@ -92,8 +92,8 @@ namespace { */ if (atn.ruleToStartState[state->ruleIndex]->isLeftRecursiveRule) { ATNState *maybeLoopEndState = state->transitions[state->transitions.size() - 1]->target; - if (is(maybeLoopEndState)) { - if (maybeLoopEndState->epsilonOnlyTransitions && is(maybeLoopEndState->transitions[0]->target)) { + if (LoopEndState::is(maybeLoopEndState)) { + if (maybeLoopEndState->epsilonOnlyTransitions && RuleStopState::is(maybeLoopEndState->transitions[0]->target)) { downCast(state)->isPrecedenceDecision = true; } } @@ -291,7 +291,7 @@ std::unique_ptr ATNDeserializer::deserialize(const std::vector& da if (stype == ATNStateType::LOOP_END) { // special case int loopBackStateNumber = data[p++]; loopBackStateNumbers.push_back({ downCast(s), loopBackStateNumber }); - } else if (is(s)) { + } else if (BlockStartState::is(s)) { int endStateNumber = data[p++]; endStateNumbers.push_back({ downCast(s), endStateNumber }); } @@ -340,7 +340,7 @@ std::unique_ptr ATNDeserializer::deserialize(const std::vector& da atn->ruleToStopState.resize(nrules); for (ATNState *state : atn->states) { - if (!is(state)) { + if (!RuleStopState::is(state)) { continue; } @@ -389,7 +389,7 @@ std::unique_ptr ATNDeserializer::deserialize(const std::vector& da for (ATNState *state : atn->states) { for (size_t i = 0; i < state->transitions.size(); i++) { const Transition *t = state->transitions[i].get(); - if (!is(t)) { + if (!RuleTransition::is(t)) { continue; } @@ -407,7 +407,7 @@ std::unique_ptr ATNDeserializer::deserialize(const std::vector& da } for (ATNState *state : atn->states) { - if (is(state)) { + if (BlockStartState::is(state)) { BlockStartState *startState = downCast(state); // we need to know the end state to set its start state @@ -423,19 +423,19 @@ std::unique_ptr ATNDeserializer::deserialize(const std::vector& da startState->endState->startState = downCast(state); } - if (is(state)) { + if (PlusLoopbackState::is(state)) { PlusLoopbackState *loopbackState = downCast(state); for (size_t i = 0; i < loopbackState->transitions.size(); i++) { ATNState *target = loopbackState->transitions[i]->target; - if (is(target)) { + if (PlusBlockStartState::is(target)) { (downCast(target))->loopBackState = loopbackState; } } - } else if (is(state)) { + } else if (StarLoopbackState::is(state)) { StarLoopbackState *loopbackState = downCast(state); for (size_t i = 0; i < loopbackState->transitions.size(); i++) { ATNState *target = loopbackState->transitions[i]->target; - if (is(target)) { + if (StarLoopEntryState::is(target)) { downCast(target)->loopBackState = loopbackState; } } @@ -506,16 +506,16 @@ std::unique_ptr ATNDeserializer::deserialize(const std::vector& da continue; } - if (!is(state)) { + if (!StarLoopEntryState::is(state)) { continue; } ATNState *maybeLoopEndState = state->transitions[state->transitions.size() - 1]->target; - if (!is(maybeLoopEndState)) { + if (!LoopEndState::is(maybeLoopEndState)) { continue; } - if (maybeLoopEndState->epsilonOnlyTransitions && is(maybeLoopEndState->transitions[0]->target)) { + if (maybeLoopEndState->epsilonOnlyTransitions && RuleStopState::(maybeLoopEndState->transitions[0]->target)) { endState = state; break; } @@ -578,52 +578,52 @@ void ATNDeserializer::verifyATN(const ATN &atn) const { checkCondition(state->epsilonOnlyTransitions || state->transitions.size() <= 1); - if (is(state)) { + if (PlusBlockStartState::is(state)) { checkCondition((downCast(state))->loopBackState != nullptr); } - if (is(state)) { + if (StarLoopEntryState::is(state)) { StarLoopEntryState *starLoopEntryState = downCast(state); checkCondition(starLoopEntryState->loopBackState != nullptr); checkCondition(starLoopEntryState->transitions.size() == 2); - if (is(starLoopEntryState->transitions[0]->target)) { + if (StarBlockStartState::is(starLoopEntryState->transitions[0]->target)) { checkCondition(downCast(starLoopEntryState->transitions[1]->target) != nullptr); checkCondition(!starLoopEntryState->nonGreedy); - } else if (is(starLoopEntryState->transitions[0]->target)) { - checkCondition(is(starLoopEntryState->transitions[1]->target)); + } else if (LoopEndState::is(starLoopEntryState->transitions[0]->target)) { + checkCondition(StarBlockStartState::is(starLoopEntryState->transitions[1]->target)); checkCondition(starLoopEntryState->nonGreedy); } else { throw IllegalStateException(); } } - if (is(state)) { + if (StarLoopbackState::is(state)) { checkCondition(state->transitions.size() == 1); - checkCondition(is(state->transitions[0]->target)); + checkCondition(StarLoopEntryState::is(state->transitions[0]->target)); } - if (is(state)) { + if (LoopEndState::is(state)) { checkCondition((downCast(state))->loopBackState != nullptr); } - if (is(state)) { + if (RuleStartState::is(state)) { checkCondition((downCast(state))->stopState != nullptr); } - if (is(state)) { + if (BlockStartState::is(state)) { checkCondition((downCast(state))->endState != nullptr); } - if (is(state)) { + if (BlockEndState::is(state)) { checkCondition((downCast(state))->startState != nullptr); } - if (is(state)) { + if (DecisionState::is(state)) { DecisionState *decisionState = downCast(state); checkCondition(decisionState->transitions.size() <= 1 || decisionState->decision >= 0); } else { - checkCondition(state->transitions.size() <= 1 || is(state)); + checkCondition(state->transitions.size() <= 1 || RuleStopState::is(state)); } } } diff --git a/runtime/Cpp/runtime/src/atn/ActionTransition.h b/runtime/Cpp/runtime/src/atn/ActionTransition.h index 8704baac1ca..0c6b9afce71 100755 --- a/runtime/Cpp/runtime/src/atn/ActionTransition.h +++ b/runtime/Cpp/runtime/src/atn/ActionTransition.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC ActionTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::ACTION; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + const size_t ruleIndex; const size_t actionIndex; const bool isCtxDependent; // e.g., $i ref in action diff --git a/runtime/Cpp/runtime/src/atn/ArrayPredictionContext.h b/runtime/Cpp/runtime/src/atn/ArrayPredictionContext.h index c91cf0078dd..152c8434567 100755 --- a/runtime/Cpp/runtime/src/atn/ArrayPredictionContext.h +++ b/runtime/Cpp/runtime/src/atn/ArrayPredictionContext.h @@ -15,6 +15,10 @@ namespace atn { class ANTLR4CPP_PUBLIC ArrayPredictionContext final : public PredictionContext { public: + static bool is(const PredictionContext &predictionContext) { return predictionContext.getContextType() == PredictionContextType::ARRAY; } + + static bool is(const PredictionContext *predictionContext) { return predictionContext != nullptr && is(*predictionContext); } + /// Parent can be empty only if full ctx mode and we make an array /// from EMPTY and non-empty. We merge EMPTY by using null parent and /// returnState == EMPTY_RETURN_STATE. diff --git a/runtime/Cpp/runtime/src/atn/AtomTransition.h b/runtime/Cpp/runtime/src/atn/AtomTransition.h index 4f7a0b82e85..db62a7feaba 100755 --- a/runtime/Cpp/runtime/src/atn/AtomTransition.h +++ b/runtime/Cpp/runtime/src/atn/AtomTransition.h @@ -13,6 +13,10 @@ namespace atn { /// TODO: make all transitions sets? no, should remove set edges. class ANTLR4CPP_PUBLIC AtomTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::ATOM; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + /// The token type or character value; or, signifies special label. /// TODO: rename this to label const size_t _label; diff --git a/runtime/Cpp/runtime/src/atn/BasicBlockStartState.h b/runtime/Cpp/runtime/src/atn/BasicBlockStartState.h index 83909bcff77..c5a588fbfd1 100755 --- a/runtime/Cpp/runtime/src/atn/BasicBlockStartState.h +++ b/runtime/Cpp/runtime/src/atn/BasicBlockStartState.h @@ -13,6 +13,10 @@ namespace atn { class ANTLR4CPP_PUBLIC BasicBlockStartState final : public BlockStartState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::BLOCK_START; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + BasicBlockStartState() : BlockStartState(ATNStateType::BLOCK_START) {} }; diff --git a/runtime/Cpp/runtime/src/atn/BasicState.h b/runtime/Cpp/runtime/src/atn/BasicState.h index e05eaa218f7..311a966e1d6 100755 --- a/runtime/Cpp/runtime/src/atn/BasicState.h +++ b/runtime/Cpp/runtime/src/atn/BasicState.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC BasicState final : public ATNState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::BASIC; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + BasicState() : ATNState(ATNStateType::BASIC) {} }; diff --git a/runtime/Cpp/runtime/src/atn/BlockEndState.h b/runtime/Cpp/runtime/src/atn/BlockEndState.h index 80283405fce..a3e067109e7 100755 --- a/runtime/Cpp/runtime/src/atn/BlockEndState.h +++ b/runtime/Cpp/runtime/src/atn/BlockEndState.h @@ -13,6 +13,10 @@ namespace atn { /// Terminal node of a simple {@code (a|b|c)} block. class ANTLR4CPP_PUBLIC BlockEndState final : public ATNState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::BLOCK_END; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + BlockStartState *startState = nullptr; BlockEndState() : ATNState(ATNStateType::BLOCK_END) {} diff --git a/runtime/Cpp/runtime/src/atn/BlockStartState.h b/runtime/Cpp/runtime/src/atn/BlockStartState.h index 538fc4a1584..7a4a91ae730 100755 --- a/runtime/Cpp/runtime/src/atn/BlockStartState.h +++ b/runtime/Cpp/runtime/src/atn/BlockStartState.h @@ -13,6 +13,15 @@ namespace atn { /// The start of a regular {@code (...)} block. class ANTLR4CPP_PUBLIC BlockStartState : public DecisionState { public: + static bool is(const ATNState &atnState) { + const auto stateType = atnState.getStateType(); + return stateType == ATNStateType::BLOCK_START || + stateType == ATNStateType::PLUS_BLOCK_START || + stateType == ATNStateType::STAR_BLOCK_START; + } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + BlockEndState *endState = nullptr; protected: diff --git a/runtime/Cpp/runtime/src/atn/DecisionState.h b/runtime/Cpp/runtime/src/atn/DecisionState.h index a396d7c22c8..61abcf7faf2 100755 --- a/runtime/Cpp/runtime/src/atn/DecisionState.h +++ b/runtime/Cpp/runtime/src/atn/DecisionState.h @@ -12,6 +12,18 @@ namespace atn { class ANTLR4CPP_PUBLIC DecisionState : public ATNState { public: + static bool is(const ATNState &atnState) { + const auto stateType = atnState.getStateType(); + return stateType == ATNStateType::BLOCK_START || + stateType == ATNStateType::PLUS_BLOCK_START || + stateType == ATNStateType::STAR_BLOCK_START || + stateType == ATNStateType::PLUS_LOOP_BACK || + stateType == ATNStateType::STAR_LOOP_ENTRY || + stateType == ATNStateType::TOKEN_START; + } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + int decision = -1; bool nonGreedy = false; diff --git a/runtime/Cpp/runtime/src/atn/EpsilonTransition.h b/runtime/Cpp/runtime/src/atn/EpsilonTransition.h index f335c31500b..2cc9cf0b614 100755 --- a/runtime/Cpp/runtime/src/atn/EpsilonTransition.h +++ b/runtime/Cpp/runtime/src/atn/EpsilonTransition.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC EpsilonTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::EPSILON; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + explicit EpsilonTransition(ATNState *target); EpsilonTransition(ATNState *target, size_t outermostPrecedenceReturn); diff --git a/runtime/Cpp/runtime/src/atn/LexerATNConfig.cpp b/runtime/Cpp/runtime/src/atn/LexerATNConfig.cpp index 1cf40ae93ef..fdb93040327 100755 --- a/runtime/Cpp/runtime/src/atn/LexerATNConfig.cpp +++ b/runtime/Cpp/runtime/src/atn/LexerATNConfig.cpp @@ -10,6 +10,7 @@ #include "atn/LexerActionExecutor.h" #include "support/CPPUtils.h" +#include "support/Casts.h" #include "atn/LexerATNConfig.h" @@ -62,5 +63,5 @@ bool LexerATNConfig::operator==(const LexerATNConfig& other) const bool LexerATNConfig::checkNonGreedyDecision(LexerATNConfig const& source, ATNState *target) { return source._passedThroughNonGreedyDecision || - (is(target) && (static_cast(target))->nonGreedy); + (DecisionState::is(target) && downCast(target)->nonGreedy); } diff --git a/runtime/Cpp/runtime/src/atn/LexerChannelAction.h b/runtime/Cpp/runtime/src/atn/LexerChannelAction.h index 3e6233061f1..219824d1f11 100755 --- a/runtime/Cpp/runtime/src/atn/LexerChannelAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerChannelAction.h @@ -22,6 +22,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerChannelAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::CHANNEL; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Constructs a new {@code channel} action with the specified channel value. /// The channel value to pass to . diff --git a/runtime/Cpp/runtime/src/atn/LexerCustomAction.h b/runtime/Cpp/runtime/src/atn/LexerCustomAction.h index ca3ef035510..3534f72e464 100755 --- a/runtime/Cpp/runtime/src/atn/LexerCustomAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerCustomAction.h @@ -26,6 +26,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerCustomAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::CUSTOM; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Constructs a custom lexer action with the specified rule and action /// indexes. diff --git a/runtime/Cpp/runtime/src/atn/LexerModeAction.h b/runtime/Cpp/runtime/src/atn/LexerModeAction.h index 511ae3bf5cd..bfcf5991c73 100755 --- a/runtime/Cpp/runtime/src/atn/LexerModeAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerModeAction.h @@ -20,6 +20,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerModeAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::MODE; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Constructs a new {@code mode} action with the specified mode value. /// The mode value to pass to . diff --git a/runtime/Cpp/runtime/src/atn/LexerMoreAction.h b/runtime/Cpp/runtime/src/atn/LexerMoreAction.h index 93f4a5da053..b0d3d43eb41 100755 --- a/runtime/Cpp/runtime/src/atn/LexerMoreAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerMoreAction.h @@ -22,6 +22,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerMoreAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::MORE; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Provides a singleton instance of this parameterless lexer action. /// diff --git a/runtime/Cpp/runtime/src/atn/LexerPopModeAction.h b/runtime/Cpp/runtime/src/atn/LexerPopModeAction.h index 92eb29a2cd8..b751375df96 100755 --- a/runtime/Cpp/runtime/src/atn/LexerPopModeAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerPopModeAction.h @@ -22,6 +22,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerPopModeAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::POP_MODE; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Provides a singleton instance of this parameterless lexer action. /// diff --git a/runtime/Cpp/runtime/src/atn/LexerPushModeAction.h b/runtime/Cpp/runtime/src/atn/LexerPushModeAction.h index ecef8dbeb2d..9cc200c6a3e 100755 --- a/runtime/Cpp/runtime/src/atn/LexerPushModeAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerPushModeAction.h @@ -20,6 +20,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerPushModeAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::PUSH_MODE; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Constructs a new {@code pushMode} action with the specified mode value. /// The mode value to pass to . diff --git a/runtime/Cpp/runtime/src/atn/LexerSkipAction.h b/runtime/Cpp/runtime/src/atn/LexerSkipAction.h index c4c9f4a77f7..1efbad072df 100755 --- a/runtime/Cpp/runtime/src/atn/LexerSkipAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerSkipAction.h @@ -22,6 +22,10 @@ namespace atn { /// class ANTLR4CPP_PUBLIC LexerSkipAction final : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::SKIP; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// Provides a singleton instance of this parameterless lexer action. static const Ref& getInstance(); diff --git a/runtime/Cpp/runtime/src/atn/LexerTypeAction.h b/runtime/Cpp/runtime/src/atn/LexerTypeAction.h index e44b853a2a2..d5ec27366d9 100755 --- a/runtime/Cpp/runtime/src/atn/LexerTypeAction.h +++ b/runtime/Cpp/runtime/src/atn/LexerTypeAction.h @@ -15,6 +15,10 @@ namespace atn { /// with the assigned type. class ANTLR4CPP_PUBLIC LexerTypeAction : public LexerAction { public: + static bool is(const LexerAction &lexerAction) { return lexerAction.getActionType() == LexerActionType::TYPE; } + + static bool is(const LexerAction *lexerAction) { return lexerAction != nullptr && is(*lexerAction); } + /// /// Constructs a new {@code type} action with the specified token type value. /// The type to assign to the token using . diff --git a/runtime/Cpp/runtime/src/atn/LoopEndState.h b/runtime/Cpp/runtime/src/atn/LoopEndState.h index ec496bd9285..b680414ebff 100755 --- a/runtime/Cpp/runtime/src/atn/LoopEndState.h +++ b/runtime/Cpp/runtime/src/atn/LoopEndState.h @@ -13,6 +13,10 @@ namespace atn { /// Mark the end of a * or + loop. class ANTLR4CPP_PUBLIC LoopEndState final : public ATNState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::LOOP_END; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + ATNState *loopBackState = nullptr; LoopEndState() : ATNState(ATNStateType::LOOP_END) {} diff --git a/runtime/Cpp/runtime/src/atn/NotSetTransition.cpp b/runtime/Cpp/runtime/src/atn/NotSetTransition.cpp index 4c6af9bbb92..b652290d4ec 100755 --- a/runtime/Cpp/runtime/src/atn/NotSetTransition.cpp +++ b/runtime/Cpp/runtime/src/atn/NotSetTransition.cpp @@ -10,8 +10,7 @@ using namespace antlr4; using namespace antlr4::atn; -NotSetTransition::NotSetTransition(ATNState *target, misc::IntervalSet set) : SetTransition(TransitionType::NOT_SET, target, std::move(set)) { -} +NotSetTransition::NotSetTransition(ATNState *target, misc::IntervalSet set) : SetTransition(TransitionType::NOT_SET, target, std::move(set)) {} bool NotSetTransition::matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const { return symbol >= minVocabSymbol && symbol <= maxVocabSymbol diff --git a/runtime/Cpp/runtime/src/atn/NotSetTransition.h b/runtime/Cpp/runtime/src/atn/NotSetTransition.h index 6de1a6e07c3..5c88ec10946 100755 --- a/runtime/Cpp/runtime/src/atn/NotSetTransition.h +++ b/runtime/Cpp/runtime/src/atn/NotSetTransition.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC NotSetTransition final : public SetTransition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::NOT_SET; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + NotSetTransition(ATNState *target, misc::IntervalSet set); virtual bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override; diff --git a/runtime/Cpp/runtime/src/atn/PlusBlockStartState.h b/runtime/Cpp/runtime/src/atn/PlusBlockStartState.h index 1b0e3cab767..6f67a8acadf 100755 --- a/runtime/Cpp/runtime/src/atn/PlusBlockStartState.h +++ b/runtime/Cpp/runtime/src/atn/PlusBlockStartState.h @@ -16,6 +16,10 @@ namespace atn { /// real decision-making note for {@code A+}. class ANTLR4CPP_PUBLIC PlusBlockStartState final : public BlockStartState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::PLUS_BLOCK_START; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + PlusLoopbackState *loopBackState = nullptr; PlusBlockStartState() : BlockStartState(ATNStateType::PLUS_BLOCK_START) {} diff --git a/runtime/Cpp/runtime/src/atn/PlusLoopbackState.h b/runtime/Cpp/runtime/src/atn/PlusLoopbackState.h index 470198b0444..d83ed7d0219 100755 --- a/runtime/Cpp/runtime/src/atn/PlusLoopbackState.h +++ b/runtime/Cpp/runtime/src/atn/PlusLoopbackState.h @@ -14,6 +14,10 @@ namespace atn { /// one to the loop back to start of the block and one to exit. class ANTLR4CPP_PUBLIC PlusLoopbackState final : public DecisionState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::PLUS_LOOP_BACK; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + PlusLoopbackState() : DecisionState(ATNStateType::PLUS_LOOP_BACK) {} }; diff --git a/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h b/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h index 9c340e7debb..1bf83fb721a 100755 --- a/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h +++ b/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h @@ -13,6 +13,10 @@ namespace atn { class ANTLR4CPP_PUBLIC PrecedencePredicateTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::PRECEDENCE; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + PrecedencePredicateTransition(ATNState *target, int precedence); int getPrecedence() const { return _predicate->precedence; } diff --git a/runtime/Cpp/runtime/src/atn/PredicateTransition.h b/runtime/Cpp/runtime/src/atn/PredicateTransition.h index 17fafb2b749..e889b1c1981 100755 --- a/runtime/Cpp/runtime/src/atn/PredicateTransition.h +++ b/runtime/Cpp/runtime/src/atn/PredicateTransition.h @@ -18,6 +18,10 @@ namespace atn { /// multiple ATN configurations into a single DFA state. class ANTLR4CPP_PUBLIC PredicateTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::PREDICATE; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + PredicateTransition(ATNState *target, size_t ruleIndex, size_t predIndex, bool isCtxDependent); size_t getRuleIndex() const { diff --git a/runtime/Cpp/runtime/src/atn/RangeTransition.h b/runtime/Cpp/runtime/src/atn/RangeTransition.h index 78b03d397f7..721b712d41c 100755 --- a/runtime/Cpp/runtime/src/atn/RangeTransition.h +++ b/runtime/Cpp/runtime/src/atn/RangeTransition.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC RangeTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::RANGE; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + const size_t from; const size_t to; diff --git a/runtime/Cpp/runtime/src/atn/RuleStopState.h b/runtime/Cpp/runtime/src/atn/RuleStopState.h index 61f2f8b39a9..e5f4dc4ca94 100755 --- a/runtime/Cpp/runtime/src/atn/RuleStopState.h +++ b/runtime/Cpp/runtime/src/atn/RuleStopState.h @@ -16,6 +16,10 @@ namespace atn { /// error handling. class ANTLR4CPP_PUBLIC RuleStopState final : public ATNState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::RULE_STOP; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + RuleStopState() : ATNState(ATNStateType::RULE_STOP) {} }; diff --git a/runtime/Cpp/runtime/src/atn/RuleTransition.h b/runtime/Cpp/runtime/src/atn/RuleTransition.h index 505b59e482b..943152d09af 100755 --- a/runtime/Cpp/runtime/src/atn/RuleTransition.h +++ b/runtime/Cpp/runtime/src/atn/RuleTransition.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC RuleTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::RULE; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + /// Ptr to the rule definition object for this rule ref. const size_t ruleIndex; // no Rule object at runtime diff --git a/runtime/Cpp/runtime/src/atn/SemanticContext.h b/runtime/Cpp/runtime/src/atn/SemanticContext.h index 4693f7841de..b80b28829d5 100755 --- a/runtime/Cpp/runtime/src/atn/SemanticContext.h +++ b/runtime/Cpp/runtime/src/atn/SemanticContext.h @@ -99,6 +99,10 @@ namespace atn { class ANTLR4CPP_PUBLIC SemanticContext::Predicate final : public SemanticContext { public: + static bool is(const SemanticContext &semanticContext) { return semanticContext.getContextType() == SemanticContextType::PREDICATE; } + + static bool is(const SemanticContext *semanticContext) { return semanticContext != nullptr && is(*semanticContext); } + const size_t ruleIndex; const size_t predIndex; const bool isCtxDependent; // e.g., $i ref in pred @@ -113,6 +117,10 @@ namespace atn { class ANTLR4CPP_PUBLIC SemanticContext::PrecedencePredicate final : public SemanticContext { public: + static bool is(const SemanticContext &semanticContext) { return semanticContext.getContextType() == SemanticContextType::PRECEDENCE; } + + static bool is(const SemanticContext *semanticContext) { return semanticContext != nullptr && is(*semanticContext); } + const int precedence; explicit PrecedencePredicate(int precedence); @@ -132,6 +140,13 @@ namespace atn { */ class ANTLR4CPP_PUBLIC SemanticContext::Operator : public SemanticContext { public: + static bool is(const SemanticContext &semanticContext) { + const auto contextType = semanticContext.getContextType(); + return contextType == SemanticContextType::AND || contextType == SemanticContextType::OR; + } + + static bool is(const SemanticContext *semanticContext) { return semanticContext != nullptr && is(*semanticContext); } + /** * Gets the operands for the semantic context operator. * @@ -153,6 +168,10 @@ namespace atn { */ class ANTLR4CPP_PUBLIC SemanticContext::AND final : public SemanticContext::Operator { public: + static bool is(const SemanticContext &semanticContext) { return semanticContext.getContextType() == SemanticContextType::AND; } + + static bool is(const SemanticContext *semanticContext) { return semanticContext != nullptr && is(*semanticContext); } + AND(Ref a, Ref b) ; const std::vector>& getOperands() const override; @@ -177,6 +196,10 @@ namespace atn { */ class ANTLR4CPP_PUBLIC SemanticContext::OR final : public SemanticContext::Operator { public: + static bool is(const SemanticContext &semanticContext) { return semanticContext.getContextType() == SemanticContextType::OR; } + + static bool is(const SemanticContext *semanticContext) { return semanticContext != nullptr && is(*semanticContext); } + OR(Ref a, Ref b); const std::vector>& getOperands() const override; diff --git a/runtime/Cpp/runtime/src/atn/SetTransition.cpp b/runtime/Cpp/runtime/src/atn/SetTransition.cpp index 69395832e8f..75d13a367a2 100755 --- a/runtime/Cpp/runtime/src/atn/SetTransition.cpp +++ b/runtime/Cpp/runtime/src/atn/SetTransition.cpp @@ -11,8 +11,8 @@ using namespace antlr4; using namespace antlr4::atn; -SetTransition::SetTransition(TransitionType transitionType, ATNState *target, misc::IntervalSet aSet) - : Transition(transitionType, target), set(aSet.isEmpty() ? misc::IntervalSet::of(Token::INVALID_TYPE) : std::move(aSet)) { +SetTransition::SetTransition(ATNState *target, misc::IntervalSet aSet) + : Transition(TransitionType::SET, target), set(aSet.isEmpty() ? misc::IntervalSet::of(Token::INVALID_TYPE) : std::move(aSet)) { } misc::IntervalSet SetTransition::label() const { diff --git a/runtime/Cpp/runtime/src/atn/SetTransition.h b/runtime/Cpp/runtime/src/atn/SetTransition.h index e142784d156..9f3eca0a920 100755 --- a/runtime/Cpp/runtime/src/atn/SetTransition.h +++ b/runtime/Cpp/runtime/src/atn/SetTransition.h @@ -14,9 +14,16 @@ namespace atn { /// A transition containing a set of values. class ANTLR4CPP_PUBLIC SetTransition : public Transition { public: + static bool is(const Transition &transition) { + const auto transitionType = transition.getTransitionType(); + return transitionType == TransitionType::SET || transitionType == TransitionType::NOT_SET; + } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + const misc::IntervalSet set; - SetTransition(ATNState *target, misc::IntervalSet set) : SetTransition(TransitionType::SET, target, std::move(set)) {} + SetTransition(ATNState *target, misc::IntervalSet set); virtual misc::IntervalSet label() const override; virtual bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override; diff --git a/runtime/Cpp/runtime/src/atn/SingletonPredictionContext.h b/runtime/Cpp/runtime/src/atn/SingletonPredictionContext.h index 28768c8b068..b30c6c2b02d 100755 --- a/runtime/Cpp/runtime/src/atn/SingletonPredictionContext.h +++ b/runtime/Cpp/runtime/src/atn/SingletonPredictionContext.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC SingletonPredictionContext final : public PredictionContext { public: + static bool is(const PredictionContext &predictionContext) { return predictionContext.getContextType() == PredictionContextType::SINGLETON; } + + static bool is(const PredictionContext *predictionContext) { return predictionContext != nullptr && is(*predictionContext); } + // Usually a parent is linked via a weak ptr. Not so here as we have kinda reverse reference chain. // There are no child contexts stored here and often the parent context is left dangling when it's // owning ATNState is released. In order to avoid having this context released as well (leaving all other contexts @@ -21,7 +25,6 @@ namespace atn { const size_t returnState; SingletonPredictionContext(Ref parent, size_t returnState); - virtual ~SingletonPredictionContext() = default; static Ref create(Ref parent, size_t returnState); diff --git a/runtime/Cpp/runtime/src/atn/StarBlockStartState.h b/runtime/Cpp/runtime/src/atn/StarBlockStartState.h index 74dd5906e22..a162631dec4 100755 --- a/runtime/Cpp/runtime/src/atn/StarBlockStartState.h +++ b/runtime/Cpp/runtime/src/atn/StarBlockStartState.h @@ -13,6 +13,10 @@ namespace atn { /// The block that begins a closure loop. class ANTLR4CPP_PUBLIC StarBlockStartState final : public BlockStartState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::STAR_BLOCK_START; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + StarBlockStartState() : BlockStartState(ATNStateType::STAR_BLOCK_START) {} }; diff --git a/runtime/Cpp/runtime/src/atn/StarLoopEntryState.h b/runtime/Cpp/runtime/src/atn/StarLoopEntryState.h index 4054a14b327..c3f47b8f70d 100755 --- a/runtime/Cpp/runtime/src/atn/StarLoopEntryState.h +++ b/runtime/Cpp/runtime/src/atn/StarLoopEntryState.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC StarLoopEntryState final : public DecisionState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::STAR_LOOP_ENTRY; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + /** * Indicates whether this state can benefit from a precedence DFA during SLL * decision making. diff --git a/runtime/Cpp/runtime/src/atn/StarLoopbackState.h b/runtime/Cpp/runtime/src/atn/StarLoopbackState.h index 4eebbfcdfc9..0780b4c25db 100755 --- a/runtime/Cpp/runtime/src/atn/StarLoopbackState.h +++ b/runtime/Cpp/runtime/src/atn/StarLoopbackState.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC StarLoopbackState final : public ATNState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::STAR_LOOP_BACK; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + StarLoopbackState() : ATNState(ATNStateType::STAR_LOOP_BACK) {} StarLoopEntryState *getLoopEntryState() const; diff --git a/runtime/Cpp/runtime/src/atn/TokensStartState.h b/runtime/Cpp/runtime/src/atn/TokensStartState.h index b67194e5d90..e1d043e78ff 100755 --- a/runtime/Cpp/runtime/src/atn/TokensStartState.h +++ b/runtime/Cpp/runtime/src/atn/TokensStartState.h @@ -13,6 +13,10 @@ namespace atn { /// The Tokens rule start state linking to each lexer rule start state. class ANTLR4CPP_PUBLIC TokensStartState final : public DecisionState { public: + static bool is(const ATNState &atnState) { return atnState.getStateType() == ATNStateType::TOKEN_START; } + + static bool is(const ATNState *atnState) { return atnState != nullptr && is(*atnState); } + TokensStartState() : DecisionState(ATNStateType::TOKEN_START) {} }; diff --git a/runtime/Cpp/runtime/src/atn/WildcardTransition.h b/runtime/Cpp/runtime/src/atn/WildcardTransition.h index 3ed5f3426c7..e088e8934f2 100755 --- a/runtime/Cpp/runtime/src/atn/WildcardTransition.h +++ b/runtime/Cpp/runtime/src/atn/WildcardTransition.h @@ -12,6 +12,10 @@ namespace atn { class ANTLR4CPP_PUBLIC WildcardTransition final : public Transition { public: + static bool is(const Transition &transition) { return transition.getTransitionType() == TransitionType::WILDCARD; } + + static bool is(const Transition *transition) { return transition != nullptr && is(*transition); } + explicit WildcardTransition(ATNState *target); virtual bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override; diff --git a/runtime/Cpp/runtime/src/tree/ErrorNode.h b/runtime/Cpp/runtime/src/tree/ErrorNode.h index a9d66396297..c77a5a246a7 100755 --- a/runtime/Cpp/runtime/src/tree/ErrorNode.h +++ b/runtime/Cpp/runtime/src/tree/ErrorNode.h @@ -11,6 +11,11 @@ namespace antlr4 { namespace tree { class ANTLR4CPP_PUBLIC ErrorNode : public TerminalNode { + public: + static bool is(const tree::ParseTree &parseTree) { return parseTree.getTreeType() == tree::ParseTreeType::ERROR; } + + static bool is(const tree::ParseTree *parseTree) { return parseTree != nullptr && is(*parseTree); } + protected: using TerminalNode::TerminalNode; }; diff --git a/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp b/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp index 2e21942d35e..83e6339518d 100644 --- a/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp +++ b/runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp @@ -4,6 +4,7 @@ */ #include "support/CPPUtils.h" +#include "support/Casts.h" #include "tree/ParseTreeListener.h" #include "tree/ParseTree.h" @@ -12,33 +13,26 @@ #include "IterativeParseTreeWalker.h" using namespace antlr4::tree; +using namespace antlrcpp; void IterativeParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const { - - std::vector nodeStack; - std::vector indexStack; - + std::vector> stack; ParseTree *currentNode = t; size_t currentIndex = 0; while (currentNode != nullptr) { // pre-order visit - switch (currentNode->getTreeType()) { - case ParseTreeType::ERROR: - listener->visitErrorNode(dynamic_cast(currentNode)); - break; - case ParseTreeType::TERMINAL: - listener->visitTerminal(dynamic_cast(currentNode)); - break; - case ParseTreeType::RULE: - enterRule(listener, currentNode); - break; + if (ErrorNode::is(*currentNode)) { + listener->visitErrorNode(downCast(currentNode)); + } else if (TerminalNode::is(*currentNode)) { + listener->visitTerminal(downCast(currentNode)); + } else { + enterRule(listener, currentNode); } // Move down to first child, if it exists. if (!currentNode->children.empty()) { - nodeStack.push_back(currentNode); - indexStack.push_back(currentIndex); + stack.push_back(std::make_pair(currentNode, currentIndex)); currentIndex = 0; currentNode = currentNode->children[0]; continue; @@ -47,29 +41,26 @@ void IterativeParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) c // No child nodes, so walk tree. do { // post-order visit - if (currentNode->getTreeType() == ParseTreeType::RULE) { + if (!TerminalNode::is(*currentNode)) { exitRule(listener, currentNode); } // No parent, so no siblings. - if (nodeStack.empty()) { + if (stack.empty()) { currentNode = nullptr; currentIndex = 0; break; } // Move to next sibling if possible. - if (nodeStack.back()->children.size() > ++currentIndex) { - currentNode = nodeStack.back()->children[currentIndex]; + if (stack.back().first->children.size() > ++currentIndex) { + currentNode = stack.back().first->children[currentIndex]; break; } // No next sibling, so move up. - currentNode = nodeStack.back(); - nodeStack.pop_back(); - currentIndex = indexStack.back(); - indexStack.pop_back(); - + std::tie(currentNode, currentIndex) = stack.back(); + stack.pop_back(); } while (currentNode != nullptr); } } diff --git a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp index 998c9ed55d7..1eeabff883c 100755 --- a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp +++ b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp @@ -7,6 +7,7 @@ #include "ParserRuleContext.h" #include "tree/ParseTreeListener.h" #include "support/CPPUtils.h" +#include "support/Casts.h" #include "tree/IterativeParseTreeWalker.h" #include "tree/ParseTreeWalker.h" @@ -17,15 +18,13 @@ using namespace antlrcpp; static IterativeParseTreeWalker defaultWalker; ParseTreeWalker &ParseTreeWalker::DEFAULT = defaultWalker; -ParseTreeWalker::~ParseTreeWalker() { -} - void ParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const { - if (is(t)) { - listener->visitErrorNode(dynamic_cast(t)); + if (ErrorNode::is(*t)) { + listener->visitErrorNode(downCast(t)); return; - } else if (is(t)) { - listener->visitTerminal(dynamic_cast(t)); + } + if (TerminalNode::is(*t)) { + listener->visitTerminal(downCast(t)); return; } @@ -37,13 +36,13 @@ void ParseTreeWalker::walk(ParseTreeListener *listener, ParseTree *t) const { } void ParseTreeWalker::enterRule(ParseTreeListener *listener, ParseTree *r) const { - ParserRuleContext *ctx = dynamic_cast(r); + auto *ctx = downCast(r); listener->enterEveryRule(ctx); ctx->enterRule(listener); } void ParseTreeWalker::exitRule(ParseTreeListener *listener, ParseTree *r) const { - ParserRuleContext *ctx = dynamic_cast(r); + auto *ctx = downCast(r); ctx->exitRule(listener); listener->exitEveryRule(ctx); } diff --git a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h index 166ad806b4a..375e6597854 100755 --- a/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h +++ b/runtime/Cpp/runtime/src/tree/ParseTreeWalker.h @@ -14,8 +14,8 @@ namespace tree { public: static ParseTreeWalker &DEFAULT; - virtual ~ParseTreeWalker(); - + virtual ~ParseTreeWalker() = default; + /** * * Performs a walk on the given parse tree starting at the root and going down recursively @@ -29,7 +29,7 @@ namespace tree { virtual void walk(ParseTreeListener *listener, ParseTree *t) const; protected: - + /** * * Enters a grammar rule by first triggering the generic event @@ -39,7 +39,7 @@ namespace tree { * The grammar rule containing the rule context */ virtual void enterRule(ParseTreeListener *listener, ParseTree *r) const; - + /** * * Exits a grammar rule by first triggering the event specific to the given parse tree node diff --git a/runtime/Cpp/runtime/src/tree/TerminalNode.h b/runtime/Cpp/runtime/src/tree/TerminalNode.h index 7c075a8ace7..421e7ad7953 100755 --- a/runtime/Cpp/runtime/src/tree/TerminalNode.h +++ b/runtime/Cpp/runtime/src/tree/TerminalNode.h @@ -12,6 +12,13 @@ namespace tree { class ANTLR4CPP_PUBLIC TerminalNode : public ParseTree { public: + static bool is(const tree::ParseTree &parseTree) { + const auto treeType = parseTree.getTreeType(); + return treeType == ParseTreeType::TERMINAL || treeType == ParseTreeType::ERROR; + } + + static bool is(const tree::ParseTree *parseTree) { return parseTree != nullptr && is(*parseTree); } + virtual Token* getSymbol() const = 0; /** Set the parent for this leaf node.