/* 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" #include "atn/SemanticContextType.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: virtual ~SemanticContext() = default; SemanticContextType getContextType() const { return _contextType; } /// /// 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) const = 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. * */ virtual Ref evalPrecedence(Recognizer *parser, RuleContext *parserCallStack) const; 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 a, Ref b); class Empty; class Predicate; class PrecedencePredicate; class Operator; class AND; class OR; protected: explicit SemanticContext(SemanticContextType contextType) : _contextType(contextType) {} private: const SemanticContextType _contextType; }; 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::Empty : public SemanticContext{ public: /** * The default {@link SemanticContext}, which is semantically equivalent to * a predicate of the form {@code {true}?}. */ static const Ref Instance; }; 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 Predicate(size_t ruleIndex, size_t predIndex, bool isCtxDependent); 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 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); 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; }; /** * 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: 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. * * @return a collection of {@link SemanticContext} operands for the * operator. * * @since 4.3 */ virtual const std::vector>& getOperands() const = 0; protected: using SemanticContext::SemanticContext; }; /** * A semantic context which is true whenever none of the contained contexts * is false. */ 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; /** * The evaluation of predicates by this context is short-circuiting, but * unordered.

*/ 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 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; /** * The evaluation of predicates by this context is short-circuiting, but * unordered. */ 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 std { template <> struct hash<::antlr4::atn::SemanticContext> { size_t operator()(const ::antlr4::atn::SemanticContext &semanticContext) const { return semanticContext.hashCode(); } }; } // namespace std