From fb7b12ebc4b73ac846dc9923956262e8997d22d4 Mon Sep 17 00:00:00 2001
From: Justin King
Date: Tue, 22 Mar 2022 12:15:54 -0700
Subject: [PATCH] [C++] Refactor and optimize SemanticContext
---
.../runtime/src/FailedPredicateException.cpp | 7 +-
runtime/Cpp/runtime/src/ParserInterpreter.cpp | 6 +-
runtime/Cpp/runtime/src/antlr4-runtime.h | 1 -
.../src/atn/AbstractPredicateTransition.cpp | 11 -
.../src/atn/AbstractPredicateTransition.h | 21 --
runtime/Cpp/runtime/src/atn/LL1Analyzer.cpp | 1 -
.../Cpp/runtime/src/atn/LexerATNSimulator.cpp | 4 +-
.../runtime/src/atn/ParserATNSimulator.cpp | 18 +-
.../src/atn/PrecedencePredicateTransition.cpp | 9 +-
.../src/atn/PrecedencePredicateTransition.h | 21 +-
.../runtime/src/atn/PredicateTransition.cpp | 14 +-
.../Cpp/runtime/src/atn/PredicateTransition.h | 32 ++-
.../Cpp/runtime/src/atn/SemanticContext.cpp | 247 +++++++++++-------
runtime/Cpp/runtime/src/atn/SemanticContext.h | 118 +++++----
.../Cpp/runtime/src/atn/SemanticContextType.h | 23 ++
.../Cpp/runtime/src/support/Declarations.h | 1 -
16 files changed, 288 insertions(+), 246 deletions(-)
delete mode 100755 runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.cpp
delete mode 100755 runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.h
create mode 100644 runtime/Cpp/runtime/src/atn/SemanticContextType.h
diff --git a/runtime/Cpp/runtime/src/FailedPredicateException.cpp b/runtime/Cpp/runtime/src/FailedPredicateException.cpp
index 459f449e0d..b44725cce8 100755
--- a/runtime/Cpp/runtime/src/FailedPredicateException.cpp
+++ b/runtime/Cpp/runtime/src/FailedPredicateException.cpp
@@ -8,6 +8,7 @@
#include "atn/PredicateTransition.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
+#include "support/Casts.h"
#include "support/CPPUtils.h"
#include "FailedPredicateException.h"
@@ -27,9 +28,9 @@ FailedPredicateException::FailedPredicateException(Parser *recognizer, const std
atn::ATNState *s = recognizer->getInterpreter()->atn.states[recognizer->getState()];
const atn::Transition *transition = s->transitions[0].get();
- if (is(transition)) {
- _ruleIndex = static_cast(transition)->ruleIndex;
- _predicateIndex = static_cast(transition)->predIndex;
+ if (transition->getTransitionType() == atn::TransitionType::PREDICATE) {
+ _ruleIndex = downCast(*transition).getRuleIndex();
+ _predicateIndex = downCast(*transition).getPredIndex();
} else {
_ruleIndex = 0;
_predicateIndex = 0;
diff --git a/runtime/Cpp/runtime/src/ParserInterpreter.cpp b/runtime/Cpp/runtime/src/ParserInterpreter.cpp
index 38195fab76..8b7c805445 100755
--- a/runtime/Cpp/runtime/src/ParserInterpreter.cpp
+++ b/runtime/Cpp/runtime/src/ParserInterpreter.cpp
@@ -199,7 +199,7 @@ void ParserInterpreter::visitState(atn::ATNState *p) {
case atn::TransitionType::PREDICATE:
{
const atn::PredicateTransition *predicateTransition = static_cast(transition);
- if (!sempred(_ctx, predicateTransition->ruleIndex, predicateTransition->predIndex)) {
+ if (!sempred(_ctx, predicateTransition->getRuleIndex(), predicateTransition->getPredIndex())) {
throw FailedPredicateException(this);
}
}
@@ -214,8 +214,8 @@ void ParserInterpreter::visitState(atn::ATNState *p) {
case atn::TransitionType::PRECEDENCE:
{
- if (!precpred(_ctx, static_cast(transition)->precedence)) {
- throw FailedPredicateException(this, "precpred(_ctx, " + std::to_string(static_cast(transition)->precedence) + ")");
+ if (!precpred(_ctx, static_cast(transition)->getPrecedence())) {
+ throw FailedPredicateException(this, "precpred(_ctx, " + std::to_string(static_cast(transition)->getPrecedence()) + ")");
}
}
break;
diff --git a/runtime/Cpp/runtime/src/antlr4-runtime.h b/runtime/Cpp/runtime/src/antlr4-runtime.h
index 193ea68964..722df6d075 100644
--- a/runtime/Cpp/runtime/src/antlr4-runtime.h
+++ b/runtime/Cpp/runtime/src/antlr4-runtime.h
@@ -60,7 +60,6 @@
#include "atn/ATNSimulator.h"
#include "atn/ATNState.h"
#include "atn/ATNType.h"
-#include "atn/AbstractPredicateTransition.h"
#include "atn/ActionTransition.h"
#include "atn/AmbiguityInfo.h"
#include "atn/ArrayPredictionContext.h"
diff --git a/runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.cpp b/runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.cpp
deleted file mode 100755
index d5c131d76a..0000000000
--- a/runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-/* 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/AbstractPredicateTransition.h"
-
-using namespace antlr4::atn;
-
-AbstractPredicateTransition::AbstractPredicateTransition(ATNState *target) : Transition(target) {
-}
diff --git a/runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.h b/runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.h
deleted file mode 100755
index ee05b587f3..0000000000
--- a/runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* 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.
- */
-
-#pragma once
-
-#include "atn/Transition.h"
-
-namespace antlr4 {
-namespace atn {
-
- class ANTState;
-
- class ANTLR4CPP_PUBLIC AbstractPredicateTransition : public Transition {
- public:
- explicit AbstractPredicateTransition(ATNState *target);
- };
-
-} // namespace atn
-} // namespace antlr4
diff --git a/runtime/Cpp/runtime/src/atn/LL1Analyzer.cpp b/runtime/Cpp/runtime/src/atn/LL1Analyzer.cpp
index 4f28d8d5cd..1e6da892e0 100755
--- a/runtime/Cpp/runtime/src/atn/LL1Analyzer.cpp
+++ b/runtime/Cpp/runtime/src/atn/LL1Analyzer.cpp
@@ -7,7 +7,6 @@
#include "atn/Transition.h"
#include "atn/RuleTransition.h"
#include "atn/SingletonPredictionContext.h"
-#include "atn/AbstractPredicateTransition.h"
#include "atn/WildcardTransition.h"
#include "atn/NotSetTransition.h"
#include "misc/IntervalSet.h"
diff --git a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp
index b6eaff5265..ab7ba7a938 100755
--- a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp
+++ b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp
@@ -392,11 +392,11 @@ Ref LexerATNSimulator::getEpsilonTarget(CharStream *input, const
const PredicateTransition *pt = static_cast(t);
#if DEBUG_ATN == 1
- std::cout << "EVAL rule " << pt->ruleIndex << ":" << pt->predIndex << std::endl;
+ std::cout << "EVAL rule " << pt->getRuleIndex() << ":" << pt->getPredIndex() << std::endl;
#endif
configs->hasSemanticContext = true;
- if (evaluatePredicate(input, pt->ruleIndex, pt->predIndex, speculative)) {
+ if (evaluatePredicate(input, pt->getRuleIndex(), pt->getPredIndex(), speculative)) {
c = std::make_shared(*config, t->target);
}
break;
diff --git a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp
index 77102d1800..534d11078c 100755
--- a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp
+++ b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp
@@ -1088,7 +1088,7 @@ Ref ParserATNSimulator::actionTransition(Ref const& config
Ref ParserATNSimulator::precedenceTransition(Ref const& config, const PrecedencePredicateTransition *pt,
bool collectPredicates, bool inContext, bool fullCtx) {
#if DEBUG_DFA == 1
- std::cout << "PRED (collectPredicates=" << collectPredicates << ") " << pt->precedence << ">=_p" << ", ctx dependent=true" << std::endl;
+ 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;
}
@@ -1096,7 +1096,7 @@ Ref ParserATNSimulator::precedenceTransition(Ref const& co
Ref c;
if (collectPredicates && inContext) {
- Ref predicate = pt->getPredicate();
+ const auto &predicate = pt->getPredicate();
if (fullCtx) {
// In full context mode, we can evaluate predicates on-the-fly
@@ -1105,14 +1105,14 @@ Ref ParserATNSimulator::precedenceTransition(Ref const& co
// later during conflict resolution.
size_t currentPosition = _input->index();
_input->seek(_startIndex);
- bool predSucceeds = evalSemanticContext(pt->getPredicate(), _outerContext, config->alt, fullCtx);
+ bool predSucceeds = evalSemanticContext(predicate, _outerContext, config->alt, fullCtx);
_input->seek(currentPosition);
if (predSucceeds) {
c = std::make_shared(*config, pt->target); // no pred context
}
} else {
Ref newSemCtx = SemanticContext::And(config->semanticContext, predicate);
- c = std::make_shared(*config, pt->target, newSemCtx);
+ c = std::make_shared(*config, pt->target, std::move(newSemCtx));
}
} else {
c = std::make_shared(*config, pt->target);
@@ -1128,15 +1128,15 @@ Ref ParserATNSimulator::precedenceTransition(Ref const& co
Ref ParserATNSimulator::predTransition(Ref const& config, const PredicateTransition *pt,
bool collectPredicates, bool inContext, bool fullCtx) {
#if DEBUG_DFA == 1
- std::cout << "PRED (collectPredicates=" << collectPredicates << ") " << pt->ruleIndex << ":" << pt->predIndex << ", ctx dependent=" << pt->isCtxDependent << std::endl;
+ 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 c = nullptr;
- if (collectPredicates && (!pt->isCtxDependent || (pt->isCtxDependent && inContext))) {
- Ref predicate = pt->getPredicate();
+ if (collectPredicates && (!pt->isCtxDependent() || (pt->isCtxDependent() && inContext))) {
+ const auto &predicate = pt->getPredicate();
if (fullCtx) {
// In full context mode, we can evaluate predicates on-the-fly
// during closure, which dramatically reduces the size of
@@ -1144,14 +1144,14 @@ Ref ParserATNSimulator::predTransition(Ref const& config,
// later during conflict resolution.
size_t currentPosition = _input->index();
_input->seek(_startIndex);
- bool predSucceeds = evalSemanticContext(pt->getPredicate(), _outerContext, config->alt, fullCtx);
+ bool predSucceeds = evalSemanticContext(predicate, _outerContext, config->alt, fullCtx);
_input->seek(currentPosition);
if (predSucceeds) {
c = std::make_shared(*config, pt->target); // no pred context
}
} else {
Ref newSemCtx = SemanticContext::And(config->semanticContext, predicate);
- c = std::make_shared(*config, pt->target, newSemCtx);
+ c = std::make_shared(*config, pt->target, std::move(newSemCtx));
}
} else {
c = std::make_shared(*config, pt->target);
diff --git a/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.cpp b/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.cpp
index 36f7bfa566..4e981a2a9c 100755
--- a/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.cpp
+++ b/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.cpp
@@ -8,8 +8,7 @@
using namespace antlr4::atn;
PrecedencePredicateTransition::PrecedencePredicateTransition(ATNState *target, int precedence)
- : AbstractPredicateTransition(target), precedence(precedence) {
-}
+ : Transition(target), _predicate(std::make_shared(precedence)) {}
TransitionType PrecedencePredicateTransition::getTransitionType() const {
return TransitionType::PRECEDENCE;
@@ -23,10 +22,6 @@ bool PrecedencePredicateTransition::matches(size_t /*symbol*/, size_t /*minVocab
return false;
}
-Ref PrecedencePredicateTransition::getPredicate() const {
- return std::make_shared(precedence);
-}
-
std::string PrecedencePredicateTransition::toString() const {
- return "PRECEDENCE " + Transition::toString() + " { precedence: " + std::to_string(precedence) + " }";
+ return "PRECEDENCE " + Transition::toString() + " { precedence: " + std::to_string(getPrecedence()) + " }";
}
diff --git a/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h b/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h
index 886b7a28f7..52d95914d7 100755
--- a/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h
+++ b/runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h
@@ -5,24 +5,27 @@
#pragma once
-#include "atn/AbstractPredicateTransition.h"
-#include "SemanticContext.h"
+#include "atn/Transition.h"
+#include "atn/SemanticContext.h"
namespace antlr4 {
namespace atn {
- class ANTLR4CPP_PUBLIC PrecedencePredicateTransition final : public AbstractPredicateTransition {
+ class ANTLR4CPP_PUBLIC PrecedencePredicateTransition final : public Transition {
public:
- const int precedence;
-
PrecedencePredicateTransition(ATNState *target, int precedence);
+ int getPrecedence() const { return _predicate->precedence; }
+
TransitionType getTransitionType() const override;
- virtual bool isEpsilon() const override;
- virtual bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override;
- Ref getPredicate() const;
- virtual std::string toString() const override;
+ bool isEpsilon() const override;
+ bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override;
+ std::string toString() const override;
+
+ const Ref& getPredicate() const { return _predicate; }
+ private:
+ const std::shared_ptr _predicate;
};
} // namespace atn
diff --git a/runtime/Cpp/runtime/src/atn/PredicateTransition.cpp b/runtime/Cpp/runtime/src/atn/PredicateTransition.cpp
index 2de6148aa9..394eaf691b 100755
--- a/runtime/Cpp/runtime/src/atn/PredicateTransition.cpp
+++ b/runtime/Cpp/runtime/src/atn/PredicateTransition.cpp
@@ -7,8 +7,8 @@
using namespace antlr4::atn;
-PredicateTransition::PredicateTransition(ATNState *target, size_t ruleIndex, size_t predIndex, bool isCtxDependent) : AbstractPredicateTransition(target), ruleIndex(ruleIndex), predIndex(predIndex), isCtxDependent(isCtxDependent) {
-}
+PredicateTransition::PredicateTransition(ATNState *target, size_t ruleIndex, size_t predIndex, bool isCtxDependent)
+ : Transition(target), _predicate(std::make_shared(ruleIndex, predIndex, isCtxDependent)) {}
TransitionType PredicateTransition::getTransitionType() const {
return TransitionType::PREDICATE;
@@ -22,13 +22,7 @@ bool PredicateTransition::matches(size_t /*symbol*/, size_t /*minVocabSymbol*/,
return false;
}
-Ref PredicateTransition::getPredicate() const {
- return std::make_shared(ruleIndex, predIndex, isCtxDependent);
-}
-
std::string PredicateTransition::toString() const {
- return "PREDICATE " + Transition::toString() + " { ruleIndex: " + std::to_string(ruleIndex) +
- ", predIndex: " + std::to_string(predIndex) + ", isCtxDependent: " + std::to_string(isCtxDependent) + " }";
-
- // Generate and add a predicate context here?
+ return "PREDICATE " + Transition::toString() + " { ruleIndex: " + std::to_string(getRuleIndex()) +
+ ", predIndex: " + std::to_string(getPredIndex()) + ", isCtxDependent: " + std::to_string(isCtxDependent()) + " }";
}
diff --git a/runtime/Cpp/runtime/src/atn/PredicateTransition.h b/runtime/Cpp/runtime/src/atn/PredicateTransition.h
index c9711baead..e41c0ad3e0 100755
--- a/runtime/Cpp/runtime/src/atn/PredicateTransition.h
+++ b/runtime/Cpp/runtime/src/atn/PredicateTransition.h
@@ -5,8 +5,8 @@
#pragma once
-#include "atn/AbstractPredicateTransition.h"
-#include "SemanticContext.h"
+#include "atn/Transition.h"
+#include "atn/SemanticContext.h"
namespace antlr4 {
namespace atn {
@@ -16,23 +16,31 @@ namespace atn {
/// In the ATN, labels will always be exactly one predicate, but the DFA
/// may have to combine a bunch of them as it collects predicates from
/// multiple ATN configurations into a single DFA state.
- class ANTLR4CPP_PUBLIC PredicateTransition final : public AbstractPredicateTransition {
+ class ANTLR4CPP_PUBLIC PredicateTransition final : public Transition {
public:
- const size_t ruleIndex;
- const size_t predIndex;
- const bool isCtxDependent; // e.g., $i ref in pred
-
PredicateTransition(ATNState *target, size_t ruleIndex, size_t predIndex, bool isCtxDependent);
- TransitionType getTransitionType() const override;
+ size_t getRuleIndex() const {
+ return _predicate->ruleIndex;
+ }
- virtual bool isEpsilon() const override;
- virtual bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override;
+ size_t getPredIndex() const {
+ return _predicate->predIndex;
+ }
- Ref getPredicate() const;
+ bool isCtxDependent() const {
+ return _predicate->isCtxDependent;
+ }
+
+ TransitionType getTransitionType() const override;
+ bool isEpsilon() const override;
+ bool matches(size_t symbol, size_t minVocabSymbol, size_t maxVocabSymbol) const override;
+ std::string toString() const override;
- virtual std::string toString() const override;
+ const Ref& getPredicate() const { return _predicate; }
+ private:
+ const std::shared_ptr _predicate;
};
} // namespace atn
diff --git a/runtime/Cpp/runtime/src/atn/SemanticContext.cpp b/runtime/Cpp/runtime/src/atn/SemanticContext.cpp
index 48aa410f11..f79210ed3c 100755
--- a/runtime/Cpp/runtime/src/atn/SemanticContext.cpp
+++ b/runtime/Cpp/runtime/src/atn/SemanticContext.cpp
@@ -38,7 +38,7 @@ namespace {
Ref &precedencePredicate,
Comparer comparer) {
if (semanticContext != nullptr) {
- if (is(semanticContext)) {
+ if (semanticContext->getContextType() == SemanticContextType::PRECEDENCE) {
if (precedencePredicate == nullptr || comparer(downCast(semanticContext.get())->precedence, precedencePredicate->precedence)) {
precedencePredicate = std::static_pointer_cast(semanticContext);
}
@@ -51,43 +51,79 @@ namespace {
}
}
-}
+ template
+ void insertSemanticContext(Ref &&semanticContext,
+ std::unordered_set &operandSet,
+ std::vector[> &operandList,
+ Ref &precedencePredicate,
+ Comparer comparer) {
+ if (semanticContext != nullptr) {
+ if (semanticContext->getContextType() == SemanticContextType::PRECEDENCE) {
+ if (precedencePredicate == nullptr || comparer(downCast(semanticContext.get())->precedence, precedencePredicate->precedence)) {
+ precedencePredicate = std::static_pointer_cast(std::move(semanticContext));
+ }
+ } else {
+ auto [existing, inserted] = operandSet.insert(semanticContext.get());
+ if (inserted) {
+ operandList.push_back(std::move(semanticContext));
+ }
+ }
+ }
+ }
-//------------------ Predicate -----------------------------------------------------------------------------------------
+ size_t predictOperandCapacity(const Ref &x) {
+ switch (x->getContextType()) {
+ case SemanticContextType::AND:
+ return downCast(*x).getOperands().size();
+ case SemanticContextType::OR:
+ return downCast(*x).getOperands().size();
+ default:
+ return 1;
+ }
+ }
+
+ size_t predictOperandCapacity(const Ref &a, const Ref &b) {
+ return predictOperandCapacity(a) + predictOperandCapacity(b);
+ }
-SemanticContext::Predicate::Predicate() : Predicate(INVALID_INDEX, INVALID_INDEX, false) {
}
+//------------------ Predicate -----------------------------------------------------------------------------------------
+
SemanticContext::Predicate::Predicate(size_t ruleIndex, size_t predIndex, bool isCtxDependent)
-: ruleIndex(ruleIndex), predIndex(predIndex), isCtxDependent(isCtxDependent) {
-}
+ : ruleIndex(ruleIndex), predIndex(predIndex), isCtxDependent(isCtxDependent) {}
+SemanticContextType SemanticContext::Predicate::getContextType() const {
+ return SemanticContextType::PREDICATE;
+}
bool SemanticContext::Predicate::eval(Recognizer *parser, RuleContext *parserCallStack) const {
RuleContext *localctx = nullptr;
- if (isCtxDependent)
+ if (isCtxDependent) {
localctx = parserCallStack;
+ }
return parser->sempred(localctx, ruleIndex, predIndex);
}
size_t SemanticContext::Predicate::hashCode() const {
size_t hashCode = misc::MurmurHash::initialize();
+ hashCode = misc::MurmurHash::update(hashCode, static_cast(getContextType()));
hashCode = misc::MurmurHash::update(hashCode, ruleIndex);
hashCode = misc::MurmurHash::update(hashCode, predIndex);
hashCode = misc::MurmurHash::update(hashCode, isCtxDependent ? 1 : 0);
- hashCode = misc::MurmurHash::finish(hashCode, 3);
+ hashCode = misc::MurmurHash::finish(hashCode, 4);
return hashCode;
}
-bool SemanticContext::Predicate::operator == (const SemanticContext &other) const {
- if (this == &other)
+bool SemanticContext::Predicate::equals(const SemanticContext &other) const {
+ if (this == &other) {
return true;
-
- const Predicate *p = dynamic_cast(&other);
- if (p == nullptr)
+ }
+ if (getContextType() != other.getContextType()) {
return false;
-
- return ruleIndex == p->ruleIndex && predIndex == p->predIndex && isCtxDependent == p->isCtxDependent;
+ }
+ const Predicate &p = downCast(other);
+ return ruleIndex == p.ruleIndex && predIndex == p.predIndex && isCtxDependent == p.isCtxDependent;
}
std::string SemanticContext::Predicate::toString() const {
@@ -96,10 +132,10 @@ std::string SemanticContext::Predicate::toString() const {
//------------------ PrecedencePredicate -------------------------------------------------------------------------------
-SemanticContext::PrecedencePredicate::PrecedencePredicate() : precedence(0) {
-}
+SemanticContext::PrecedencePredicate::PrecedencePredicate(int precedence) : precedence(precedence) {}
-SemanticContext::PrecedencePredicate::PrecedencePredicate(int precedence) : precedence(precedence) {
+SemanticContextType SemanticContext::PrecedencePredicate::getContextType() const {
+ return SemanticContextType::PRECEDENCE;
}
bool SemanticContext::PrecedencePredicate::eval(Recognizer *parser, RuleContext *parserCallStack) const {
@@ -111,30 +147,25 @@ Ref SemanticContext::PrecedencePredicate::evalPrecedence(
if (parser->precpred(parserCallStack, precedence)) {
return SemanticContext::NONE;
}
- else {
- return nullptr;
- }
-}
-
-int SemanticContext::PrecedencePredicate::compareTo(PrecedencePredicate *o) {
- return precedence - o->precedence;
+ return nullptr;
}
size_t SemanticContext::PrecedencePredicate::hashCode() const {
- size_t hashCode = 1;
- hashCode = 31 * hashCode + static_cast(precedence);
- return hashCode;
+ size_t hashCode = misc::MurmurHash::initialize();
+ hashCode = misc::MurmurHash::update(hashCode, static_cast(getContextType()));
+ hashCode = misc::MurmurHash::update(hashCode, static_cast(precedence));
+ return misc::MurmurHash::finish(hashCode, 2);
}
-bool SemanticContext::PrecedencePredicate::operator == (const SemanticContext &other) const {
- if (this == &other)
+bool SemanticContext::PrecedencePredicate::equals(const SemanticContext &other) const {
+ if (this == &other) {
return true;
-
- const PrecedencePredicate *predicate = dynamic_cast(&other);
- if (predicate == nullptr)
+ }
+ if (getContextType() != other.getContextType()) {
return false;
-
- return precedence == predicate->precedence;
+ }
+ const PrecedencePredicate &predicate = downCast(other);
+ return precedence == predicate.precedence;
}
std::string SemanticContext::PrecedencePredicate::toString() const {
@@ -143,56 +174,64 @@ std::string SemanticContext::PrecedencePredicate::toString() const {
//------------------ AND -----------------------------------------------------------------------------------------------
-SemanticContext::AND::AND(Ref const& a, Ref const& b) {
+SemanticContext::AND::AND(Ref a, Ref b) {
std::unordered_set operands;
Ref precedencePredicate;
- if (is(a)) {
- for (const auto &operand : std::dynamic_pointer_cast(a)->opnds) {
- insertSemanticContext(operand, operands, opnds, precedencePredicate, std::less{});
+ _opnds.reserve(predictOperandCapacity(a, b) + 1);
+
+ if (a->getContextType() == SemanticContextType::AND) {
+ for (const auto &operand : downCast(a.get())->getOperands()) {
+ insertSemanticContext(operand, operands, _opnds, precedencePredicate, std::less{});
}
} else {
- insertSemanticContext(a, operands, opnds, precedencePredicate, std::less{});
+ insertSemanticContext(std::move(a), operands, _opnds, precedencePredicate, std::less{});
}
- if (is(b)) {
- for (const auto &operand : std::dynamic_pointer_cast(b)->opnds) {
- insertSemanticContext(operand, operands, opnds, precedencePredicate, std::less{});
+ if (b->getContextType() == SemanticContextType::AND) {
+ for (const auto &operand : downCast(b.get())->getOperands()) {
+ insertSemanticContext(operand, operands, _opnds, precedencePredicate, std::less{});
}
} else {
- insertSemanticContext(b, operands, opnds, precedencePredicate, std::less{});
+ insertSemanticContext(std::move(b), operands, _opnds, precedencePredicate, std::less{});
}
if (precedencePredicate != nullptr) {
// interested in the transition with the lowest precedence
auto [existing, inserted] = operands.insert(precedencePredicate.get());
if (inserted) {
- opnds.push_back(std::move(precedencePredicate));
+ _opnds.push_back(std::move(precedencePredicate));
}
}
}
const std::vector][>& SemanticContext::AND::getOperands() const {
- return opnds;
+ return _opnds;
}
-bool SemanticContext::AND::operator==(const SemanticContext &other) const {
- if (this == &other)
- return true;
+SemanticContextType SemanticContext::AND::getContextType() const {
+ return SemanticContextType::AND;
+}
- const AND *context = dynamic_cast(&other);
- if (context == nullptr)
+bool SemanticContext::AND::equals(const SemanticContext &other) const {
+ if (this == &other) {
+ return true;
+ }
+ if (getContextType() != other.getContextType()) {
return false;
-
- return Arrays::equals(opnds, context->opnds);
+ }
+ const AND &context = downCast(other);
+ return Arrays::equals(getOperands(), context.getOperands());
}
size_t SemanticContext::AND::hashCode() const {
- return misc::MurmurHash::hashCode(opnds, typeid(AND).hash_code());
+ size_t hash = misc::MurmurHash::initialize();
+ hash = misc::MurmurHash::update(hash, static_cast(getContextType()));
+ return misc::MurmurHash::hashCode(getOperands(), hash);
}
bool SemanticContext::AND::eval(Recognizer *parser, RuleContext *parserCallStack) const {
- for (const auto &opnd : opnds) {
+ for (const auto &opnd : getOperands()) {
if (!opnd->eval(parser, parserCallStack)) {
return false;
}
@@ -203,15 +242,16 @@ bool SemanticContext::AND::eval(Recognizer *parser, RuleContext *parserCallStack
Ref SemanticContext::AND::evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const {
bool differs = false;
std::vector][> operands;
- for (const auto &context : opnds) {
- Ref evaluated = context->evalPrecedence(parser, parserCallStack);
+ for (const auto &context : getOperands()) {
+ auto evaluated = context->evalPrecedence(parser, parserCallStack);
differs |= (evaluated != context);
if (evaluated == nullptr) {
// The AND context is false if any element is false.
return nullptr;
- } else if (evaluated != NONE) {
+ }
+ if (evaluated != NONE) {
// Reduce the result by skipping true elements.
- operands.push_back(evaluated);
+ operands.push_back(std::move(evaluated));
}
}
@@ -224,9 +264,9 @@ Ref SemanticContext::AND::evalPrecedence(Recognizer *pars
return NONE;
}
- Ref result = operands[0];
+ Ref result = std::move(operands[0]);
for (size_t i = 1; i < operands.size(); ++i) {
- result = SemanticContext::And(result, operands[i]);
+ result = SemanticContext::And(std::move(result), std::move(operands[i]));
}
return result;
@@ -234,7 +274,7 @@ Ref SemanticContext::AND::evalPrecedence(Recognizer *pars
std::string SemanticContext::AND::toString() const {
std::string tmp;
- for (const auto &var : opnds) {
+ for (const auto &var : getOperands()) {
tmp += var->toString() + " && ";
}
return tmp;
@@ -242,56 +282,64 @@ std::string SemanticContext::AND::toString() const {
//------------------ OR ------------------------------------------------------------------------------------------------
-SemanticContext::OR::OR(Ref const& a, Ref const& b) {
+SemanticContext::OR::OR(Ref a, Ref b) {
std::unordered_set operands;
Ref precedencePredicate;
- if (is(a)) {
- for (const auto &operand : std::dynamic_pointer_cast(a)->opnds) {
- insertSemanticContext(operand, operands, opnds, precedencePredicate, std::greater{});
+ _opnds.reserve(predictOperandCapacity(a, b) + 1);
+
+ if (a->getContextType() == SemanticContextType::OR) {
+ for (const auto &operand : downCast(a.get())->getOperands()) {
+ insertSemanticContext(operand, operands, _opnds, precedencePredicate, std::greater{});
}
} else {
- insertSemanticContext(a, operands, opnds, precedencePredicate, std::greater{});
+ insertSemanticContext(std::move(a), operands, _opnds, precedencePredicate, std::greater{});
}
- if (is(b)) {
- for (const auto &operand : std::dynamic_pointer_cast(b)->opnds) {
- insertSemanticContext(operand, operands, opnds, precedencePredicate, std::greater{});
+ if (b->getContextType() == SemanticContextType::OR) {
+ for (const auto &operand : downCast(b.get())->getOperands()) {
+ insertSemanticContext(operand, operands, _opnds, precedencePredicate, std::greater{});
}
} else {
- insertSemanticContext(b, operands, opnds, precedencePredicate, std::greater{});
+ insertSemanticContext(std::move(b), operands, _opnds, precedencePredicate, std::greater{});
}
if (precedencePredicate != nullptr) {
// interested in the transition with the highest precedence
auto [existing, inserted] = operands.insert(precedencePredicate.get());
if (inserted) {
- opnds.push_back(std::move(precedencePredicate));
+ _opnds.push_back(std::move(precedencePredicate));
}
}
}
const std::vector][>& SemanticContext::OR::getOperands() const {
- return opnds;
+ return _opnds;
}
-bool SemanticContext::OR::operator==(const SemanticContext &other) const {
- if (this == &other)
- return true;
+SemanticContextType SemanticContext::OR::getContextType() const {
+ return SemanticContextType::OR;
+}
- const OR *context = dynamic_cast(&other);
- if (context == nullptr)
+bool SemanticContext::OR::equals(const SemanticContext &other) const {
+ if (this == &other) {
+ return true;
+ }
+ if (getContextType() != other.getContextType()) {
return false;
-
- return Arrays::equals(opnds, context->opnds);
+ }
+ const OR &context = downCast(other);
+ return Arrays::equals(getOperands(), context.getOperands());
}
size_t SemanticContext::OR::hashCode() const {
- return misc::MurmurHash::hashCode(opnds, typeid(OR).hash_code());
+ size_t hash = misc::MurmurHash::initialize();
+ hash = misc::MurmurHash::update(hash, static_cast(getContextType()));
+ return misc::MurmurHash::hashCode(getOperands(), hash);
}
bool SemanticContext::OR::eval(Recognizer *parser, RuleContext *parserCallStack) const {
- for (const auto &opnd : opnds) {
+ for (const auto &opnd : getOperands()) {
if (opnd->eval(parser, parserCallStack)) {
return true;
}
@@ -302,15 +350,16 @@ bool SemanticContext::OR::eval(Recognizer *parser, RuleContext *parserCallStack)
Ref SemanticContext::OR::evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const {
bool differs = false;
std::vector][> operands;
- for (const auto &context : opnds) {
- Ref evaluated = context->evalPrecedence(parser, parserCallStack);
+ for (const auto &context : getOperands()) {
+ auto evaluated = context->evalPrecedence(parser, parserCallStack);
differs |= (evaluated != context);
if (evaluated == NONE) {
// The OR context is true if any element is true.
return NONE;
- } else if (evaluated != nullptr) {
+ }
+ if (evaluated != nullptr) {
// Reduce the result by skipping false elements.
- operands.push_back(evaluated);
+ operands.push_back(std::move(evaluated));
}
}
@@ -323,9 +372,9 @@ Ref SemanticContext::OR::evalPrecedence(Recognizer *parse
return nullptr;
}
- Ref result = operands[0];
+ Ref result = std::move(operands[0]);
for (size_t i = 1; i < operands.size(); ++i) {
- result = SemanticContext::Or(result, operands[i]);
+ result = SemanticContext::Or(std::move(result), std::move(operands[i]));
}
return result;
@@ -333,7 +382,7 @@ Ref SemanticContext::OR::evalPrecedence(Recognizer *parse
std::string SemanticContext::OR::toString() const {
std::string tmp;
- for(const auto &var : opnds) {
+ for(const auto &var : getOperands()) {
tmp += var->toString() + " || ";
}
return tmp;
@@ -343,15 +392,11 @@ std::string SemanticContext::OR::toString() const {
const Ref SemanticContext::NONE = std::make_shared(INVALID_INDEX, INVALID_INDEX, false);
-bool SemanticContext::operator!=(const SemanticContext &other) const {
- return !(*this == other);
-}
-
Ref SemanticContext::evalPrecedence(Recognizer * /*parser*/, RuleContext * /*parserCallStack*/) const {
return shared_from_this();
}
-Ref SemanticContext::And(Ref const& a, Ref const& b) {
+Ref SemanticContext::And(Ref a, Ref b) {
if (!a || a == NONE) {
return b;
}
@@ -360,15 +405,15 @@ Ref SemanticContext::And(Ref const
return a;
}
- Ref result = std::make_shared(a, b);
- if (result->opnds.size() == 1) {
- return result->opnds[0];
+ Ref result = std::make_shared(std::move(a), std::move(b));
+ if (result->getOperands().size() == 1) {
+ return result->getOperands()[0];
}
return result;
}
-Ref SemanticContext::Or(Ref const& a, Ref const& b) {
+Ref SemanticContext::Or(Ref a, Ref b) {
if (!a) {
return b;
}
@@ -380,9 +425,9 @@ Ref SemanticContext::Or(Ref const&
return NONE;
}
- Ref result = std::make_shared(a, b);
- if (result->opnds.size() == 1) {
- return result->opnds[0];
+ Ref result = std::make_shared(std::move(a), std::move(b));
+ if (result->getOperands().size() == 1) {
+ return result->getOperands()[0];
}
return result;
diff --git a/runtime/Cpp/runtime/src/atn/SemanticContext.h b/runtime/Cpp/runtime/src/atn/SemanticContext.h
index cf39c6c9a6..b7193332f7 100755
--- a/runtime/Cpp/runtime/src/atn/SemanticContext.h
+++ b/runtime/Cpp/runtime/src/atn/SemanticContext.h
@@ -7,6 +7,7 @@
#include "Recognizer.h"
#include "support/CPPUtils.h"
+#include "atn/SemanticContextType.h"
namespace antlr4 {
namespace atn {
@@ -27,10 +28,7 @@ namespace atn {
virtual ~SemanticContext() = default;
- virtual size_t hashCode() const = 0;
- virtual std::string toString() const = 0;
- virtual bool operator==(const SemanticContext &other) const = 0;
- virtual bool operator!=(const SemanticContext &other) const;
+ virtual SemanticContextType getContextType() const = 0;
///
/// For context independent predicates, we evaluate them without a local
@@ -67,10 +65,16 @@ namespace atn {
*/
virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const;
- static Ref And(Ref const& a, Ref const& b);
+ virtual size_t hashCode() const = 0;
+
+ virtual bool equals(const SemanticContext &other) const = 0;
+
+ virtual std::string toString() const = 0;
+
+ static Ref And(Ref a, Ref b);
/// See also: ParserATNSimulator::getPredsForAmbigAlts.
- static Ref Or(Ref const& a, Ref const& b);
+ static Ref Or(Ref a, Ref b);
class Predicate;
class PrecedencePredicate;
@@ -79,40 +83,41 @@ namespace atn {
class OR;
};
- class ANTLR4CPP_PUBLIC SemanticContext::Predicate : public SemanticContext {
+ inline bool operator==(const SemanticContext &lhs, const SemanticContext &rhs) {
+ return lhs.equals(rhs);
+ }
+
+ inline bool operator!=(const SemanticContext &lhs, const SemanticContext &rhs) {
+ return !operator==(lhs, rhs);
+ }
+
+ class ANTLR4CPP_PUBLIC SemanticContext::Predicate final : public SemanticContext {
public:
const size_t ruleIndex;
const size_t predIndex;
const bool isCtxDependent; // e.g., $i ref in pred
- protected:
- Predicate();
-
- public:
Predicate(size_t ruleIndex, size_t predIndex, bool isCtxDependent);
- virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual size_t hashCode() const override;
- virtual bool operator == (const SemanticContext &other) const override;
- virtual std::string toString() const override;
+ SemanticContextType getContextType() const override;
+ bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
+ size_t hashCode() const override;
+ bool equals(const SemanticContext &other) const override;
+ std::string toString() const override;
};
- class ANTLR4CPP_PUBLIC SemanticContext::PrecedencePredicate : public SemanticContext {
+ class ANTLR4CPP_PUBLIC SemanticContext::PrecedencePredicate final : public SemanticContext {
public:
const int precedence;
- protected:
- PrecedencePredicate();
-
- public:
explicit PrecedencePredicate(int precedence);
- virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual int compareTo(PrecedencePredicate *o);
- virtual size_t hashCode() const override;
- virtual bool operator == (const SemanticContext &other) const override;
- virtual std::string toString() const override;
+ SemanticContextType getContextType() const override;
+ bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
+ Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const override;
+ size_t hashCode() const override;
+ bool equals(const SemanticContext &other) const override;
+ std::string toString() const override;
};
/**
@@ -139,61 +144,64 @@ namespace atn {
* A semantic context which is true whenever none of the contained contexts
* is false.
*/
- class ANTLR4CPP_PUBLIC SemanticContext::AND : public SemanticContext::Operator {
+ class ANTLR4CPP_PUBLIC SemanticContext::AND final : public SemanticContext::Operator {
public:
- std::vector][> opnds;
-
- AND(Ref const& a, Ref const& b) ;
+ AND(Ref a, Ref b) ;
- virtual const std::vector][>& getOperands() const override;
- virtual bool operator==(const SemanticContext &other) const override;
- virtual size_t hashCode() const override;
+ const std::vector][>& getOperands() const override;
+ SemanticContextType getContextType() const override;
/**
* The evaluation of predicates by this context is short-circuiting, but
* unordered.]
*/
- virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual std::string toString() const override;
+ bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
+ Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const override;
+ size_t hashCode() const override;
+ bool equals(const SemanticContext &other) const override;
+ std::string toString() const override;
+
+ private:
+ std::vector[> _opnds;
};
/**
* A semantic context which is true whenever at least one of the contained
* contexts is true.
*/
- class ANTLR4CPP_PUBLIC SemanticContext::OR : public SemanticContext::Operator {
+ class ANTLR4CPP_PUBLIC SemanticContext::OR final : public SemanticContext::Operator {
public:
- std::vector][> opnds;
+ OR(Ref a, Ref b);
- OR(Ref const& a, Ref const& b);
-
- virtual const std::vector][>& getOperands() const override;
- virtual bool operator==(const SemanticContext &other) const override;
- virtual size_t hashCode() const override;
+ const std::vector][>& getOperands() const override;
+ SemanticContextType getContextType() const override;
/**
* The evaluation of predicates by this context is short-circuiting, but
* unordered.
*/
- virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const override;
- virtual std::string toString() const override;
+ bool eval(Recognizer *parser, RuleContext *parserCallStack) const override;
+ Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const override;
+ size_t hashCode() const override;
+ bool equals(const SemanticContext &other) const override;
+ std::string toString() const override;
+
+ private:
+ std::vector][> _opnds;
};
-} // namespace atn
-} // namespace antlr4
+} // namespace atn
+} // namespace antlr4
// Hash function for SemanticContext, used in the MurmurHash::update function
namespace std {
- using antlr4::atn::SemanticContext;
- template <> struct hash
- {
- size_t operator () (const SemanticContext &x) const
- {
- return x.hashCode();
+ template <>
+ struct hash<::antlr4::atn::SemanticContext> {
+ size_t operator()(const ::antlr4::atn::SemanticContext &semanticContext) const {
+ return semanticContext.hashCode();
}
};
-}
+
+} // namespace std
diff --git a/runtime/Cpp/runtime/src/atn/SemanticContextType.h b/runtime/Cpp/runtime/src/atn/SemanticContextType.h
new file mode 100644
index 0000000000..bca6e421d2
--- /dev/null
+++ b/runtime/Cpp/runtime/src/atn/SemanticContextType.h
@@ -0,0 +1,23 @@
+/* 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.
+ */
+
+#pragma once
+
+#include
+
+#include "antlr4-common.h"
+
+namespace antlr4 {
+namespace atn {
+
+ enum class SemanticContextType : size_t {
+ PREDICATE = 1,
+ PRECEDENCE = 2,
+ AND = 3,
+ OR = 4,
+ };
+
+} // namespace atn
+} // namespace antlr4
diff --git a/runtime/Cpp/runtime/src/support/Declarations.h b/runtime/Cpp/runtime/src/support/Declarations.h
index 519dbbaa5e..8e960676cf 100644
--- a/runtime/Cpp/runtime/src/support/Declarations.h
+++ b/runtime/Cpp/runtime/src/support/Declarations.h
@@ -69,7 +69,6 @@ namespace antlr4 {
class ATNSimulator;
class ATNState;
enum class ATNType;
- class AbstractPredicateTransition;
class ActionTransition;
class ArrayPredictionContext;
class AtomTransition;
]