diff options
Diffstat (limited to 'src/yuescript/ast.hpp')
-rw-r--r-- | src/yuescript/ast.hpp | 138 |
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 | |||
24 | namespace parserlib { | 22 | namespace parserlib { |
25 | 23 | ||
26 | |||
27 | class ast_node; | 24 | class ast_node; |
28 | template <bool Required, class T> class ast_ptr; | 25 | template <bool Required, class T> |
29 | template <bool Required, class T> class ast_list; | 26 | class ast_ptr; |
30 | template <class T> class ast; | 27 | template <bool Required, class T> |
31 | 28 | class ast_list; | |
29 | template <class T> | ||
30 | class ast; | ||
32 | 31 | ||
33 | /** type of AST node stack. | 32 | /** type of AST node stack. |
34 | */ | 33 | */ |
35 | typedef std::vector<ast_node*> ast_stack; | 34 | typedef std::vector<ast_node*> ast_stack; |
36 | typedef std::list<ast_node*> node_container; | 35 | typedef std::list<ast_node*> node_container; |
37 | 36 | ||
38 | 37 | template <size_t Num> | |
39 | template<size_t Num> struct Counter { enum { value = Counter<Num-1>::value }; }; | 38 | struct Counter { |
40 | template<> struct Counter<0> { enum { value = 0 }; }; | 39 | enum { value = Counter<Num - 1>::value }; |
40 | }; | ||
41 | template <> | ||
42 | struct 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 | ||
45 | class ast_node; | 53 | class ast_node; |
46 | template<class T> | 54 | template <class T> |
47 | constexpr typename std::enable_if<std::is_base_of<ast_node,T>::value,int>::type | 55 | constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type |
48 | id(); | 56 | id(); |
49 | 57 | ||
50 | enum class traversal { | 58 | enum 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 | */ |
58 | class ast_node : public input_range { | 66 | class ast_node : public input_range { |
59 | public: | 67 | public: |
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 | |||
111 | private: | 121 | private: |
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 | ||
116 | template<class T> | 126 | template <class T> |
117 | constexpr typename std::enable_if<std::is_base_of<ast_node,T>::value,int>::type | 127 | constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type |
118 | id() { return 0; } | 128 | id() { return 0; } |
119 | 129 | ||
120 | template<class T> | 130 | template <class T> |
121 | T* ast_cast(ast_node* node) { | 131 | T* 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 | ||
125 | template<class T> | 135 | template <class T> |
126 | T* ast_to(ast_node* node) { | 136 | T* 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 | ||
131 | template <class ...Args> | 141 | template <class... Args> |
132 | bool ast_is(ast_node* node) { | 142 | bool 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) { | |||
141 | class ast_member; | 151 | class ast_member; |
142 | 152 | ||
143 | /** type of ast member vector. | 153 | /** type of ast member vector. |
144 | */ | 154 | */ |
145 | typedef std::vector<ast_member*> ast_member_vector; | 155 | typedef 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 | */ |
150 | class ast_container : public ast_node { | 159 | class ast_container : public ast_node { |
151 | public: | 160 | public: |
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; | ||
175 | private: | 185 | private: |
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 | */ |
188 | class ast_member { | 198 | class ast_member { |
189 | public: | 199 | public: |
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 | |||
203 | class _ast_ptr : public ast_member { | 212 | class _ast_ptr : public ast_member { |
204 | public: | 213 | public: |
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 | |||
253 | protected: | 264 | protected: |
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 | */ |
263 | template <bool Required, class T> class ast_ptr : public _ast_ptr { | 274 | template <bool Required, class T> |
275 | class ast_ptr : public _ast_ptr { | ||
264 | public: | 276 | public: |
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 | |||
318 | private: | 333 | private: |
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 | ||
324 | template <bool Required, class ...Args> class ast_sel : public _ast_ptr { | 339 | template <bool Required, class... Args> |
340 | class ast_sel : public _ast_ptr { | ||
325 | public: | 341 | public: |
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 | |||
358 | private: | 377 | private: |
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 | |||
447 | protected: | 467 | protected: |
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 | */ |
457 | template <bool Required, class T> class ast_list : public _ast_list { | 477 | template <bool Required, class T> |
478 | class ast_list : public _ast_list { | ||
458 | public: | 479 | public: |
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 | |||
494 | private: | 516 | private: |
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 | ||
500 | template <bool Required, class ...Args> class ast_sel_list : public _ast_list { | 522 | template <bool Required, class... Args> |
523 | class ast_sel_list : public _ast_list { | ||
501 | public: | 524 | public: |
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 | |||
531 | private: | 555 | private: |
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 | */ |
544 | template <class T> class ast { | 568 | template <class T> |
569 | class ast { | ||
545 | public: | 570 | public: |
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 | |||
552 | private: | 578 | private: |
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 | */ |
573 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); | 598 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); |
574 | 599 | ||
575 | 600 | } // namespace parserlib | |
576 | } //namespace parserlib | ||