1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2 * Use of this file is governed by the BSD 3-clause license that
3 * can be found in the LICENSE.txt file in the project root.
6 #include "misc/MurmurHash.h"
7 #include "support/CPPUtils.h"
8 #include "support/Arrays.h"
10 #include "SemanticContext.h"
12 using namespace antlr4;
13 using namespace antlr4::atn;
14 using namespace antlrcpp;
16 //------------------ Predicate -----------------------------------------------------------------------------------------
18 SemanticContext::Predicate::Predicate() : Predicate(INVALID_INDEX, INVALID_INDEX, false) {
21 SemanticContext::Predicate::Predicate(size_t ruleIndex, size_t predIndex, bool isCtxDependent)
22 : ruleIndex(ruleIndex), predIndex(predIndex), isCtxDependent(isCtxDependent) {
26 bool SemanticContext::Predicate::eval(Recognizer *parser, RuleContext *parserCallStack) {
27 RuleContext *localctx = nullptr;
29 localctx = parserCallStack;
30 return parser->sempred(localctx, ruleIndex, predIndex);
33 size_t SemanticContext::Predicate::hashCode() const {
34 size_t hashCode = misc::MurmurHash::initialize();
35 hashCode = misc::MurmurHash::update(hashCode, ruleIndex);
36 hashCode = misc::MurmurHash::update(hashCode, predIndex);
37 hashCode = misc::MurmurHash::update(hashCode, isCtxDependent ? 1 : 0);
38 hashCode = misc::MurmurHash::finish(hashCode, 3);
42 bool SemanticContext::Predicate::operator == (const SemanticContext &other) const {
46 const Predicate *p = dynamic_cast<const Predicate*>(&other);
50 return ruleIndex == p->ruleIndex && predIndex == p->predIndex && isCtxDependent == p->isCtxDependent;
53 std::string SemanticContext::Predicate::toString() const {
54 return std::string("{") + std::to_string(ruleIndex) + std::string(":") + std::to_string(predIndex) + std::string("}?");
57 //------------------ PrecedencePredicate -------------------------------------------------------------------------------
59 SemanticContext::PrecedencePredicate::PrecedencePredicate() : precedence(0) {
62 SemanticContext::PrecedencePredicate::PrecedencePredicate(int precedence) : precedence(precedence) {
65 bool SemanticContext::PrecedencePredicate::eval(Recognizer *parser, RuleContext *parserCallStack) {
66 return parser->precpred(parserCallStack, precedence);
69 Ref<SemanticContext> SemanticContext::PrecedencePredicate::evalPrecedence(Recognizer *parser,
70 RuleContext *parserCallStack) {
71 if (parser->precpred(parserCallStack, precedence)) {
72 return SemanticContext::NONE;
79 int SemanticContext::PrecedencePredicate::compareTo(PrecedencePredicate *o) {
80 return precedence - o->precedence;
83 size_t SemanticContext::PrecedencePredicate::hashCode() const {
85 hashCode = 31 * hashCode + static_cast<size_t>(precedence);
89 bool SemanticContext::PrecedencePredicate::operator == (const SemanticContext &other) const {
93 const PrecedencePredicate *predicate = dynamic_cast<const PrecedencePredicate *>(&other);
94 if (predicate == nullptr)
97 return precedence == predicate->precedence;
100 std::string SemanticContext::PrecedencePredicate::toString() const {
101 return "{" + std::to_string(precedence) + ">=prec}?";
104 //------------------ AND -----------------------------------------------------------------------------------------------
106 SemanticContext::AND::AND(Ref<SemanticContext> const& a, Ref<SemanticContext> const& b) {
110 for (auto operand : std::dynamic_pointer_cast<AND>(a)->opnds) {
111 operands.insert(operand);
118 for (auto operand : std::dynamic_pointer_cast<AND>(b)->opnds) {
119 operands.insert(operand);
125 std::vector<Ref<PrecedencePredicate>> precedencePredicates = filterPrecedencePredicates(operands);
127 if (!precedencePredicates.empty()) {
128 // interested in the transition with the lowest precedence
129 auto predicate = [](Ref<PrecedencePredicate> const& a, Ref<PrecedencePredicate> const& b) {
130 return a->precedence < b->precedence;
133 auto reduced = std::min_element(precedencePredicates.begin(), precedencePredicates.end(), predicate);
134 operands.insert(*reduced);
137 std::copy(operands.begin(), operands.end(), std::back_inserter(opnds));
140 std::vector<Ref<SemanticContext>> SemanticContext::AND::getOperands() const {
144 bool SemanticContext::AND::operator == (const SemanticContext &other) const {
148 const AND *context = dynamic_cast<const AND *>(&other);
149 if (context == nullptr)
152 return Arrays::equals(opnds, context->opnds);
155 size_t SemanticContext::AND::hashCode() const {
156 return misc::MurmurHash::hashCode(opnds, typeid(AND).hash_code());
159 bool SemanticContext::AND::eval(Recognizer *parser, RuleContext *parserCallStack) {
160 for (auto opnd : opnds) {
161 if (!opnd->eval(parser, parserCallStack)) {
168 Ref<SemanticContext> SemanticContext::AND::evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) {
169 bool differs = false;
170 std::vector<Ref<SemanticContext>> operands;
171 for (auto context : opnds) {
172 Ref<SemanticContext> evaluated = context->evalPrecedence(parser, parserCallStack);
173 differs |= (evaluated != context);
174 if (evaluated == nullptr) {
175 // The AND context is false if any element is false.
177 } else if (evaluated != NONE) {
178 // Reduce the result by skipping true elements.
179 operands.push_back(evaluated);
184 return shared_from_this();
187 if (operands.empty()) {
188 // All elements were true, so the AND context is true.
192 Ref<SemanticContext> result = operands[0];
193 for (size_t i = 1; i < operands.size(); ++i) {
194 result = SemanticContext::And(result, operands[i]);
200 std::string SemanticContext::AND::toString() const {
202 for (auto var : opnds) {
203 tmp += var->toString() + " && ";
208 //------------------ OR ------------------------------------------------------------------------------------------------
210 SemanticContext::OR::OR(Ref<SemanticContext> const& a, Ref<SemanticContext> const& b) {
214 for (auto operand : std::dynamic_pointer_cast<OR>(a)->opnds) {
215 operands.insert(operand);
222 for (auto operand : std::dynamic_pointer_cast<OR>(b)->opnds) {
223 operands.insert(operand);
229 std::vector<Ref<PrecedencePredicate>> precedencePredicates = filterPrecedencePredicates(operands);
230 if (!precedencePredicates.empty()) {
231 // interested in the transition with the highest precedence
232 auto predicate = [](Ref<PrecedencePredicate> const& a, Ref<PrecedencePredicate> const& b) {
233 return a->precedence < b->precedence;
235 auto reduced = std::max_element(precedencePredicates.begin(), precedencePredicates.end(), predicate);
236 operands.insert(*reduced);
239 std::copy(operands.begin(), operands.end(), std::back_inserter(opnds));
242 std::vector<Ref<SemanticContext>> SemanticContext::OR::getOperands() const {
246 bool SemanticContext::OR::operator == (const SemanticContext &other) const {
250 const OR *context = dynamic_cast<const OR *>(&other);
251 if (context == nullptr)
254 return Arrays::equals(opnds, context->opnds);
257 size_t SemanticContext::OR::hashCode() const {
258 return misc::MurmurHash::hashCode(opnds, typeid(OR).hash_code());
261 bool SemanticContext::OR::eval(Recognizer *parser, RuleContext *parserCallStack) {
262 for (auto opnd : opnds) {
263 if (opnd->eval(parser, parserCallStack)) {
270 Ref<SemanticContext> SemanticContext::OR::evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) {
271 bool differs = false;
272 std::vector<Ref<SemanticContext>> operands;
273 for (auto context : opnds) {
274 Ref<SemanticContext> evaluated = context->evalPrecedence(parser, parserCallStack);
275 differs |= (evaluated != context);
276 if (evaluated == NONE) {
277 // The OR context is true if any element is true.
279 } else if (evaluated != nullptr) {
280 // Reduce the result by skipping false elements.
281 operands.push_back(evaluated);
286 return shared_from_this();
289 if (operands.empty()) {
290 // All elements were false, so the OR context is false.
294 Ref<SemanticContext> result = operands[0];
295 for (size_t i = 1; i < operands.size(); ++i) {
296 result = SemanticContext::Or(result, operands[i]);
302 std::string SemanticContext::OR::toString() const {
304 for(auto var : opnds) {
305 tmp += var->toString() + " || ";
310 //------------------ SemanticContext -----------------------------------------------------------------------------------
312 const Ref<SemanticContext> SemanticContext::NONE = std::make_shared<Predicate>(INVALID_INDEX, INVALID_INDEX, false);
314 SemanticContext::~SemanticContext() {
317 bool SemanticContext::operator != (const SemanticContext &other) const {
318 return !(*this == other);
321 Ref<SemanticContext> SemanticContext::evalPrecedence(Recognizer * /*parser*/, RuleContext * /*parserCallStack*/) {
322 return shared_from_this();
325 Ref<SemanticContext> SemanticContext::And(Ref<SemanticContext> const& a, Ref<SemanticContext> const& b) {
326 if (!a || a == NONE) {
330 if (!b || b == NONE) {
334 Ref<AND> result = std::make_shared<AND>(a, b);
335 if (result->opnds.size() == 1) {
336 return result->opnds[0];
342 Ref<SemanticContext> SemanticContext::Or(Ref<SemanticContext> const& a, Ref<SemanticContext> const& b) {
350 if (a == NONE || b == NONE) {
354 Ref<OR> result = std::make_shared<OR>(a, b);
355 if (result->opnds.size() == 1) {
356 return result->opnds[0];
362 std::vector<Ref<SemanticContext::PrecedencePredicate>> SemanticContext::filterPrecedencePredicates(const Set &collection) {
363 std::vector<Ref<SemanticContext::PrecedencePredicate>> result;
364 for (auto context : collection) {
365 if (antlrcpp::is<PrecedencePredicate>(context)) {
366 result.push_back(std::dynamic_pointer_cast<PrecedencePredicate>(context));
374 //------------------ Operator -----------------------------------------------------------------------------------------
376 SemanticContext::Operator::~Operator() {