/* 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" #include "atn/SemanticContext.h" namespace antlr4 { namespace atn { /// /// A tuple: (ATN state, predicted alt, syntactic, semantic context). /// The syntactic context is a graph-structured stack node whose /// path(s) to the root is the rule invocation(s) /// chain used to arrive at the state. The semantic context is /// the tree of semantic predicates encountered before reaching /// an ATN state. /// class ANTLR4CPP_PUBLIC ATNConfig { public: struct Hasher { size_t operator()(Ref const& k) const { return k->hashCode(); } size_t operator()(ATNConfig const& k) const { return k.hashCode(); } }; struct Comparer { bool operator()(Ref const& lhs, Ref const& rhs) const { return (lhs == rhs) || (*lhs == *rhs); } bool operator()(ATNConfig const& lhs, ATNConfig const& rhs) const { return (&lhs == &rhs) || (lhs == rhs); } }; using Set = std::unordered_set, Hasher, Comparer>; /// The ATN state associated with this configuration. ATNState *state = nullptr; /// What alt (or lexer rule) is predicted by this configuration. const size_t alt = 0; /// The stack of invoking states leading to the rule/states associated /// with this config. We track only those contexts pushed during /// execution of the ATN simulator. /// /// Can be shared between multiple ANTConfig instances. Ref context; /** * We cannot execute predicates dependent upon local context unless * we know for sure we are in the correct context. Because there is * no way to do this efficiently, we simply cannot evaluate * dependent predicates unless we are in the rule that initially * invokes the ATN simulator. * *

* closure() tracks the depth of how far we dip into the outer context: * depth > 0. Note that it may not be totally accurate depth since I * don't ever decrement. TODO: make it a boolean then

* *

* For memory efficiency, the {@link #isPrecedenceFilterSuppressed} method * is also backed by this field. Since the field is publicly accessible, the * highest bit which would not cause the value to become negative is used to * store this field. This choice minimizes the risk that code which only * compares this value to 0 would be affected by the new purpose of the * flag. It also ensures the performance of the existing {@link ATNConfig} * constructors as well as certain operations like * {@link ATNConfigSet#add(ATNConfig, DoubleKeyMap)} method are * completely unaffected by the change.

*/ size_t reachesIntoOuterContext = 0; /// Can be shared between multiple ATNConfig instances. Ref semanticContext; ATNConfig(ATNState *state, size_t alt, Ref context); ATNConfig(ATNState *state, size_t alt, Ref context, Ref semanticContext); ATNConfig(ATNConfig const& other, Ref semanticContext); ATNConfig(ATNConfig const& other, ATNState *state); ATNConfig(ATNConfig const& other, ATNState *state, Ref semanticContext); ATNConfig(ATNConfig const& other, ATNState *state, Ref context); ATNConfig(ATNConfig const& other, ATNState *state, Ref context, Ref semanticContext); ATNConfig(ATNConfig const&) = default; ATNConfig(ATNConfig&&) = default; virtual ~ATNConfig() = default; virtual size_t hashCode() const; /** * This method gets the value of the {@link #reachesIntoOuterContext} field * as it existed prior to the introduction of the * {@link #isPrecedenceFilterSuppressed} method. */ size_t getOuterContextDepth() const; bool isPrecedenceFilterSuppressed() const; void setPrecedenceFilterSuppressed(bool value); /// An ATN configuration is equal to another if both have /// the same state, they predict the same alternative, and /// syntactic/semantic contexts are the same. bool operator==(const ATNConfig &other) const; bool operator!=(const ATNConfig &other) const; virtual std::string toString() const; std::string toString(bool showAlt) const; private: ATNConfig(ATNState *state, size_t alt, Ref context, size_t reachesIntoOuterContext, Ref semanticContext); }; } // namespace atn } // namespace antlr4 // Hash function for ATNConfig. namespace std { using antlr4::atn::ATNConfig; template <> struct hash { size_t operator() (const ATNConfig &x) const { return x.hashCode(); } }; template <> struct hash>> { size_t operator() (const std::vector> &vector) const { std::size_t seed = 0; for (const auto &config : vector) { seed ^= config->hashCode() + 0x9e3779b9 + (seed << 6) + (seed >> 2); } return seed; } }; }