aboutsummaryrefslogtreecommitdiff
path: root/MoonParser/ast.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'MoonParser/ast.hpp')
-rw-r--r--MoonParser/ast.hpp24
1 files changed, 20 insertions, 4 deletions
diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp
index 664c8af..01e2350 100644
--- a/MoonParser/ast.hpp
+++ b/MoonParser/ast.hpp
@@ -5,6 +5,7 @@
5#include <cassert> 5#include <cassert>
6#include <list> 6#include <list>
7#include <stdexcept> 7#include <stdexcept>
8#include <type_traits>
8#include "parser.hpp" 9#include "parser.hpp"
9 10
10 11
@@ -21,6 +22,14 @@ template <class T> class ast;
21 */ 22 */
22typedef std::vector<ast_node *> ast_stack; 23typedef std::vector<ast_node *> ast_stack;
23 24
25extern int ast_type_id;
26
27template<class T>
28int ast_type()
29{
30 static int type = ast_type_id++;
31 return type;
32}
24 33
25/** Base class for AST nodes. 34/** Base class for AST nodes.
26 */ 35 */
@@ -58,6 +67,8 @@ public:
58 @param user_data vector for storing user data. 67 @param user_data vector for storing user data.
59 */ 68 */
60 virtual void visit(void* user_data) {} 69 virtual void visit(void* user_data) {}
70
71 virtual int get_type() { return ast_type<ast_node>(); }
61private: 72private:
62 //parent 73 //parent
63 ast_node *m_parent; 74 ast_node *m_parent;
@@ -68,6 +79,11 @@ private:
68 template <class T> friend class ast; 79 template <class T> friend class ast;
69}; 80};
70 81
82template<class T>
83T* ast_cast(ast_node *node)
84{
85 return ast_type<T>() == node->get_type() ? static_cast<T*>(node) : nullptr;
86}
71 87
72class ast_member; 88class ast_member;
73 89
@@ -254,7 +270,7 @@ public:
254 ast_node *node = st.back(); 270 ast_node *node = st.back();
255 271
256 //get the object 272 //get the object
257 T *obj = dynamic_cast<T *>(node); 273 T *obj = std::is_same<T, ast_node>() ? static_cast<T*>(node) : ast_cast<T>(node);
258 274
259 //if the object is optional, simply return 275 //if the object is optional, simply return
260 if (OPT) { 276 if (OPT) {
@@ -337,7 +353,7 @@ public:
337 ast_node *obj = nullptr; 353 ast_node *obj = nullptr;
338 354
339 using swallow = bool[]; 355 using swallow = bool[];
340 (void)swallow{obj || (obj = dynamic_cast<Args*>(node))...}; 356 (void)swallow{obj || (obj = std::is_same<Args, ast_node>() ? node : ast_cast<Args>(node))...};
341 357
342 if (!obj) throw std::logic_error("invalid AST node"); 358 if (!obj) throw std::logic_error("invalid AST node");
343 359
@@ -414,7 +430,7 @@ public:
414 ast_node *node = st.back(); 430 ast_node *node = st.back();
415 431
416 //get the object 432 //get the object
417 T *obj = dynamic_cast<T *>(node); 433 T *obj = std::is_same<T, ast_node>() ? static_cast<T*>(node) : ast_cast<T>(node);
418 434
419 //if the object was not not of the appropriate type, 435 //if the object was not not of the appropriate type,
420 //end the list parsing 436 //end the list parsing
@@ -503,7 +519,7 @@ ast_node *parse(input &i, rule &g, error_list &el, void* ud);
503 */ 519 */
504template <class T> bool parse(input &i, rule &g, error_list &el, T *&ast, void* ud = nullptr) { 520template <class T> bool parse(input &i, rule &g, error_list &el, T *&ast, void* ud = nullptr) {
505 ast_node *node = parse(i, g, el, ud); 521 ast_node *node = parse(i, g, el, ud);
506 ast = dynamic_cast<T *>(node); 522 ast = ast_cast<T>(node);
507 if (ast) return true; 523 if (ast) return true;
508 delete node; 524 delete node;
509 return false; 525 return false;