diff options
Diffstat (limited to 'MoonParser/ast.hpp')
-rw-r--r-- | MoonParser/ast.hpp | 24 |
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 | */ |
22 | typedef std::vector<ast_node *> ast_stack; | 23 | typedef std::vector<ast_node *> ast_stack; |
23 | 24 | ||
25 | extern int ast_type_id; | ||
26 | |||
27 | template<class T> | ||
28 | int 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>(); } | ||
61 | private: | 72 | private: |
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 | ||
82 | template<class T> | ||
83 | T* ast_cast(ast_node *node) | ||
84 | { | ||
85 | return ast_type<T>() == node->get_type() ? static_cast<T*>(node) : nullptr; | ||
86 | } | ||
71 | 87 | ||
72 | class ast_member; | 88 | class 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 | */ |
504 | template <class T> bool parse(input &i, rule &g, error_list &el, T *&ast, void* ud = nullptr) { | 520 | template <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; |