diff options
Diffstat (limited to '')
| -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; |
