diff options
-rw-r--r-- | MoonParser/ast.cpp | 2 | ||||
-rw-r--r-- | MoonParser/ast.hpp | 24 | ||||
-rw-r--r-- | MoonParser/main.cpp | 9 |
3 files changed, 27 insertions, 8 deletions
diff --git a/MoonParser/ast.cpp b/MoonParser/ast.cpp index 916fdd7..090f5ee 100644 --- a/MoonParser/ast.cpp +++ b/MoonParser/ast.cpp | |||
@@ -8,6 +8,8 @@ namespace parserlib { | |||
8 | //current AST container. | 8 | //current AST container. |
9 | static ast_container *_current = 0; | 9 | static ast_container *_current = 0; |
10 | 10 | ||
11 | int ast_type_id = 0; | ||
12 | |||
11 | 13 | ||
12 | /** sets the container under construction to be this. | 14 | /** sets the container under construction to be this. |
13 | */ | 15 | */ |
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; |
diff --git a/MoonParser/main.cpp b/MoonParser/main.cpp index 985fdcf..202a8df 100644 --- a/MoonParser/main.cpp +++ b/MoonParser/main.cpp | |||
@@ -50,7 +50,7 @@ struct Data | |||
50 | rule Any = any(); | 50 | rule Any = any(); |
51 | rule plain_space = *set(" \t"); | 51 | rule plain_space = *set(" \t"); |
52 | rule Break = nl(-expr('\r') >> '\n'); | 52 | rule Break = nl(-expr('\r') >> '\n'); |
53 | rule White = *(set(" \t\r") | Break); | 53 | rule White = *(set(" \t") | Break); |
54 | rule Stop = Break | eof(); | 54 | rule Stop = Break | eof(); |
55 | rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); | 55 | rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); |
56 | rule Indent = *set(" \t"); | 56 | rule Indent = *set(" \t"); |
@@ -556,12 +556,14 @@ rule BlockEnd = Block >> eof(); | |||
556 | #define AST_LEAF(type) \ | 556 | #define AST_LEAF(type) \ |
557 | class type##_t : public ast_node \ | 557 | class type##_t : public ast_node \ |
558 | { \ | 558 | { \ |
559 | public: | 559 | public: \ |
560 | virtual int get_type() override { return ast_type<type##_t>(); } | ||
560 | 561 | ||
561 | #define AST_NODE(type) \ | 562 | #define AST_NODE(type) \ |
562 | class type##_t : public ast_container \ | 563 | class type##_t : public ast_container \ |
563 | { \ | 564 | { \ |
564 | public: | 565 | public: \ |
566 | virtual int get_type() override { return ast_type<type##_t>(); } | ||
565 | 567 | ||
566 | #define AST_END(type) \ | 568 | #define AST_END(type) \ |
567 | }; \ | 569 | }; \ |
@@ -577,7 +579,6 @@ AST_LEAF(Num) | |||
577 | stream << static_cast<char>(*it); | 579 | stream << static_cast<char>(*it); |
578 | } | 580 | } |
579 | stream >> value; | 581 | stream >> value; |
580 | cout << value << '\n'; | ||
581 | } | 582 | } |
582 | AST_END(Num) | 583 | AST_END(Num) |
583 | 584 | ||