@@ -23,27 +23,10 @@ namespace graphql::peg {
2323using namespace tao ::graphqlpeg;
2424namespace peginternal = tao::graphqlpeg::internal;
2525
26- class [[nodiscard]] ast_node
26+ class [[nodiscard]] ast_node : public parse_tree::basic_node<ast_node>
2727{
2828public:
29- // Must be default constructible
30- ast_node () = default ;
31-
32- // Nodes are always owned/handled by a std::unique_ptr
33- // and never copied or assigned...
34- ast_node (const ast_node&) = delete ;
35- ast_node (ast_node&&) = delete ;
36- ast_node& operator =(const ast_node&) = delete ;
37- ast_node& operator =(ast_node&&) = delete ;
38-
39- // Must be destructible
40- ~ast_node () = default ;
41-
42- [[nodiscard]] GRAPHQLPEG_EXPORT bool is_root () const noexcept ;
43- [[nodiscard]] GRAPHQLPEG_EXPORT position begin () const noexcept ;
44- [[nodiscard]] GRAPHQLPEG_EXPORT std::string_view string_view () const noexcept ;
45- [[nodiscard]] GRAPHQLPEG_EXPORT std::string string () const noexcept ;
46- [[nodiscard]] GRAPHQLPEG_EXPORT bool has_content () const noexcept ;
29+ GRAPHQLPEG_EXPORT void remove_content () noexcept ;
4730
4831 GRAPHQLPEG_EXPORT void unescaped_view (std::string_view unescaped) noexcept ;
4932 [[nodiscard]] GRAPHQLPEG_EXPORT std::string_view unescaped_view () const ;
@@ -55,71 +38,31 @@ class [[nodiscard]] ast_node
5538
5639 // The pointer comparison doesn't work with shared libraries where the parse tree is
5740 // constructed in one module and consumed in another. So to optimize this comparison, check
58- // the size first, then the hash (cached in a static local variable per specialization of
59- // type_hash<U>()), then the pointer comparison with a full string compare as fallback.
60- return _type.size () == u.size () && _type_hash == type_hash<U>()
61- && (_type.data () == u.data () || _type == u);
41+ // the size first, then the pointer (cached in a static local variable per specialization of
42+ // type_name<U>()), then the hash (cached in a static local variable per specialization of
43+ // type_hash<U>()) and a full string compare as fallback.
44+ return _type_name.size () == u.size ()
45+ && (_type_name.data () == u.data () || (_type_hash == type_hash<U>() && _type_name == u));
6246 }
6347
64- template <typename ... States>
65- void remove_content (States&&...) noexcept
66- {
67- _content = {};
68- _unescaped.reset ();
69- }
48+ using basic_node_t = parse_tree::basic_node<ast_node>;
7049
71- // All non-root nodes receive a call to start() when
72- // a match is attempted for Rule in a parsing run...
73- template <typename Rule, typename ParseInput, typename ... States>
74- void start (const ParseInput& in, States&&...)
50+ template <typename Rule, typename ParseInput>
51+ void success (const ParseInput& in)
7552 {
76- _begin = in.iterator ();
77- }
78-
79- // ...and later a call to success() when the match succeeded...
80- template <typename Rule, typename ParseInput, typename ... States>
81- void success (const ParseInput& in, States&&...)
82- {
83- const char * end = in.iterator ().data ;
84-
85- _type = type_name<Rule>();
53+ basic_node_t ::template success<Rule>(in);
54+ _type_name = type_name<Rule>();
8655 _type_hash = type_hash<Rule>();
87- _source = in.source ();
88- _content = { _begin.data , static_cast <size_t >(end - _begin.data ) };
89- _unescaped.reset ();
9056 }
9157
92- // ...or to failure() when a (local) failure was encountered.
93- template <typename Rule, typename ParseInput, typename ... States>
94- void failure (const ParseInput&, States&&...)
95- {
96- }
97-
98- // if parsing of the rule failed with an exception, this method is called
99- template <typename Rule, typename ParseInput, typename ... States>
100- void unwind (const ParseInput&, States&&...) noexcept
101- {
102- }
103-
104- // After a call to success(), and the (optional) call to the selector's
105- // transform() did not discard a node, it is passed to its parent node
106- // with a call to the parent node's emplace_back() member function.
107- template <typename ... States>
108- void emplace_back (std::unique_ptr<ast_node> child, States&&...)
109- {
110- children.emplace_back (std::move (child));
111- }
112-
113- using children_t = std::vector<std::unique_ptr<ast_node>>;
114-
115- children_t children;
116-
11758private:
11859 template <typename U>
11960 [[nodiscard]] static std::string_view type_name () noexcept
12061 {
12162 // This is cached in a static local variable per-specialization, but each module may have
122- // its own instance of the specialization and the local variable.
63+ // its own instance of the specialization and the local variable. Within a single module,
64+ // the pointer returned from std::string_view::data() should always be equal, which speeds
65+ // up the string comparison in is_type.
12366 static const std::string_view name { tao::graphqlpeg::demangle<U>() };
12467
12568 return name;
@@ -130,20 +73,17 @@ class [[nodiscard]] ast_node
13073 {
13174 // This is cached in a static local variable per-specialization, but each module may have
13275 // its own instance of the specialization and the local variable.
133- static const size_t hash = std::hash<std::string_view>() (type_name<U>());
76+ static const size_t hash = std::hash<std::string_view> {} (type_name<U>());
13477
13578 return hash;
13679 }
13780
138- std::string_view _source;
139- peginternal::iterator _begin;
140- std::string_view _type;
81+ std::string_view _type_name;
14182 size_t _type_hash = 0 ;
142- std::string_view _content;
14383
14484 using unescaped_t = std::variant<std::string_view, std::string>;
14585
146- std::unique_ptr<unescaped_t > _unescaped;
86+ mutable std::unique_ptr<unescaped_t > _unescaped;
14787};
14888
14989template <class ParseInput >
0 commit comments