aboutsummaryrefslogtreecommitdiff
path: root/MoonParser/ast.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'MoonParser/ast.hpp')
-rw-r--r--MoonParser/ast.hpp575
1 files changed, 0 insertions, 575 deletions
diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp
deleted file mode 100644
index b388e77..0000000
--- a/MoonParser/ast.hpp
+++ /dev/null
@@ -1,575 +0,0 @@
1#pragma once
2
3
4#include <cassert>
5#include <list>
6#include <stdexcept>
7#include <type_traits>
8#include "parser.hpp"
9
10
11namespace parserlib {
12
13
14class ast_node;
15template <bool Required, class T> class ast_ptr;
16template <bool Required, class T> class ast_list;
17template <class T> class ast;
18
19
20/** type of AST node stack.
21 */
22typedef std::vector<ast_node*> ast_stack;
23typedef std::list<ast_node*> node_container;
24
25extern int ast_type_id;
26
27template<class T>
28int ast_type() {
29 static int type = ast_type_id++;
30 return type;
31}
32
33enum class traversal {
34 Continue,
35 Return,
36 Stop
37};
38
39/** Base class for AST nodes.
40 */
41class ast_node : public input_range {
42public:
43 ast_node() : _ref(0) {}
44
45 void retain() {
46 ++_ref;
47 }
48
49 void release() {
50 --_ref;
51 if (_ref == 0) {
52 delete this;
53 }
54 }
55
56 /** interface for filling the contents of the node
57 from a node stack.
58 @param st stack.
59 */
60 virtual void construct(ast_stack& st) {}
61
62 /** interface for visiting AST tree use.
63 */
64 virtual traversal traverse(const std::function<traversal (ast_node*)>& func);
65
66 template <typename... Ts>
67 struct select_last {
68 using type = typename decltype((std::enable_if<true,Ts>{}, ...))::type;
69 };
70 template <typename... Ts>
71 using select_last_t = typename select_last<Ts...>::type;
72
73 template <class ...Args>
74 select_last_t<Args...>* getByPath() {
75 int types[] = {ast_type<Args>()...};
76 return static_cast<select_last_t<Args...>*>(getByTypeIds(std::begin(types), std::end(types)));
77 }
78
79 virtual bool visitChild(const std::function<bool (ast_node*)>& func);
80
81 virtual size_t getId() const { return "ast_node"_id; }
82
83 virtual const char* getName() const { return "ast_node"; }
84
85 virtual int get_type() { return ast_type<ast_node>(); }
86
87 template<class T>
88 inline ast_ptr<false, T> new_ptr() {
89 auto item = new T;
90 item->m_begin.m_line = m_begin.m_line;
91 item->m_end.m_line = m_begin.m_line;
92 return ast_ptr<false, T>(item);
93 }
94private:
95 int _ref;
96 ast_node* getByTypeIds(int* begin, int* end);
97};
98
99template<class T>
100T* ast_cast(ast_node* node) {
101 return node && ast_type<T>() == node->get_type() ? static_cast<T*>(node) : nullptr;
102}
103
104template<class T>
105T* ast_to(ast_node* node) {
106 assert(node->get_type() == ast_type<T>());
107 return static_cast<T*>(node);
108}
109
110template <class ...Args>
111bool ast_is(ast_node* node) {
112 if (!node) return false;
113 bool result = false;
114 int type = node->get_type();
115 using swallow = bool[];
116 (void)swallow{result || (result = ast_type<Args>() == type)...};
117 return result;
118}
119
120class ast_member;
121
122/** type of ast member vector.
123 */
124typedef std::vector<ast_member*> ast_member_vector;
125
126
127/** base class for AST nodes with children.
128 */
129class ast_container : public ast_node {
130public:
131 void add_members(std::initializer_list<ast_member*> members) {
132 for (auto member : members) {
133 m_members.push_back(member);
134 }
135 }
136
137 /** returns the vector of AST members.
138 @return the vector of AST members.
139 */
140 const ast_member_vector& members() const {
141 return m_members;
142 }
143
144 /** Asks all members to construct themselves from the stack.
145 The members are asked to construct themselves in reverse order.
146 from a node stack.
147 @param st stack.
148 */
149 virtual void construct(ast_stack& st) override;
150
151 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override;
152
153 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override;
154
155 virtual size_t getId() const override { return "ast_container"_id; }
156
157 virtual const char* getName() const override { return "ast_container"; }
158private:
159 ast_member_vector m_members;
160
161 friend class ast_member;
162};
163
164
165/** Base class for children of ast_container.
166 */
167class ast_member {
168public:
169 virtual ~ast_member() {}
170
171 /** interface for filling the the member from a node stack.
172 @param st stack.
173 */
174 virtual void construct(ast_stack& st) = 0;
175
176 virtual bool accept(ast_node* node) = 0;
177
178 virtual int get_type() { return ast_type<ast_member>(); }
179};
180
181template<class T>
182T* ast_cast(ast_member* member) {
183 return member && ast_type<T>() == member->get_type() ? static_cast<T*>(member) : nullptr;
184}
185
186class _ast_ptr : public ast_member {
187public:
188 _ast_ptr(ast_node* node) : m_ptr(node) {
189 if (node) node->retain();
190 }
191
192 virtual ~_ast_ptr() {
193 if (m_ptr) {
194 m_ptr->release();
195 m_ptr = nullptr;
196 }
197 }
198
199 ast_node* get() const {
200 return m_ptr;
201 }
202
203 template <class T>
204 T* as() const {
205 return ast_cast<T>(m_ptr);
206 }
207
208 template <class T>
209 T* to() const {
210 assert(m_ptr && m_ptr->get_type() == ast_type<T>());
211 return static_cast<T*>(m_ptr);
212 }
213
214 template <class T>
215 bool is() const {
216 return m_ptr && m_ptr->get_type() == ast_type<T>();
217 }
218
219 void set(ast_node* node) {
220 if (node == m_ptr) {
221 return;
222 } else if (!node) {
223 if (m_ptr) m_ptr->release();
224 m_ptr = nullptr;
225 } else {
226 assert(accept(node));
227 if (m_ptr) m_ptr->release();
228 m_ptr = node;
229 node->retain();
230 }
231 }
232
233 virtual int get_type() override {
234 return ast_type<_ast_ptr>();
235 }
236protected:
237 ast_node* m_ptr;
238};
239
240/** pointer to an AST object.
241 It assumes ownership of the object.
242 It pops an object of the given type from the stack.
243 @tparam Required if true, the object is required.
244 @tparam T type of object to control.
245 */
246template <bool Required, class T> class ast_ptr : public _ast_ptr {
247public:
248 ast_ptr(T* node = nullptr) : _ast_ptr(node) {}
249
250 ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {}
251
252 ast_ptr& operator=(const ast_ptr& other) {
253 set(other.get());
254 return *this;
255 }
256
257 /** gets the underlying ptr value.
258 @return the underlying ptr value.
259 */
260 T* get() const {
261 return static_cast<T*>(m_ptr);
262 }
263
264 /** auto conversion to the underlying object ptr.
265 @return the underlying ptr value.
266 */
267 operator T*() const {
268 return static_cast<T*>(m_ptr);
269 }
270
271 /** member access.
272 @return the underlying ptr value.
273 */
274 T* operator->() const {
275 assert(m_ptr);
276 return static_cast<T*>(m_ptr);
277 }
278
279 /** Pops a node from the stack.
280 @param st stack.
281 @exception std::logic_error thrown if the node is not of the appropriate type;
282 thrown only if Required == true or if the stack is empty.
283 */
284 virtual void construct(ast_stack& st) override {
285 // check the stack node
286 if (st.empty()) {
287 if (!Required) return;
288 throw std::logic_error("Invalid AST stack");
289 }
290 ast_node* node = st.back();
291 if (!ast_ptr::accept(node)) {
292 // if the object is not required, simply return
293 if (!Required) return;
294 // else if the object is mandatory, throw an exception
295 throw std::logic_error("Invalid AST node");
296 }
297 st.pop_back();
298 m_ptr = node;
299 node->retain();
300 }
301private:
302 virtual bool accept(ast_node* node) override {
303 return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type());
304 }
305};
306
307template <bool Required, class ...Args> class ast_sel : public _ast_ptr {
308public:
309 ast_sel() : _ast_ptr(nullptr) {}
310
311 ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {}
312
313 ast_sel& operator=(const ast_sel& other) {
314 set(other.get());
315 return *this;
316 }
317
318 operator ast_node*() const {
319 return m_ptr;
320 }
321
322 ast_node* operator->() const {
323 assert(m_ptr);
324 return m_ptr;
325 }
326
327 virtual void construct(ast_stack& st) override {
328 if (st.empty()) {
329 if (!Required) return;
330 throw std::logic_error("Invalid AST stack");
331 }
332 ast_node* node = st.back();
333 if (!ast_sel::accept(node)) {
334 if (!Required) return;
335 throw std::logic_error("Invalid AST node");
336 }
337 st.pop_back();
338 m_ptr = node;
339 node->retain();
340 }
341private:
342 virtual bool accept(ast_node* node) override {
343 if (!node) return false;
344 using swallow = bool[];
345 bool result = false;
346 (void)swallow{result || (result = ast_type<Args>() == node->get_type())...};
347 return result;
348 }
349};
350
351class _ast_list : public ast_member {
352public:
353 ~_ast_list() {
354 clear();
355 }
356
357 inline ast_node* back() const {
358 return m_objects.back();
359 }
360
361 inline ast_node* front() const {
362 return m_objects.front();
363 }
364
365 inline size_t size() const {
366 return m_objects.size();
367 }
368
369 inline bool empty() const {
370 return m_objects.empty();
371 }
372
373 void push_back(ast_node* node) {
374 assert(node && accept(node));
375 m_objects.push_back(node);
376 node->retain();
377 }
378
379 void push_front(ast_node* node) {
380 assert(node && accept(node));
381 m_objects.push_front(node);
382 node->retain();
383 }
384
385 void pop_front() {
386 auto node = m_objects.front();
387 m_objects.pop_front();
388 node->release();
389 }
390
391 void set_front(ast_node* node) {
392 assert(node && accept(node));
393 m_objects.front()->release();
394 m_objects.front() = node;
395 node->retain();
396 }
397
398 void set_back(ast_node* node) {
399 assert(node && accept(node));
400 m_objects.back()->release();
401 m_objects.back() = node;
402 node->retain();
403 }
404
405 const node_container& objects() const {
406 return m_objects;
407 }
408
409 void clear() {
410 for(ast_node* obj : m_objects) {
411 if (obj) obj->release();
412 }
413 m_objects.clear();
414 }
415
416 void dup(const _ast_list& src) {
417 for(ast_node* obj : src.m_objects) {
418 m_objects.push_back(obj);
419 obj->retain();
420 }
421 }
422
423 virtual int get_type() override { return ast_type<_ast_list>(); }
424protected:
425 node_container m_objects;
426};
427
428/** A list of objects.
429 It pops objects of the given type from the ast stack, until no more objects can be popped.
430 It assumes ownership of objects.
431 @tparam Required if true, the object is required.
432 @tparam T type of object to control.
433 */
434template <bool Required, class T> class ast_list : public _ast_list {
435public:
436 ast_list() { }
437
438 ast_list(const ast_list& other) {
439 dup(other);
440 }
441
442 ast_list& operator=(const ast_list& other) {
443 clear();
444 dup(other);
445 return *this;
446 }
447
448 /** Pops objects of type T from the stack until no more objects can be popped.
449 @param st stack.
450 */
451 virtual void construct(ast_stack &st) override {
452 while (!st.empty()) {
453 ast_node* node = st.back();
454 // if the object was not not of the appropriate type,
455 // end the list parsing
456 if (!ast_list::accept(node)) {
457 if (Required && m_objects.empty()) {
458 throw std::logic_error("Invalid AST node");
459 }
460 return;
461 }
462 st.pop_back();
463 // insert the object in the list, in reverse order
464 m_objects.push_front(node);
465 node->retain();
466 }
467 if (Required && m_objects.empty()) {
468 throw std::logic_error("Invalid AST stack");
469 }
470 }
471private:
472 virtual bool accept(ast_node* node) override {
473 return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type());
474 }
475};
476
477template <bool Required, class ...Args> class ast_sel_list : public _ast_list {
478public:
479 ast_sel_list() { }
480
481 ast_sel_list(const ast_sel_list& other) {
482 dup(other);
483 }
484
485 ast_sel_list& operator=(const ast_sel_list& other) {
486 clear();
487 dup(other);
488 return *this;
489 }
490
491 virtual void construct(ast_stack &st) override {
492 while (!st.empty()) {
493 ast_node* node = st.back();
494 if (!ast_sel_list::accept(node)) {
495 if (Required && m_objects.empty()) {
496 throw std::logic_error("Invalid AST node");
497 }
498 return;
499 }
500 st.pop_back();
501 m_objects.push_front(node);
502 node->retain();
503 }
504 if (Required && m_objects.empty()) {
505 throw std::logic_error("Invalid AST stack");
506 }
507 }
508private:
509 virtual bool accept(ast_node* node) override {
510 if (!node) return false;
511 using swallow = bool[];
512 bool result = false;
513 (void)swallow{result || (result = ast_type<Args>() == node->get_type())...};
514 return result;
515 }
516};
517
518/** AST function which creates an object of type T
519 and pushes it to the node stack.
520 */
521template <class T> class ast {
522public:
523 /** constructor.
524 @param r rule to attach the AST function to.
525 */
526 ast(rule& r) {
527 r.set_parse_proc(&_parse_proc);
528 }
529
530private:
531 //parse proc
532 static void _parse_proc(const pos& b, const pos& e, void* d) {
533 ast_stack* st = reinterpret_cast<ast_stack*>(d);
534 T* obj = new T;
535 obj->m_begin = b;
536 obj->m_end = e;
537 obj->construct(*st);
538 st->push_back(obj);
539 }
540};
541
542
543/** parses the given input.
544 @param i input.
545 @param g root rule of grammar.
546 @param el list of errors.
547 @param ud user data, passed to the parse procedures.
548 @return pointer to ast node created, or null if there was an error.
549 The return object must be deleted by the caller.
550 */
551ast_node* _parse(input &i, rule &g, error_list &el, void* ud);
552
553
554/** parses the given input.
555 @param i input.
556 @param g root rule of grammar.
557 @param el list of errors.
558 @param ud user data, passed to the parse procedures.
559 @return ast nodes.
560 */
561template <class T> ast_ptr<false, T> parse(input &i, rule &g, error_list &el, void* ud = nullptr) {
562 ast_node* node = _parse(i, g, el, ud);
563 T* ast = ast_cast<T>(node);
564 ast_ptr<false, T> ptr;
565 if (ast) {
566 ast_stack st{node};
567 ptr.construct(st);
568 } else if (node) {
569 delete node;
570 }
571 return ptr;
572}
573
574
575} //namespace parserlib