@@ -23,27 +23,10 @@ namespace graphql::peg {
23
23
using namespace tao ::graphqlpeg;
24
24
namespace peginternal = tao::graphqlpeg::internal;
25
25
26
- class [[nodiscard]] ast_node
26
+ class [[nodiscard]] ast_node : public parse_tree::basic_node<ast_node>
27
27
{
28
28
public:
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 ;
47
30
48
31
GRAPHQLPEG_EXPORT void unescaped_view (std::string_view unescaped) noexcept ;
49
32
[[nodiscard]] GRAPHQLPEG_EXPORT std::string_view unescaped_view () const ;
@@ -55,71 +38,31 @@ class [[nodiscard]] ast_node
55
38
56
39
// The pointer comparison doesn't work with shared libraries where the parse tree is
57
40
// 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));
62
46
}
63
47
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>;
70
49
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)
75
52
{
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>();
86
55
_type_hash = type_hash<Rule>();
87
- _source = in.source ();
88
- _content = { _begin.data , static_cast <size_t >(end - _begin.data ) };
89
- _unescaped.reset ();
90
56
}
91
57
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
-
117
58
private:
118
59
template <typename U>
119
60
[[nodiscard]] static std::string_view type_name () noexcept
120
61
{
121
62
// 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.
123
66
static const std::string_view name { tao::graphqlpeg::demangle<U>() };
124
67
125
68
return name;
@@ -130,20 +73,17 @@ class [[nodiscard]] ast_node
130
73
{
131
74
// This is cached in a static local variable per-specialization, but each module may have
132
75
// 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>());
134
77
135
78
return hash;
136
79
}
137
80
138
- std::string_view _source;
139
- peginternal::iterator _begin;
140
- std::string_view _type;
81
+ std::string_view _type_name;
141
82
size_t _type_hash = 0 ;
142
- std::string_view _content;
143
83
144
84
using unescaped_t = std::variant<std::string_view, std::string>;
145
85
146
- std::unique_ptr<unescaped_t > _unescaped;
86
+ mutable std::unique_ptr<unescaped_t > _unescaped;
147
87
};
148
88
149
89
template <class ParseInput >
0 commit comments