X-Git-Url: https://gitweb.ps.run/toc/blobdiff_plain/9f94b672a5dc32da5ad01742bd4e976315a30d9c..c6ad2948bb98d42f8e0883ef82cd14cd2d5eda60:/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/SemanticContext.h diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/SemanticContext.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/SemanticContext.h new file mode 100644 index 0000000..7ccc16c --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/atn/SemanticContext.h @@ -0,0 +1,222 @@ +/* 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(); + } + }; +}