1111#define TAO_PEGTL_NAMESPACE tao::graphqlpeg
1212
1313#include < tao/pegtl.hpp>
14+ #include < tao/pegtl/contrib/parse_tree.hpp>
1415
1516#include < string>
1617#include < string_view>
@@ -22,27 +23,9 @@ namespace graphql::peg {
2223using namespace tao ::graphqlpeg;
2324namespace peginternal = tao::graphqlpeg::internal;
2425
25- class [[nodiscard]] ast_node
26+ class [[nodiscard]] ast_node : public parse_tree::basic_node<ast_node>
2627{
2728public:
28- // Must be default constructible
29- ast_node () = default ;
30-
31- // Nodes are always owned/handled by a std::unique_ptr
32- // and never copied or assigned...
33- ast_node (const ast_node&) = delete ;
34- ast_node (ast_node&&) = delete ;
35- ast_node& operator =(const ast_node&) = delete ;
36- ast_node& operator =(ast_node&&) = delete ;
37-
38- // Must be destructible
39- ~ast_node () = default ;
40-
41- [[nodiscard]] GRAPHQLPEG_EXPORT bool is_root () const noexcept ;
42- [[nodiscard]] GRAPHQLPEG_EXPORT position begin () const noexcept ;
43- [[nodiscard]] GRAPHQLPEG_EXPORT std::string_view string_view () const noexcept ;
44- [[nodiscard]] GRAPHQLPEG_EXPORT std::string string () const noexcept ;
45- [[nodiscard]] GRAPHQLPEG_EXPORT bool has_content () const noexcept ;
4629 GRAPHQLPEG_EXPORT void remove_content () noexcept ;
4730
4831 GRAPHQLPEG_EXPORT void unescaped_view (std::string_view unescaped) noexcept ;
@@ -55,31 +38,21 @@ 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- // All non-root nodes receive a call to start() when
65- // a match is attempted for Rule in a parsing run...
66- template <typename ParseInput>
67- void start (const ParseInput& in)
68- {
69- _begin = in.iterator ();
70- }
48+ using basic_node_t = parse_tree::basic_node<ast_node>;
7149
72- // ...and later a call to success() when the match succeeded...
7350 template <typename Rule, typename ParseInput>
7451 void success (const ParseInput& in)
7552 {
76- const char * end = in.iterator ().data ;
77-
78- _type = type_name<Rule>();
53+ basic_node_t ::template success<Rule>(in);
54+ _type_name = type_name<Rule>();
7955 _type_hash = type_hash<Rule>();
80- _source = in.source ();
81- _content = { _begin.data , static_cast <size_t >(end - _begin.data ) };
82- _unescaped.reset ();
8356 }
8457
8558 using children_t = std::vector<std::unique_ptr<ast_node>>;
@@ -91,7 +64,9 @@ class [[nodiscard]] ast_node
9164 [[nodiscard]] static std::string_view type_name () noexcept
9265 {
9366 // This is cached in a static local variable per-specialization, but each module may have
94- // its own instance of the specialization and the local variable.
67+ // its own instance of the specialization and the local variable. Within a single module,
68+ // the pointer returned from std::string_view::data() should always be equal, which speeds
69+ // up the string comparison in is_type.
9570 static const std::string_view name { tao::graphqlpeg::demangle<U>() };
9671
9772 return name;
@@ -102,20 +77,17 @@ class [[nodiscard]] ast_node
10277 {
10378 // This is cached in a static local variable per-specialization, but each module may have
10479 // its own instance of the specialization and the local variable.
105- static const size_t hash = std::hash<std::string_view>() (type_name<U>());
80+ static const size_t hash = std::hash<std::string_view> {} (type_name<U>());
10681
10782 return hash;
10883 }
10984
110- std::string_view _source;
111- peginternal::iterator _begin;
112- std::string_view _type;
85+ std::string_view _type_name;
11386 size_t _type_hash = 0 ;
114- std::string_view _content;
11587
11688 using unescaped_t = std::variant<std::string_view, std::string>;
11789
118- std::unique_ptr<unescaped_t > _unescaped;
90+ mutable std::unique_ptr<unescaped_t > _unescaped;
11991};
12092
12193template <class ParseInput >
0 commit comments