aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MoonParser/ast.cpp2
-rw-r--r--MoonParser/ast.hpp24
-rw-r--r--MoonParser/main.cpp9
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.
9static ast_container *_current = 0; 9static ast_container *_current = 0;
10 10
11int 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 */
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;
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
50rule Any = any(); 50rule Any = any();
51rule plain_space = *set(" \t"); 51rule plain_space = *set(" \t");
52rule Break = nl(-expr('\r') >> '\n'); 52rule Break = nl(-expr('\r') >> '\n');
53rule White = *(set(" \t\r") | Break); 53rule White = *(set(" \t") | Break);
54rule Stop = Break | eof(); 54rule Stop = Break | eof();
55rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); 55rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop);
56rule Indent = *set(" \t"); 56rule Indent = *set(" \t");
@@ -556,12 +556,14 @@ rule BlockEnd = Block >> eof();
556#define AST_LEAF(type) \ 556#define AST_LEAF(type) \
557class type##_t : public ast_node \ 557class type##_t : public ast_node \
558{ \ 558{ \
559public: 559public: \
560 virtual int get_type() override { return ast_type<type##_t>(); }
560 561
561#define AST_NODE(type) \ 562#define AST_NODE(type) \
562class type##_t : public ast_container \ 563class type##_t : public ast_container \
563{ \ 564{ \
564public: 565public: \
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 }
582AST_END(Num) 583AST_END(Num)
583 584