/* 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 "Recognizer.h" #include "support/CPPUtils.h" namespace antlr4 { namespace atn { /// A tree structure used to record the semantic context in which /// an ATN configuration is valid. It's either a single predicate, /// a conjunction "p1 && p2", or a sum of products "p1||p2". /// /// I have scoped the AND, OR, and Predicate subclasses of /// SemanticContext within the scope of this outer class. class ANTLR4CPP_PUBLIC SemanticContext : public std::enable_shared_from_this { public: struct Hasher { size_t operator()(Ref const& k) const { return k->hashCode(); } }; struct Comparer { bool operator()(Ref const& lhs, Ref const& rhs) const { if (lhs == rhs) return true; return (lhs->hashCode() == rhs->hashCode()) && (*lhs == *rhs); } }; using Set = std::unordered_set, Hasher, Comparer>; /** * The default {@link SemanticContext}, which is semantically equivalent to * a predicate of the form {@code {true}?}. */ static const Ref NONE; virtual ~SemanticContext(); 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; /// /// For context independent predicates, we evaluate them without a local /// context (i.e., null context). That way, we can evaluate them without /// having to create proper rule-specific context during prediction (as /// opposed to the parser, which creates them naturally). In a practical /// sense, this avoids a cast exception from RuleContext to myruleContext. ///

/// For context dependent predicates, we must pass in a local context so that /// references such as $arg evaluate properly as _localctx.arg. We only /// capture context dependent predicates in the context in which we begin /// prediction, so we passed in the outer context here in case of context /// dependent predicate evaluation. ///

virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) = 0; /** * Evaluate the precedence predicates for the context and reduce the result. * * @param parser The parser instance. * @param parserCallStack * @return The simplified semantic context after precedence predicates are * evaluated, which will be one of the following values. *
    *
  • {@link #NONE}: if the predicate simplifies to {@code true} after * precedence predicates are evaluated.
  • *
  • {@code null}: if the predicate simplifies to {@code false} after * precedence predicates are evaluated.
  • *
  • {@code this}: if the semantic context is not changed as a result of * precedence predicate evaluation.
  • *
  • A non-{@code null} {@link SemanticContext}: the new simplified * semantic context after precedence predicates are evaluated.
  • *
*/ virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack); static Ref And(Ref const& a, Ref const& b); /// See also: ParserATNSimulator::getPredsForAmbigAlts. static Ref Or(Ref const& a, Ref const& b); class Predicate; class PrecedencePredicate; class Operator; class AND; class OR; private: static std::vector> filterPrecedencePredicates(const Set &collection); }; class ANTLR4CPP_PUBLIC SemanticContext::Predicate : 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) override; virtual size_t hashCode() const override; virtual bool operator == (const SemanticContext &other) const override; virtual std::string toString() const override; }; class ANTLR4CPP_PUBLIC SemanticContext::PrecedencePredicate : public SemanticContext { public: const int precedence; protected: PrecedencePredicate(); public: PrecedencePredicate(int precedence); virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) override; virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) 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; }; /** * This is the base class for semantic context "operators", which operate on * a collection of semantic context "operands". * * @since 4.3 */ class ANTLR4CPP_PUBLIC SemanticContext::Operator : public SemanticContext { public: virtual ~Operator() override; /** * Gets the operands for the semantic context operator. * * @return a collection of {@link SemanticContext} operands for the * operator. * * @since 4.3 */ virtual std::vector> getOperands() const = 0; }; /** * A semantic context which is true whenever none of the contained contexts * is false. */ class ANTLR4CPP_PUBLIC SemanticContext::AND : public SemanticContext::Operator { public: std::vector> opnds; AND(Ref const& a, Ref const& b) ; virtual std::vector> getOperands() const override; virtual bool operator == (const SemanticContext &other) const override; virtual size_t hashCode() const override; /** * The evaluation of predicates by this context is short-circuiting, but * unordered.

*/ virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) override; virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) override; virtual std::string toString() const override; }; /** * A semantic context which is true whenever at least one of the contained * contexts is true. */ class ANTLR4CPP_PUBLIC SemanticContext::OR : public SemanticContext::Operator { public: std::vector> opnds; OR(Ref const& a, Ref const& b); virtual std::vector> getOperands() const override; virtual bool operator == (const SemanticContext &other) const override; virtual size_t hashCode() const override; /** * The evaluation of predicates by this context is short-circuiting, but * unordered. */ virtual bool eval(Recognizer *parser, RuleContext *parserCallStack) override; virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) override; virtual std::string toString() const override; }; } // 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 () (SemanticContext &x) const { return x.hashCode(); } }; }