aboutsummaryrefslogtreecommitdiff
path: root/src/yuescript/ast.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuescript/ast.hpp')
-rw-r--r--src/yuescript/ast.hpp138
1 files changed, 81 insertions, 57 deletions
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp
index 4860fc9..681c27f 100644
--- a/src/yuescript/ast.hpp
+++ b/src/yuescript/ast.hpp
@@ -11,40 +11,48 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
11 11
12#pragma once 12#pragma once
13 13
14
15#include <cassert> 14#include <cassert>
16#include <list> 15#include <list>
17#include <stdexcept> 16#include <stdexcept>
18#include <type_traits>
19#include <string_view> 17#include <string_view>
18#include <type_traits>
20 19
21#include "yuescript/parser.hpp" 20#include "yuescript/parser.hpp"
22 21
23
24namespace parserlib { 22namespace parserlib {
25 23
26
27class ast_node; 24class ast_node;
28template <bool Required, class T> class ast_ptr; 25template <bool Required, class T>
29template <bool Required, class T> class ast_list; 26class ast_ptr;
30template <class T> class ast; 27template <bool Required, class T>
31 28class ast_list;
29template <class T>
30class ast;
32 31
33/** type of AST node stack. 32/** type of AST node stack.
34*/ 33 */
35typedef std::vector<ast_node*> ast_stack; 34typedef std::vector<ast_node*> ast_stack;
36typedef std::list<ast_node*> node_container; 35typedef std::list<ast_node*> node_container;
37 36
38 37template <size_t Num>
39template<size_t Num> struct Counter { enum { value = Counter<Num-1>::value }; }; 38struct Counter {
40template<> struct Counter<0> { enum { value = 0 }; }; 39 enum { value = Counter<Num - 1>::value };
40};
41template <>
42struct Counter<0> {
43 enum { value = 0 };
44};
41 45
42#define COUNTER_READ Counter<__LINE__>::value 46#define COUNTER_READ Counter<__LINE__>::value
43#define COUNTER_INC template<> struct Counter<__LINE__> { enum { value = Counter<__LINE__-1>::value + 1}; } 47#define COUNTER_INC \
48 template <> \
49 struct Counter<__LINE__> { \
50 enum { value = Counter<__LINE__ - 1>::value + 1 }; \
51 }
44 52
45class ast_node; 53class ast_node;
46template<class T> 54template <class T>
47constexpr typename std::enable_if<std::is_base_of<ast_node,T>::value,int>::type 55constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type
48id(); 56id();
49 57
50enum class traversal { 58enum class traversal {
@@ -54,10 +62,11 @@ enum class traversal {
54}; 62};
55 63
56/** Base class for AST nodes. 64/** Base class for AST nodes.
57*/ 65 */
58class ast_node : public input_range { 66class ast_node : public input_range {
59public: 67public:
60 ast_node() : _ref(0) {} 68 ast_node()
69 : _ref(0) { }
61 70
62 void retain() { 71 void retain() {
63 ++_ref; 72 ++_ref;
@@ -74,32 +83,32 @@ public:
74 from a node stack. 83 from a node stack.
75 @param st stack. 84 @param st stack.
76 */ 85 */
77 virtual void construct(ast_stack&) {} 86 virtual void construct(ast_stack&) { }
78 87
79 /** interface for visiting AST tree use. 88 /** interface for visiting AST tree use.
80 */ 89 */
81 virtual traversal traverse(const std::function<traversal (ast_node*)>& func); 90 virtual traversal traverse(const std::function<traversal(ast_node*)>& func);
82 91
83 template <typename... Ts> 92 template <typename... Ts>
84 struct select_last { 93 struct select_last {
85 using type = typename decltype((std::enable_if<true,Ts>{}, ...))::type; 94 using type = typename decltype((std::enable_if<true, Ts>{}, ...))::type;
86 }; 95 };
87 template <typename... Ts> 96 template <typename... Ts>
88 using select_last_t = typename select_last<Ts...>::type; 97 using select_last_t = typename select_last<Ts...>::type;
89 98
90 template <class ...Args> 99 template <class... Args>
91 select_last_t<Args...>* getByPath() { 100 select_last_t<Args...>* getByPath() {
92 int types[] = {id<Args>()...}; 101 int types[] = {id<Args>()...};
93 return static_cast<select_last_t<Args...>*>(getByTypeIds(std::begin(types), std::end(types))); 102 return static_cast<select_last_t<Args...>*>(getByTypeIds(std::begin(types), std::end(types)));
94 } 103 }
95 104
96 virtual bool visitChild(const std::function<bool (ast_node*)>& func); 105 virtual bool visitChild(const std::function<bool(ast_node*)>& func);
97 106
98 virtual int getId() const = 0; 107 virtual int getId() const = 0;
99 108
100 virtual const std::string_view getName() const = 0; 109 virtual const std::string_view getName() const = 0;
101 110
102 template<class T> 111 template <class T>
103 inline ast_ptr<false, T> new_ptr() const { 112 inline ast_ptr<false, T> new_ptr() const {
104 auto item = new T; 113 auto item = new T;
105 item->m_begin.m_line = m_begin.m_line; 114 item->m_begin.m_line = m_begin.m_line;
@@ -108,27 +117,28 @@ public:
108 item->m_end.m_col = m_end.m_col; 117 item->m_end.m_col = m_end.m_col;
109 return ast_ptr<false, T>(item); 118 return ast_ptr<false, T>(item);
110 } 119 }
120
111private: 121private:
112 int _ref; 122 int _ref;
113 ast_node* getByTypeIds(int* begin, int* end); 123 ast_node* getByTypeIds(int* begin, int* end);
114}; 124};
115 125
116template<class T> 126template <class T>
117constexpr typename std::enable_if<std::is_base_of<ast_node,T>::value,int>::type 127constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type
118id() { return 0; } 128id() { return 0; }
119 129
120template<class T> 130template <class T>
121T* ast_cast(ast_node* node) { 131T* ast_cast(ast_node* node) {
122 return node && id<T>() == node->getId() ? static_cast<T*>(node) : nullptr; 132 return node && id<T>() == node->getId() ? static_cast<T*>(node) : nullptr;
123} 133}
124 134
125template<class T> 135template <class T>
126T* ast_to(ast_node* node) { 136T* ast_to(ast_node* node) {
127 assert(node->getId() == id<T>()); 137 assert(node->getId() == id<T>());
128 return static_cast<T*>(node); 138 return static_cast<T*>(node);
129} 139}
130 140
131template <class ...Args> 141template <class... Args>
132bool ast_is(ast_node* node) { 142bool ast_is(ast_node* node) {
133 if (!node) return false; 143 if (!node) return false;
134 bool result = false; 144 bool result = false;
@@ -141,12 +151,11 @@ bool ast_is(ast_node* node) {
141class ast_member; 151class ast_member;
142 152
143/** type of ast member vector. 153/** type of ast member vector.
144*/ 154 */
145typedef std::vector<ast_member*> ast_member_vector; 155typedef std::vector<ast_member*> ast_member_vector;
146 156
147
148/** base class for AST nodes with children. 157/** base class for AST nodes with children.
149*/ 158 */
150class ast_container : public ast_node { 159class ast_container : public ast_node {
151public: 160public:
152 void add_members(std::initializer_list<ast_member*> members) { 161 void add_members(std::initializer_list<ast_member*> members) {
@@ -169,9 +178,10 @@ public:
169 */ 178 */
170 virtual void construct(ast_stack& st) override; 179 virtual void construct(ast_stack& st) override;
171 180
172 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override; 181 virtual traversal traverse(const std::function<traversal(ast_node*)>& func) override;
182
183 virtual bool visitChild(const std::function<bool(ast_node*)>& func) override;
173 184
174 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override;
175private: 185private:
176 ast_member_vector m_members; 186 ast_member_vector m_members;
177 187
@@ -184,10 +194,10 @@ enum class ast_holder_type {
184}; 194};
185 195
186/** Base class for children of ast_container. 196/** Base class for children of ast_container.
187*/ 197 */
188class ast_member { 198class ast_member {
189public: 199public:
190 virtual ~ast_member() {} 200 virtual ~ast_member() { }
191 201
192 /** interface for filling the the member from a node stack. 202 /** interface for filling the the member from a node stack.
193 @param st stack. 203 @param st stack.
@@ -199,10 +209,10 @@ public:
199 virtual ast_holder_type get_type() const = 0; 209 virtual ast_holder_type get_type() const = 0;
200}; 210};
201 211
202
203class _ast_ptr : public ast_member { 212class _ast_ptr : public ast_member {
204public: 213public:
205 _ast_ptr(ast_node* node) : m_ptr(node) { 214 _ast_ptr(ast_node* node)
215 : m_ptr(node) {
206 if (node) node->retain(); 216 if (node) node->retain();
207 } 217 }
208 218
@@ -250,6 +260,7 @@ public:
250 virtual ast_holder_type get_type() const override { 260 virtual ast_holder_type get_type() const override {
251 return ast_holder_type::Pointer; 261 return ast_holder_type::Pointer;
252 } 262 }
263
253protected: 264protected:
254 ast_node* m_ptr; 265 ast_node* m_ptr;
255}; 266};
@@ -260,11 +271,14 @@ protected:
260 @tparam Required if true, the object is required. 271 @tparam Required if true, the object is required.
261 @tparam T type of object to control. 272 @tparam T type of object to control.
262*/ 273*/
263template <bool Required, class T> class ast_ptr : public _ast_ptr { 274template <bool Required, class T>
275class ast_ptr : public _ast_ptr {
264public: 276public:
265 ast_ptr(T* node = nullptr) : _ast_ptr(node) {} 277 ast_ptr(T* node = nullptr)
278 : _ast_ptr(node) { }
266 279
267 ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} 280 ast_ptr(const ast_ptr& other)
281 : _ast_ptr(other.get()) { }
268 282
269 ast_ptr& operator=(const ast_ptr& other) { 283 ast_ptr& operator=(const ast_ptr& other) {
270 set(other.get()); 284 set(other.get());
@@ -315,17 +329,21 @@ public:
315 m_ptr = node; 329 m_ptr = node;
316 node->retain(); 330 node->retain();
317 } 331 }
332
318private: 333private:
319 virtual bool accept(ast_node* node) override { 334 virtual bool accept(ast_node* node) override {
320 return node && (std::is_same<ast_node,T>() || id<T>() == node->getId()); 335 return node && (std::is_same<ast_node, T>() || id<T>() == node->getId());
321 } 336 }
322}; 337};
323 338
324template <bool Required, class ...Args> class ast_sel : public _ast_ptr { 339template <bool Required, class... Args>
340class ast_sel : public _ast_ptr {
325public: 341public:
326 ast_sel() : _ast_ptr(nullptr) {} 342 ast_sel()
343 : _ast_ptr(nullptr) { }
327 344
328 ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} 345 ast_sel(const ast_sel& other)
346 : _ast_ptr(other.get()) { }
329 347
330 ast_sel& operator=(const ast_sel& other) { 348 ast_sel& operator=(const ast_sel& other) {
331 set(other.get()); 349 set(other.get());
@@ -355,6 +373,7 @@ public:
355 m_ptr = node; 373 m_ptr = node;
356 node->retain(); 374 node->retain();
357 } 375 }
376
358private: 377private:
359 virtual bool accept(ast_node* node) override { 378 virtual bool accept(ast_node* node) override {
360 if (!node) return false; 379 if (!node) return false;
@@ -428,14 +447,14 @@ public:
428 } 447 }
429 448
430 void clear() { 449 void clear() {
431 for(ast_node* obj : m_objects) { 450 for (ast_node* obj : m_objects) {
432 if (obj) obj->release(); 451 if (obj) obj->release();
433 } 452 }
434 m_objects.clear(); 453 m_objects.clear();
435 } 454 }
436 455
437 void dup(const _ast_list& src) { 456 void dup(const _ast_list& src) {
438 for(ast_node* obj : src.m_objects) { 457 for (ast_node* obj : src.m_objects) {
439 m_objects.push_back(obj); 458 m_objects.push_back(obj);
440 obj->retain(); 459 obj->retain();
441 } 460 }
@@ -444,6 +463,7 @@ public:
444 virtual ast_holder_type get_type() const override { 463 virtual ast_holder_type get_type() const override {
445 return ast_holder_type::List; 464 return ast_holder_type::List;
446 } 465 }
466
447protected: 467protected:
448 node_container m_objects; 468 node_container m_objects;
449}; 469};
@@ -454,7 +474,8 @@ protected:
454 @tparam Required if true, the object is required. 474 @tparam Required if true, the object is required.
455 @tparam T type of object to control. 475 @tparam T type of object to control.
456*/ 476*/
457template <bool Required, class T> class ast_list : public _ast_list { 477template <bool Required, class T>
478class ast_list : public _ast_list {
458public: 479public:
459 ast_list() { } 480 ast_list() { }
460 481
@@ -471,7 +492,7 @@ public:
471 /** Pops objects of type T from the stack until no more objects can be popped. 492 /** Pops objects of type T from the stack until no more objects can be popped.
472 @param st stack. 493 @param st stack.
473 */ 494 */
474 virtual void construct(ast_stack &st) override { 495 virtual void construct(ast_stack& st) override {
475 while (!st.empty()) { 496 while (!st.empty()) {
476 ast_node* node = st.back(); 497 ast_node* node = st.back();
477 // if the object was not not of the appropriate type, 498 // if the object was not not of the appropriate type,
@@ -491,13 +512,15 @@ public:
491 throw std::logic_error("Invalid AST stack."); 512 throw std::logic_error("Invalid AST stack.");
492 } 513 }
493 } 514 }
515
494private: 516private:
495 virtual bool accept(ast_node* node) override { 517 virtual bool accept(ast_node* node) override {
496 return node && (std::is_same<ast_node,T>() || id<T>() == node->getId()); 518 return node && (std::is_same<ast_node, T>() || id<T>() == node->getId());
497 } 519 }
498}; 520};
499 521
500template <bool Required, class ...Args> class ast_sel_list : public _ast_list { 522template <bool Required, class... Args>
523class ast_sel_list : public _ast_list {
501public: 524public:
502 ast_sel_list() { } 525 ast_sel_list() { }
503 526
@@ -511,7 +534,7 @@ public:
511 return *this; 534 return *this;
512 } 535 }
513 536
514 virtual void construct(ast_stack &st) override { 537 virtual void construct(ast_stack& st) override {
515 while (!st.empty()) { 538 while (!st.empty()) {
516 ast_node* node = st.back(); 539 ast_node* node = st.back();
517 if (!ast_sel_list::accept(node)) { 540 if (!ast_sel_list::accept(node)) {
@@ -528,6 +551,7 @@ public:
528 throw std::logic_error("Invalid AST stack."); 551 throw std::logic_error("Invalid AST stack.");
529 } 552 }
530 } 553 }
554
531private: 555private:
532 virtual bool accept(ast_node* node) override { 556 virtual bool accept(ast_node* node) override {
533 if (!node) return false; 557 if (!node) return false;
@@ -541,7 +565,8 @@ private:
541/** AST function which creates an object of type T 565/** AST function which creates an object of type T
542 and pushes it to the node stack. 566 and pushes it to the node stack.
543*/ 567*/
544template <class T> class ast { 568template <class T>
569class ast {
545public: 570public:
546 /** constructor. 571 /** constructor.
547 @param r rule to attach the AST function to. 572 @param r rule to attach the AST function to.
@@ -549,8 +574,9 @@ public:
549 ast(rule& r) { 574 ast(rule& r) {
550 r.set_parse_proc(&_parse_proc); 575 r.set_parse_proc(&_parse_proc);
551 } 576 }
577
552private: 578private:
553 //parse proc 579 // parse proc
554 static void _parse_proc(const pos& b, const pos& e, void* d) { 580 static void _parse_proc(const pos& b, const pos& e, void* d) {
555 ast_stack* st = reinterpret_cast<ast_stack*>(d); 581 ast_stack* st = reinterpret_cast<ast_stack*>(d);
556 T* obj = new T; 582 T* obj = new T;
@@ -561,7 +587,6 @@ private:
561 } 587 }
562}; 588};
563 589
564
565/** parses the given input. 590/** parses the given input.
566 @param i input. 591 @param i input.
567 @param g root rule of grammar. 592 @param g root rule of grammar.
@@ -572,5 +597,4 @@ private:
572*/ 597*/
573ast_node* parse(input& i, rule& g, error_list& el, void* ud); 598ast_node* parse(input& i, rule& g, error_list& el, void* ud);
574 599
575 600} // namespace parserlib
576} //namespace parserlib