diff options
Diffstat (limited to 'MoonParser/ast.hpp')
-rw-r--r-- | MoonParser/ast.hpp | 194 |
1 files changed, 83 insertions, 111 deletions
diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp index 8d28177..b388e77 100644 --- a/MoonParser/ast.hpp +++ b/MoonParser/ast.hpp | |||
@@ -1,5 +1,4 @@ | |||
1 | #ifndef AST_HPP | 1 | #pragma once |
2 | #define AST_HPP | ||
3 | 2 | ||
4 | 3 | ||
5 | #include <cassert> | 4 | #include <cassert> |
@@ -13,14 +12,15 @@ namespace parserlib { | |||
13 | 12 | ||
14 | 13 | ||
15 | class ast_node; | 14 | class ast_node; |
16 | template <class T, bool OPT, bool MEM> class ast_ptr; | 15 | template <bool Required, class T> class ast_ptr; |
17 | template <class T> class ast_list; | 16 | template <bool Required, class T> class ast_list; |
18 | template <class T> class ast; | 17 | template <class T> class ast; |
19 | 18 | ||
20 | 19 | ||
21 | /** type of AST node stack. | 20 | /** type of AST node stack. |
22 | */ | 21 | */ |
23 | typedef std::vector<ast_node*> ast_stack; | 22 | typedef std::vector<ast_node*> ast_stack; |
23 | typedef std::list<ast_node*> node_container; | ||
24 | 24 | ||
25 | extern int ast_type_id; | 25 | extern int ast_type_id; |
26 | 26 | ||
@@ -78,26 +78,22 @@ public: | |||
78 | 78 | ||
79 | virtual bool visitChild(const std::function<bool (ast_node*)>& func); | 79 | virtual bool visitChild(const std::function<bool (ast_node*)>& func); |
80 | 80 | ||
81 | virtual ast_node* getChild(int) const { return nullptr; } | ||
82 | |||
83 | virtual size_t getChildCount() const { return 0; } | ||
84 | |||
85 | virtual ast_node* getFirstChild() const { return nullptr; } | ||
86 | |||
87 | virtual ast_node* getLastChild() const { return nullptr; } | ||
88 | |||
89 | virtual size_t getId() const { return "ast_node"_id; } | 81 | virtual size_t getId() const { return "ast_node"_id; } |
90 | 82 | ||
91 | virtual const char* getName() const { return "ast_node"; } | 83 | virtual const char* getName() const { return "ast_node"; } |
92 | 84 | ||
93 | virtual int get_type() { return ast_type<ast_node>(); } | 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 | } | ||
94 | private: | 94 | private: |
95 | int _ref; | 95 | int _ref; |
96 | ast_node* getByTypeIds(int* begin, int* end); | 96 | ast_node* getByTypeIds(int* begin, int* end); |
97 | template <class T, bool OPT, bool MEM> friend class ast_ptr; | ||
98 | template <class ...Args> friend class ast_choice; | ||
99 | template <class T> friend class ast_list; | ||
100 | template <class T> friend class ast; | ||
101 | }; | 97 | }; |
102 | 98 | ||
103 | template<class T> | 99 | template<class T> |
@@ -132,9 +128,11 @@ typedef std::vector<ast_member*> ast_member_vector; | |||
132 | */ | 128 | */ |
133 | class ast_container : public ast_node { | 129 | class ast_container : public ast_node { |
134 | public: | 130 | public: |
135 | /** sets the container under construction to be this. | 131 | void add_members(std::initializer_list<ast_member*> members) { |
136 | */ | 132 | for (auto member : members) { |
137 | ast_container(); | 133 | m_members.push_back(member); |
134 | } | ||
135 | } | ||
138 | 136 | ||
139 | /** returns the vector of AST members. | 137 | /** returns the vector of AST members. |
140 | @return the vector of AST members. | 138 | @return the vector of AST members. |
@@ -154,14 +152,6 @@ public: | |||
154 | 152 | ||
155 | virtual bool visitChild(const std::function<bool (ast_node*)>& func) override; | 153 | virtual bool visitChild(const std::function<bool (ast_node*)>& func) override; |
156 | 154 | ||
157 | virtual ast_node* getChild(int index) const override; | ||
158 | |||
159 | virtual size_t getChildCount() const override; | ||
160 | |||
161 | virtual ast_node* getFirstChild() const override; | ||
162 | |||
163 | virtual ast_node* getLastChild() const override; | ||
164 | |||
165 | virtual size_t getId() const override { return "ast_container"_id; } | 155 | virtual size_t getId() const override { return "ast_container"_id; } |
166 | 156 | ||
167 | virtual const char* getName() const override { return "ast_container"; } | 157 | virtual const char* getName() const override { return "ast_container"; } |
@@ -176,12 +166,6 @@ private: | |||
176 | */ | 166 | */ |
177 | class ast_member { | 167 | class ast_member { |
178 | public: | 168 | public: |
179 | /** automatically registers itself to the container under construction. | ||
180 | */ | ||
181 | ast_member(bool is_member) { | ||
182 | if (is_member) add_to_owner(); | ||
183 | } | ||
184 | |||
185 | virtual ~ast_member() {} | 169 | virtual ~ast_member() {} |
186 | 170 | ||
187 | /** interface for filling the the member from a node stack. | 171 | /** interface for filling the the member from a node stack. |
@@ -192,9 +176,6 @@ public: | |||
192 | virtual bool accept(ast_node* node) = 0; | 176 | virtual bool accept(ast_node* node) = 0; |
193 | 177 | ||
194 | virtual int get_type() { return ast_type<ast_member>(); } | 178 | virtual int get_type() { return ast_type<ast_member>(); } |
195 | private: | ||
196 | //register the AST member to the current container. | ||
197 | void add_to_owner(); | ||
198 | }; | 179 | }; |
199 | 180 | ||
200 | template<class T> | 181 | template<class T> |
@@ -204,7 +185,7 @@ T* ast_cast(ast_member* member) { | |||
204 | 185 | ||
205 | class _ast_ptr : public ast_member { | 186 | class _ast_ptr : public ast_member { |
206 | public: | 187 | public: |
207 | _ast_ptr(ast_node* node, bool is_member) : ast_member(is_member), m_ptr(node) { | 188 | _ast_ptr(ast_node* node) : m_ptr(node) { |
208 | if (node) node->retain(); | 189 | if (node) node->retain(); |
209 | } | 190 | } |
210 | 191 | ||
@@ -226,13 +207,13 @@ public: | |||
226 | 207 | ||
227 | template <class T> | 208 | template <class T> |
228 | T* to() const { | 209 | T* to() const { |
229 | assert(m_ptr->get_type() == ast_type<T>()); | 210 | assert(m_ptr && m_ptr->get_type() == ast_type<T>()); |
230 | return static_cast<T*>(m_ptr); | 211 | return static_cast<T*>(m_ptr); |
231 | } | 212 | } |
232 | 213 | ||
233 | template <class T> | 214 | template <class T> |
234 | bool is() const { | 215 | bool is() const { |
235 | return m_ptr->get_type() == ast_type<T>(); | 216 | return m_ptr && m_ptr->get_type() == ast_type<T>(); |
236 | } | 217 | } |
237 | 218 | ||
238 | void set(ast_node* node) { | 219 | void set(ast_node* node) { |
@@ -259,16 +240,16 @@ protected: | |||
259 | /** pointer to an AST object. | 240 | /** pointer to an AST object. |
260 | It assumes ownership of the object. | 241 | It assumes ownership of the object. |
261 | It pops an object of the given type from the stack. | 242 | It pops an object of the given type from the stack. |
243 | @tparam Required if true, the object is required. | ||
262 | @tparam T type of object to control. | 244 | @tparam T type of object to control. |
263 | @tparam OPT if true, the object becomes optional. | ||
264 | */ | 245 | */ |
265 | template <class T, bool OPT = false, bool MEM = true> class ast_ptr : public _ast_ptr { | 246 | template <bool Required, class T> class ast_ptr : public _ast_ptr { |
266 | public: | 247 | public: |
267 | ast_ptr(T* node = nullptr) : _ast_ptr(node, MEM) {} | 248 | ast_ptr(T* node = nullptr) : _ast_ptr(node) {} |
268 | 249 | ||
269 | ast_ptr(const ast_ptr<T, OPT, MEM>& other) : _ast_ptr(other.get(), MEM) {} | 250 | ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} |
270 | 251 | ||
271 | ast_ptr<T, OPT, MEM>& operator=(const ast_ptr<T, OPT, MEM>& other) { | 252 | ast_ptr& operator=(const ast_ptr& other) { |
272 | set(other.get()); | 253 | set(other.get()); |
273 | return *this; | 254 | return *this; |
274 | } | 255 | } |
@@ -298,28 +279,22 @@ public: | |||
298 | /** Pops a node from the stack. | 279 | /** Pops a node from the stack. |
299 | @param st stack. | 280 | @param st stack. |
300 | @exception std::logic_error thrown if the node is not of the appropriate type; | 281 | @exception std::logic_error thrown if the node is not of the appropriate type; |
301 | thrown only if OPT == false or if the stack is empty. | 282 | thrown only if Required == true or if the stack is empty. |
302 | */ | 283 | */ |
303 | virtual void construct(ast_stack& st) override { | 284 | virtual void construct(ast_stack& st) override { |
304 | //check the stack node | 285 | // check the stack node |
305 | if (st.empty()) { | 286 | if (st.empty()) { |
306 | if (OPT) return; | 287 | if (!Required) return; |
307 | else throw std::logic_error("invalid AST stack"); | 288 | throw std::logic_error("Invalid AST stack"); |
308 | } | 289 | } |
309 | |||
310 | ast_node* node = st.back(); | 290 | ast_node* node = st.back(); |
311 | |||
312 | if (!ast_ptr::accept(node)) { | 291 | if (!ast_ptr::accept(node)) { |
313 | //if the object is optional, simply return | 292 | // if the object is not required, simply return |
314 | if (OPT) { | 293 | if (!Required) return; |
315 | return; | 294 | // else if the object is mandatory, throw an exception |
316 | } else { //else if the object is mandatory, throw an exception | 295 | throw std::logic_error("Invalid AST node"); |
317 | throw std::logic_error("invalid AST node"); | ||
318 | } | ||
319 | } | 296 | } |
320 | |||
321 | st.pop_back(); | 297 | st.pop_back(); |
322 | |||
323 | m_ptr = node; | 298 | m_ptr = node; |
324 | node->retain(); | 299 | node->retain(); |
325 | } | 300 | } |
@@ -329,18 +304,13 @@ private: | |||
329 | } | 304 | } |
330 | }; | 305 | }; |
331 | 306 | ||
332 | template<class T> | 307 | template <bool Required, class ...Args> class ast_sel : public _ast_ptr { |
333 | inline ast_ptr<T, false, false> new_ptr() { | ||
334 | return ast_ptr<T, false, false>(new T); | ||
335 | } | ||
336 | |||
337 | template <class ...Args> class ast_sel : public _ast_ptr { | ||
338 | public: | 308 | public: |
339 | ast_sel() : _ast_ptr(nullptr, true) {} | 309 | ast_sel() : _ast_ptr(nullptr) {} |
340 | 310 | ||
341 | ast_sel(const ast_sel<Args...>& other) : _ast_ptr(other.get(), true) {} | 311 | ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} |
342 | 312 | ||
343 | ast_sel<Args...>& operator=(const ast_sel<Args...>& other) { | 313 | ast_sel& operator=(const ast_sel& other) { |
344 | set(other.get()); | 314 | set(other.get()); |
345 | return *this; | 315 | return *this; |
346 | } | 316 | } |
@@ -356,15 +326,15 @@ public: | |||
356 | 326 | ||
357 | virtual void construct(ast_stack& st) override { | 327 | virtual void construct(ast_stack& st) override { |
358 | if (st.empty()) { | 328 | if (st.empty()) { |
359 | throw std::logic_error("invalid AST stack"); | 329 | if (!Required) return; |
330 | throw std::logic_error("Invalid AST stack"); | ||
360 | } | 331 | } |
361 | |||
362 | ast_node* node = st.back(); | 332 | ast_node* node = st.back(); |
363 | 333 | if (!ast_sel::accept(node)) { | |
364 | if (!ast_sel::accept(node)) throw std::logic_error("invalid AST node"); | 334 | if (!Required) return; |
365 | 335 | throw std::logic_error("Invalid AST node"); | |
336 | } | ||
366 | st.pop_back(); | 337 | st.pop_back(); |
367 | |||
368 | m_ptr = node; | 338 | m_ptr = node; |
369 | node->retain(); | 339 | node->retain(); |
370 | } | 340 | } |
@@ -380,10 +350,6 @@ private: | |||
380 | 350 | ||
381 | class _ast_list : public ast_member { | 351 | class _ast_list : public ast_member { |
382 | public: | 352 | public: |
383 | typedef std::list<ast_node*> container; | ||
384 | |||
385 | _ast_list() : ast_member(true) {} | ||
386 | |||
387 | ~_ast_list() { | 353 | ~_ast_list() { |
388 | clear(); | 354 | clear(); |
389 | } | 355 | } |
@@ -416,6 +382,12 @@ public: | |||
416 | node->retain(); | 382 | node->retain(); |
417 | } | 383 | } |
418 | 384 | ||
385 | void pop_front() { | ||
386 | auto node = m_objects.front(); | ||
387 | m_objects.pop_front(); | ||
388 | node->release(); | ||
389 | } | ||
390 | |||
419 | void set_front(ast_node* node) { | 391 | void set_front(ast_node* node) { |
420 | assert(node && accept(node)); | 392 | assert(node && accept(node)); |
421 | m_objects.front()->release(); | 393 | m_objects.front()->release(); |
@@ -430,7 +402,7 @@ public: | |||
430 | node->retain(); | 402 | node->retain(); |
431 | } | 403 | } |
432 | 404 | ||
433 | const container& objects() const { | 405 | const node_container& objects() const { |
434 | return m_objects; | 406 | return m_objects; |
435 | } | 407 | } |
436 | 408 | ||
@@ -450,24 +422,24 @@ public: | |||
450 | 422 | ||
451 | virtual int get_type() override { return ast_type<_ast_list>(); } | 423 | virtual int get_type() override { return ast_type<_ast_list>(); } |
452 | protected: | 424 | protected: |
453 | container m_objects; | 425 | node_container m_objects; |
454 | }; | 426 | }; |
455 | 427 | ||
456 | /** A list of objects. | 428 | /** A list of objects. |
457 | It pops objects of the given type from the ast stack, until no more objects can be popped. | 429 | It pops objects of the given type from the ast stack, until no more objects can be popped. |
458 | It assumes ownership of objects. | 430 | It assumes ownership of objects. |
431 | @tparam Required if true, the object is required. | ||
459 | @tparam T type of object to control. | 432 | @tparam T type of object to control. |
460 | */ | 433 | */ |
461 | template <class T> class ast_list : public _ast_list { | 434 | template <bool Required, class T> class ast_list : public _ast_list { |
462 | public: | 435 | public: |
463 | ast_list() {} | 436 | ast_list() { } |
464 | 437 | ||
465 | ast_list(const ast_list<T>& other) { | 438 | ast_list(const ast_list& other) { |
466 | clear(); | ||
467 | dup(other); | 439 | dup(other); |
468 | } | 440 | } |
469 | 441 | ||
470 | ast_list<T>& operator=(const ast_list<T>& other) { | 442 | ast_list& operator=(const ast_list& other) { |
471 | clear(); | 443 | clear(); |
472 | dup(other); | 444 | dup(other); |
473 | return *this; | 445 | return *this; |
@@ -479,17 +451,22 @@ public: | |||
479 | virtual void construct(ast_stack &st) override { | 451 | virtual void construct(ast_stack &st) override { |
480 | while (!st.empty()) { | 452 | while (!st.empty()) { |
481 | ast_node* node = st.back(); | 453 | ast_node* node = st.back(); |
482 | 454 | // if the object was not not of the appropriate type, | |
483 | //if the object was not not of the appropriate type, | 455 | // end the list parsing |
484 | //end the list parsing | 456 | if (!ast_list::accept(node)) { |
485 | if (!ast_list::accept(node)) return; | 457 | if (Required && m_objects.empty()) { |
486 | 458 | throw std::logic_error("Invalid AST node"); | |
459 | } | ||
460 | return; | ||
461 | } | ||
487 | st.pop_back(); | 462 | st.pop_back(); |
488 | 463 | // insert the object in the list, in reverse order | |
489 | //insert the object in the list, in reverse order | ||
490 | m_objects.push_front(node); | 464 | m_objects.push_front(node); |
491 | node->retain(); | 465 | node->retain(); |
492 | } | 466 | } |
467 | if (Required && m_objects.empty()) { | ||
468 | throw std::logic_error("Invalid AST stack"); | ||
469 | } | ||
493 | } | 470 | } |
494 | private: | 471 | private: |
495 | virtual bool accept(ast_node* node) override { | 472 | virtual bool accept(ast_node* node) override { |
@@ -497,38 +474,36 @@ private: | |||
497 | } | 474 | } |
498 | }; | 475 | }; |
499 | 476 | ||
500 | template <class ...Args> class ast_sel_list : public _ast_list { | 477 | template <bool Required, class ...Args> class ast_sel_list : public _ast_list { |
501 | public: | 478 | public: |
502 | ast_sel_list() {} | 479 | ast_sel_list() { } |
503 | 480 | ||
504 | ast_sel_list(const ast_sel_list<Args...>& other) { | 481 | ast_sel_list(const ast_sel_list& other) { |
505 | clear(); | ||
506 | dup(other); | 482 | dup(other); |
507 | } | 483 | } |
508 | 484 | ||
509 | ast_sel_list<Args...>& operator=(const ast_sel_list<Args...>& other) { | 485 | ast_sel_list& operator=(const ast_sel_list& other) { |
510 | clear(); | 486 | clear(); |
511 | dup(other); | 487 | dup(other); |
512 | return *this; | 488 | return *this; |
513 | } | 489 | } |
514 | 490 | ||
515 | /** Pops objects of type T from the stack until no more objects can be popped. | ||
516 | @param st stack. | ||
517 | */ | ||
518 | virtual void construct(ast_stack &st) override { | 491 | virtual void construct(ast_stack &st) override { |
519 | while (!st.empty()) { | 492 | while (!st.empty()) { |
520 | ast_node* node = st.back(); | 493 | ast_node* node = st.back(); |
521 | 494 | if (!ast_sel_list::accept(node)) { | |
522 | //if the object was not not of the appropriate type, | 495 | if (Required && m_objects.empty()) { |
523 | //end the list parsing | 496 | throw std::logic_error("Invalid AST node"); |
524 | if (!ast_sel_list<Args...>::accept(node)) return; | 497 | } |
525 | 498 | return; | |
499 | } | ||
526 | st.pop_back(); | 500 | st.pop_back(); |
527 | |||
528 | //insert the object in the list, in reverse order | ||
529 | m_objects.push_front(node); | 501 | m_objects.push_front(node); |
530 | node->retain(); | 502 | node->retain(); |
531 | } | 503 | } |
504 | if (Required && m_objects.empty()) { | ||
505 | throw std::logic_error("Invalid AST stack"); | ||
506 | } | ||
532 | } | 507 | } |
533 | private: | 508 | private: |
534 | virtual bool accept(ast_node* node) override { | 509 | virtual bool accept(ast_node* node) override { |
@@ -583,10 +558,10 @@ ast_node* _parse(input &i, rule &g, error_list &el, void* ud); | |||
583 | @param ud user data, passed to the parse procedures. | 558 | @param ud user data, passed to the parse procedures. |
584 | @return ast nodes. | 559 | @return ast nodes. |
585 | */ | 560 | */ |
586 | template <class T> ast_ptr<T, false, false> parse(input &i, rule &g, error_list &el, void* ud = nullptr) { | 561 | template <class T> ast_ptr<false, T> parse(input &i, rule &g, error_list &el, void* ud = nullptr) { |
587 | ast_node* node = _parse(i, g, el, ud); | 562 | ast_node* node = _parse(i, g, el, ud); |
588 | T* ast = ast_cast<T>(node); | 563 | T* ast = ast_cast<T>(node); |
589 | ast_ptr<T, false, false> ptr; | 564 | ast_ptr<false, T> ptr; |
590 | if (ast) { | 565 | if (ast) { |
591 | ast_stack st{node}; | 566 | ast_stack st{node}; |
592 | ptr.construct(st); | 567 | ptr.construct(st); |
@@ -598,6 +573,3 @@ template <class T> ast_ptr<T, false, false> parse(input &i, rule &g, error_list | |||
598 | 573 | ||
599 | 574 | ||
600 | } //namespace parserlib | 575 | } //namespace parserlib |
601 | |||
602 | |||
603 | #endif //AST_HPP | ||