diff options
Diffstat (limited to 'src/MoonP/ast.hpp')
-rw-r--r-- | src/MoonP/ast.hpp | 431 |
1 files changed, 216 insertions, 215 deletions
diff --git a/src/MoonP/ast.hpp b/src/MoonP/ast.hpp index 38141e2..8bcfc21 100644 --- a/src/MoonP/ast.hpp +++ b/src/MoonP/ast.hpp | |||
@@ -1,12 +1,13 @@ | |||
1 | /* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li | 1 | /* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li |
2 | All rights reserved. | 2 | All rights reserved. |
3 | 3 | ||
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
5 | 5 | ||
6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. | ||
8 | 7 | ||
9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 8 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
9 | |||
10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ | ||
10 | 11 | ||
11 | #pragma once | 12 | #pragma once |
12 | 13 | ||
@@ -28,7 +29,7 @@ template <class T> class ast; | |||
28 | 29 | ||
29 | 30 | ||
30 | /** type of AST node stack. | 31 | /** type of AST node stack. |
31 | */ | 32 | */ |
32 | typedef std::vector<ast_node*> ast_stack; | 33 | typedef std::vector<ast_node*> ast_stack; |
33 | typedef std::list<ast_node*> node_container; | 34 | typedef std::list<ast_node*> node_container; |
34 | 35 | ||
@@ -47,7 +48,7 @@ enum class traversal { | |||
47 | }; | 48 | }; |
48 | 49 | ||
49 | /** Base class for AST nodes. | 50 | /** Base class for AST nodes. |
50 | */ | 51 | */ |
51 | class ast_node : public input_range { | 52 | class ast_node : public input_range { |
52 | public: | 53 | public: |
53 | ast_node() : _ref(0) {} | 54 | ast_node() : _ref(0) {} |
@@ -63,14 +64,14 @@ public: | |||
63 | } | 64 | } |
64 | } | 65 | } |
65 | 66 | ||
66 | /** interface for filling the contents of the node | 67 | /** interface for filling the contents of the node |
67 | from a node stack. | 68 | from a node stack. |
68 | @param st stack. | 69 | @param st stack. |
69 | */ | 70 | */ |
70 | virtual void construct(ast_stack&) {} | 71 | virtual void construct(ast_stack&) {} |
71 | 72 | ||
72 | /** interface for visiting AST tree use. | 73 | /** interface for visiting AST tree use. |
73 | */ | 74 | */ |
74 | virtual traversal traverse(const std::function<traversal (ast_node*)>& func); | 75 | virtual traversal traverse(const std::function<traversal (ast_node*)>& func); |
75 | 76 | ||
76 | template <typename... Ts> | 77 | template <typename... Ts> |
@@ -128,12 +129,12 @@ bool ast_is(ast_node* node) { | |||
128 | class ast_member; | 129 | class ast_member; |
129 | 130 | ||
130 | /** type of ast member vector. | 131 | /** type of ast member vector. |
131 | */ | 132 | */ |
132 | typedef std::vector<ast_member*> ast_member_vector; | 133 | typedef std::vector<ast_member*> ast_member_vector; |
133 | 134 | ||
134 | 135 | ||
135 | /** base class for AST nodes with children. | 136 | /** base class for AST nodes with children. |
136 | */ | 137 | */ |
137 | class ast_container : public ast_node { | 138 | class ast_container : public ast_node { |
138 | public: | 139 | public: |
139 | void add_members(std::initializer_list<ast_member*> members) { | 140 | void add_members(std::initializer_list<ast_member*> members) { |
@@ -142,42 +143,42 @@ public: | |||
142 | } | 143 | } |
143 | } | 144 | } |
144 | 145 | ||
145 | /** returns the vector of AST members. | 146 | /** returns the vector of AST members. |
146 | @return the vector of AST members. | 147 | @return the vector of AST members. |
147 | */ | 148 | */ |
148 | const ast_member_vector& members() const { | 149 | const ast_member_vector& members() const { |
149 | return m_members; | 150 | return m_members; |
150 | } | 151 | } |
151 | 152 | ||
152 | /** Asks all members to construct themselves from the stack. | 153 | /** Asks all members to construct themselves from the stack. |
153 | The members are asked to construct themselves in reverse order. | 154 | The members are asked to construct themselves in reverse order. |
154 | from a node stack. | 155 | from a node stack. |
155 | @param st stack. | 156 | @param st stack. |
156 | */ | 157 | */ |
157 | virtual void construct(ast_stack& st) override; | 158 | virtual void construct(ast_stack& st) override; |
158 | 159 | ||
159 | virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override; | 160 | virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override; |
160 | 161 | ||
161 | virtual bool visitChild(const std::function<bool (ast_node*)>& func) override; | 162 | virtual bool visitChild(const std::function<bool (ast_node*)>& func) override; |
162 | private: | 163 | private: |
163 | ast_member_vector m_members; | 164 | ast_member_vector m_members; |
164 | 165 | ||
165 | friend class ast_member; | 166 | friend class ast_member; |
166 | }; | 167 | }; |
167 | 168 | ||
168 | 169 | ||
169 | /** Base class for children of ast_container. | 170 | /** Base class for children of ast_container. |
170 | */ | 171 | */ |
171 | class ast_member { | 172 | class ast_member { |
172 | public: | 173 | public: |
173 | virtual ~ast_member() {} | 174 | virtual ~ast_member() {} |
174 | 175 | ||
175 | /** interface for filling the the member from a node stack. | 176 | /** interface for filling the the member from a node stack. |
176 | @param st stack. | 177 | @param st stack. |
177 | */ | 178 | */ |
178 | virtual void construct(ast_stack& st) = 0; | 179 | virtual void construct(ast_stack& st) = 0; |
179 | 180 | ||
180 | virtual bool accept(ast_node* node) = 0; | 181 | virtual bool accept(ast_node* node) = 0; |
181 | 182 | ||
182 | virtual int get_type() { return ast_type<ast_member>(); } | 183 | virtual int get_type() { return ast_type<ast_member>(); } |
183 | }; | 184 | }; |
@@ -193,12 +194,12 @@ public: | |||
193 | if (node) node->retain(); | 194 | if (node) node->retain(); |
194 | } | 195 | } |
195 | 196 | ||
196 | virtual ~_ast_ptr() { | 197 | virtual ~_ast_ptr() { |
197 | if (m_ptr) { | 198 | if (m_ptr) { |
198 | m_ptr->release(); | 199 | m_ptr->release(); |
199 | m_ptr = nullptr; | 200 | m_ptr = nullptr; |
200 | } | 201 | } |
201 | } | 202 | } |
202 | 203 | ||
203 | ast_node* get() const { | 204 | ast_node* get() const { |
204 | return m_ptr; | 205 | return m_ptr; |
@@ -242,109 +243,109 @@ protected: | |||
242 | }; | 243 | }; |
243 | 244 | ||
244 | /** pointer to an AST object. | 245 | /** pointer to an AST object. |
245 | It assumes ownership of the object. | 246 | It assumes ownership of the object. |
246 | It pops an object of the given type from the stack. | 247 | It pops an object of the given type from the stack. |
247 | @tparam Required if true, the object is required. | 248 | @tparam Required if true, the object is required. |
248 | @tparam T type of object to control. | 249 | @tparam T type of object to control. |
249 | */ | 250 | */ |
250 | template <bool Required, class T> class ast_ptr : public _ast_ptr { | 251 | template <bool Required, class T> class ast_ptr : public _ast_ptr { |
251 | public: | 252 | public: |
252 | ast_ptr(T* node = nullptr) : _ast_ptr(node) {} | 253 | ast_ptr(T* node = nullptr) : _ast_ptr(node) {} |
253 | 254 | ||
254 | ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} | 255 | ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} |
255 | 256 | ||
256 | ast_ptr& operator=(const ast_ptr& other) { | 257 | ast_ptr& operator=(const ast_ptr& other) { |
257 | set(other.get()); | 258 | set(other.get()); |
258 | return *this; | 259 | return *this; |
259 | } | 260 | } |
260 | 261 | ||
261 | /** gets the underlying ptr value. | 262 | /** gets the underlying ptr value. |
262 | @return the underlying ptr value. | 263 | @return the underlying ptr value. |
263 | */ | 264 | */ |
264 | T* get() const { | 265 | T* get() const { |
265 | return static_cast<T*>(m_ptr); | 266 | return static_cast<T*>(m_ptr); |
266 | } | 267 | } |
267 | 268 | ||
268 | /** auto conversion to the underlying object ptr. | 269 | /** auto conversion to the underlying object ptr. |
269 | @return the underlying ptr value. | 270 | @return the underlying ptr value. |
270 | */ | 271 | */ |
271 | operator T*() const { | 272 | operator T*() const { |
272 | return static_cast<T*>(m_ptr); | 273 | return static_cast<T*>(m_ptr); |
273 | } | 274 | } |
274 | 275 | ||
275 | /** member access. | 276 | /** member access. |
276 | @return the underlying ptr value. | 277 | @return the underlying ptr value. |
277 | */ | 278 | */ |
278 | T* operator->() const { | 279 | T* operator->() const { |
279 | assert(m_ptr); | 280 | assert(m_ptr); |
280 | return static_cast<T*>(m_ptr); | 281 | return static_cast<T*>(m_ptr); |
281 | } | 282 | } |
282 | 283 | ||
283 | /** Pops a node from the stack. | 284 | /** Pops a node from the stack. |
284 | @param st stack. | 285 | @param st stack. |
285 | @exception std::logic_error thrown if the node is not of the appropriate type; | 286 | @exception std::logic_error thrown if the node is not of the appropriate type; |
286 | thrown only if Required == true or if the stack is empty. | 287 | thrown only if Required == true or if the stack is empty. |
287 | */ | 288 | */ |
288 | virtual void construct(ast_stack& st) override { | 289 | virtual void construct(ast_stack& st) override { |
289 | // check the stack node | 290 | // check the stack node |
290 | if (st.empty()) { | 291 | if (st.empty()) { |
291 | if (!Required) return; | 292 | if (!Required) return; |
292 | throw std::logic_error("Invalid AST stack."); | 293 | throw std::logic_error("Invalid AST stack."); |
293 | } | 294 | } |
294 | ast_node* node = st.back(); | 295 | ast_node* node = st.back(); |
295 | if (!ast_ptr::accept(node)) { | 296 | if (!ast_ptr::accept(node)) { |
296 | // if the object is not required, simply return | 297 | // if the object is not required, simply return |
297 | if (!Required) return; | 298 | if (!Required) return; |
298 | // else if the object is mandatory, throw an exception | 299 | // else if the object is mandatory, throw an exception |
299 | throw std::logic_error("Invalid AST node."); | 300 | throw std::logic_error("Invalid AST node."); |
300 | } | 301 | } |
301 | st.pop_back(); | 302 | st.pop_back(); |
302 | m_ptr = node; | 303 | m_ptr = node; |
303 | node->retain(); | 304 | node->retain(); |
304 | } | 305 | } |
305 | private: | 306 | private: |
306 | virtual bool accept(ast_node* node) override { | 307 | virtual bool accept(ast_node* node) override { |
307 | return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); | 308 | return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); |
308 | } | 309 | } |
309 | }; | 310 | }; |
310 | 311 | ||
311 | template <bool Required, class ...Args> class ast_sel : public _ast_ptr { | 312 | template <bool Required, class ...Args> class ast_sel : public _ast_ptr { |
312 | public: | 313 | public: |
313 | ast_sel() : _ast_ptr(nullptr) {} | 314 | ast_sel() : _ast_ptr(nullptr) {} |
314 | 315 | ||
315 | ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} | 316 | ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} |
316 | 317 | ||
317 | ast_sel& operator=(const ast_sel& other) { | 318 | ast_sel& operator=(const ast_sel& other) { |
318 | set(other.get()); | 319 | set(other.get()); |
319 | return *this; | 320 | return *this; |
320 | } | 321 | } |
321 | 322 | ||
322 | operator ast_node*() const { | 323 | operator ast_node*() const { |
323 | return m_ptr; | 324 | return m_ptr; |
324 | } | 325 | } |
325 | 326 | ||
326 | ast_node* operator->() const { | 327 | ast_node* operator->() const { |
327 | assert(m_ptr); | 328 | assert(m_ptr); |
328 | return m_ptr; | 329 | return m_ptr; |
329 | } | 330 | } |
330 | 331 | ||
331 | virtual void construct(ast_stack& st) override { | 332 | virtual void construct(ast_stack& st) override { |
332 | if (st.empty()) { | 333 | if (st.empty()) { |
333 | if (!Required) return; | 334 | if (!Required) return; |
334 | throw std::logic_error("Invalid AST stack."); | 335 | throw std::logic_error("Invalid AST stack."); |
335 | } | 336 | } |
336 | ast_node* node = st.back(); | 337 | ast_node* node = st.back(); |
337 | if (!ast_sel::accept(node)) { | 338 | if (!ast_sel::accept(node)) { |
338 | if (!Required) return; | 339 | if (!Required) return; |
339 | throw std::logic_error("Invalid AST node."); | 340 | throw std::logic_error("Invalid AST node."); |
340 | } | 341 | } |
341 | st.pop_back(); | 342 | st.pop_back(); |
342 | m_ptr = node; | 343 | m_ptr = node; |
343 | node->retain(); | 344 | node->retain(); |
344 | } | 345 | } |
345 | private: | 346 | private: |
346 | virtual bool accept(ast_node* node) override { | 347 | virtual bool accept(ast_node* node) override { |
347 | if (!node) return false; | 348 | if (!node) return false; |
348 | using swallow = bool[]; | 349 | using swallow = bool[]; |
349 | bool result = false; | 350 | bool result = false; |
350 | (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; | 351 | (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; |
@@ -355,8 +356,8 @@ private: | |||
355 | class _ast_list : public ast_member { | 356 | class _ast_list : public ast_member { |
356 | public: | 357 | public: |
357 | ~_ast_list() { | 358 | ~_ast_list() { |
358 | clear(); | 359 | clear(); |
359 | } | 360 | } |
360 | 361 | ||
361 | inline ast_node* back() const { | 362 | inline ast_node* back() const { |
362 | return m_objects.back(); | 363 | return m_objects.back(); |
@@ -374,14 +375,14 @@ public: | |||
374 | return m_objects.empty(); | 375 | return m_objects.empty(); |
375 | } | 376 | } |
376 | 377 | ||
377 | void push_back(ast_node* node) { | 378 | void push_back(ast_node* node) { |
378 | assert(node && accept(node)); | 379 | assert(node && accept(node)); |
379 | m_objects.push_back(node); | 380 | m_objects.push_back(node); |
380 | node->retain(); | 381 | node->retain(); |
381 | } | 382 | } |
382 | 383 | ||
383 | void push_front(ast_node* node) { | 384 | void push_front(ast_node* node) { |
384 | assert(node && accept(node)); | 385 | assert(node && accept(node)); |
385 | m_objects.push_front(node); | 386 | m_objects.push_front(node); |
386 | node->retain(); | 387 | node->retain(); |
387 | } | 388 | } |
@@ -399,22 +400,22 @@ public: | |||
399 | } | 400 | } |
400 | 401 | ||
401 | const node_container& objects() const { | 402 | const node_container& objects() const { |
402 | return m_objects; | 403 | return m_objects; |
403 | } | 404 | } |
404 | 405 | ||
405 | void clear() { | 406 | void clear() { |
406 | for(ast_node* obj : m_objects) { | 407 | for(ast_node* obj : m_objects) { |
407 | if (obj) obj->release(); | 408 | if (obj) obj->release(); |
408 | } | 409 | } |
409 | m_objects.clear(); | 410 | m_objects.clear(); |
410 | } | 411 | } |
411 | 412 | ||
412 | void dup(const _ast_list& src) { | 413 | void dup(const _ast_list& src) { |
413 | for(ast_node* obj : src.m_objects) { | 414 | for(ast_node* obj : src.m_objects) { |
414 | m_objects.push_back(obj); | 415 | m_objects.push_back(obj); |
415 | obj->retain(); | 416 | obj->retain(); |
416 | } | 417 | } |
417 | } | 418 | } |
418 | 419 | ||
419 | virtual int get_type() override { return ast_type<_ast_list>(); } | 420 | virtual int get_type() override { return ast_type<_ast_list>(); } |
420 | protected: | 421 | protected: |
@@ -422,50 +423,50 @@ protected: | |||
422 | }; | 423 | }; |
423 | 424 | ||
424 | /** A list of objects. | 425 | /** A list of objects. |
425 | It pops objects of the given type from the ast stack, until no more objects can be popped. | 426 | It pops objects of the given type from the ast stack, until no more objects can be popped. |
426 | It assumes ownership of objects. | 427 | It assumes ownership of objects. |
427 | @tparam Required if true, the object is required. | 428 | @tparam Required if true, the object is required. |
428 | @tparam T type of object to control. | 429 | @tparam T type of object to control. |
429 | */ | 430 | */ |
430 | template <bool Required, class T> class ast_list : public _ast_list { | 431 | template <bool Required, class T> class ast_list : public _ast_list { |
431 | public: | 432 | public: |
432 | ast_list() { } | 433 | ast_list() { } |
433 | 434 | ||
434 | ast_list(const ast_list& other) { | 435 | ast_list(const ast_list& other) { |
435 | dup(other); | 436 | dup(other); |
436 | } | 437 | } |
437 | 438 | ||
438 | ast_list& operator=(const ast_list& other) { | 439 | ast_list& operator=(const ast_list& other) { |
439 | clear(); | 440 | clear(); |
440 | dup(other); | 441 | dup(other); |
441 | return *this; | 442 | return *this; |
442 | } | 443 | } |
443 | 444 | ||
444 | /** Pops objects of type T from the stack until no more objects can be popped. | 445 | /** Pops objects of type T from the stack until no more objects can be popped. |
445 | @param st stack. | 446 | @param st stack. |
446 | */ | 447 | */ |
447 | virtual void construct(ast_stack &st) override { | 448 | virtual void construct(ast_stack &st) override { |
448 | while (!st.empty()) { | 449 | while (!st.empty()) { |
449 | ast_node* node = st.back(); | 450 | ast_node* node = st.back(); |
450 | // if the object was not not of the appropriate type, | 451 | // if the object was not not of the appropriate type, |
451 | // end the list parsing | 452 | // end the list parsing |
452 | if (!ast_list::accept(node)) { | 453 | if (!ast_list::accept(node)) { |
453 | if (Required && m_objects.empty()) { | 454 | if (Required && m_objects.empty()) { |
454 | throw std::logic_error("Invalid AST node."); | 455 | throw std::logic_error("Invalid AST node."); |
455 | } | 456 | } |
456 | return; | 457 | return; |
457 | } | 458 | } |
458 | st.pop_back(); | 459 | st.pop_back(); |
459 | // insert the object in the list, in reverse order | 460 | // insert the object in the list, in reverse order |
460 | m_objects.push_front(node); | 461 | m_objects.push_front(node); |
461 | node->retain(); | 462 | node->retain(); |
462 | } | 463 | } |
463 | if (Required && m_objects.empty()) { | 464 | if (Required && m_objects.empty()) { |
464 | throw std::logic_error("Invalid AST stack."); | 465 | throw std::logic_error("Invalid AST stack."); |
465 | } | 466 | } |
466 | } | 467 | } |
467 | private: | 468 | private: |
468 | virtual bool accept(ast_node* node) override { | 469 | virtual bool accept(ast_node* node) override { |
469 | return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); | 470 | return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); |
470 | } | 471 | } |
471 | }; | 472 | }; |
@@ -474,36 +475,36 @@ template <bool Required, class ...Args> class ast_sel_list : public _ast_list { | |||
474 | public: | 475 | public: |
475 | ast_sel_list() { } | 476 | ast_sel_list() { } |
476 | 477 | ||
477 | ast_sel_list(const ast_sel_list& other) { | 478 | ast_sel_list(const ast_sel_list& other) { |
478 | dup(other); | 479 | dup(other); |
479 | } | 480 | } |
480 | 481 | ||
481 | ast_sel_list& operator=(const ast_sel_list& other) { | 482 | ast_sel_list& operator=(const ast_sel_list& other) { |
482 | clear(); | 483 | clear(); |
483 | dup(other); | 484 | dup(other); |
484 | return *this; | 485 | return *this; |
485 | } | 486 | } |
486 | 487 | ||
487 | virtual void construct(ast_stack &st) override { | 488 | virtual void construct(ast_stack &st) override { |
488 | while (!st.empty()) { | 489 | while (!st.empty()) { |
489 | ast_node* node = st.back(); | 490 | ast_node* node = st.back(); |
490 | if (!ast_sel_list::accept(node)) { | 491 | if (!ast_sel_list::accept(node)) { |
491 | if (Required && m_objects.empty()) { | 492 | if (Required && m_objects.empty()) { |
492 | throw std::logic_error("Invalid AST node."); | 493 | throw std::logic_error("Invalid AST node."); |
493 | } | 494 | } |
494 | return; | 495 | return; |
495 | } | 496 | } |
496 | st.pop_back(); | 497 | st.pop_back(); |
497 | m_objects.push_front(node); | 498 | m_objects.push_front(node); |
498 | node->retain(); | 499 | node->retain(); |
499 | } | 500 | } |
500 | if (Required && m_objects.empty()) { | 501 | if (Required && m_objects.empty()) { |
501 | throw std::logic_error("Invalid AST stack."); | 502 | throw std::logic_error("Invalid AST stack."); |
502 | } | 503 | } |
503 | } | 504 | } |
504 | private: | 505 | private: |
505 | virtual bool accept(ast_node* node) override { | 506 | virtual bool accept(ast_node* node) override { |
506 | if (!node) return false; | 507 | if (!node) return false; |
507 | using swallow = bool[]; | 508 | using swallow = bool[]; |
508 | bool result = false; | 509 | bool result = false; |
509 | (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; | 510 | (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; |
@@ -512,37 +513,37 @@ private: | |||
512 | }; | 513 | }; |
513 | 514 | ||
514 | /** AST function which creates an object of type T | 515 | /** AST function which creates an object of type T |
515 | and pushes it to the node stack. | 516 | and pushes it to the node stack. |
516 | */ | 517 | */ |
517 | template <class T> class ast { | 518 | template <class T> class ast { |
518 | public: | 519 | public: |
519 | /** constructor. | 520 | /** constructor. |
520 | @param r rule to attach the AST function to. | 521 | @param r rule to attach the AST function to. |
521 | */ | 522 | */ |
522 | ast(rule& r) { | 523 | ast(rule& r) { |
523 | r.set_parse_proc(&_parse_proc); | 524 | r.set_parse_proc(&_parse_proc); |
524 | } | 525 | } |
525 | private: | 526 | private: |
526 | //parse proc | 527 | //parse proc |
527 | static void _parse_proc(const pos& b, const pos& e, void* d) { | 528 | static void _parse_proc(const pos& b, const pos& e, void* d) { |
528 | ast_stack* st = reinterpret_cast<ast_stack*>(d); | 529 | ast_stack* st = reinterpret_cast<ast_stack*>(d); |
529 | T* obj = new T; | 530 | T* obj = new T; |
530 | obj->m_begin = b; | 531 | obj->m_begin = b; |
531 | obj->m_end = e; | 532 | obj->m_end = e; |
532 | obj->construct(*st); | 533 | obj->construct(*st); |
533 | st->push_back(obj); | 534 | st->push_back(obj); |
534 | } | 535 | } |
535 | }; | 536 | }; |
536 | 537 | ||
537 | 538 | ||
538 | /** parses the given input. | 539 | /** parses the given input. |
539 | @param i input. | 540 | @param i input. |
540 | @param g root rule of grammar. | 541 | @param g root rule of grammar. |
541 | @param el list of errors. | 542 | @param el list of errors. |
542 | @param ud user data, passed to the parse procedures. | 543 | @param ud user data, passed to the parse procedures. |
543 | @return pointer to ast node created, or null if there was an error. | 544 | @return pointer to ast node created, or null if there was an error. |
544 | The return object must be deleted by the caller. | 545 | The return object must be deleted by the caller. |
545 | */ | 546 | */ |
546 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); | 547 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); |
547 | 548 | ||
548 | 549 | ||