aboutsummaryrefslogtreecommitdiff
path: root/MoonParser/ast.hpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2017-07-13 16:03:11 +0800
committerLi Jin <dragon-fly@qq.com>2017-07-13 16:03:11 +0800
commitcb906e739f27931e9798510cd83725131ed55209 (patch)
tree52b465c5eb2250dec3ed3d5f02b86db79653b838 /MoonParser/ast.hpp
parent975c3c7dfa032229272c3b225de1127f1605e2d2 (diff)
downloadyuescript-cb906e739f27931e9798510cd83725131ed55209.tar.gz
yuescript-cb906e739f27931e9798510cd83725131ed55209.tar.bz2
yuescript-cb906e739f27931e9798510cd83725131ed55209.zip
rewrite parsing codes with parserlib.
Diffstat (limited to 'MoonParser/ast.hpp')
-rw-r--r--MoonParser/ast.hpp437
1 files changed, 437 insertions, 0 deletions
diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp
new file mode 100644
index 0000000..5d87db9
--- /dev/null
+++ b/MoonParser/ast.hpp
@@ -0,0 +1,437 @@
1#ifndef AST_HPP
2#define AST_HPP
3
4
5#include <cassert>
6#include <list>
7#include <stdexcept>
8#include "parser.hpp"
9
10
11namespace parserlib {
12
13
14class ast_node;
15template <class T, bool OPT> class ast_ptr;
16template <class T> class ast_list;
17template <class T> class ast;
18
19
20/** type of AST node stack.
21 */
22typedef std::vector<ast_node *> ast_stack;
23
24
25/** Base class for AST nodes.
26 */
27class ast_node : public input_range {
28public:
29 ///constructor.
30 ast_node() : m_parent(0) {}
31
32 /** copy constructor.
33 @param n source object.
34 */
35 ast_node(const ast_node &n) : m_parent(0) {}
36
37 ///destructor.
38 virtual ~ast_node() {}
39
40 /** assignment operator.
41 @param n source object.
42 @return reference to this.
43 */
44 ast_node &operator = (const ast_node &n) { return *this; }
45
46 /** get the parent node.
47 @return the parent node, if there is one.
48 */
49 ast_node *parent() const { return m_parent; }
50
51 /** interface for filling the contents of the node
52 from a node stack.
53 @param st stack.
54 */
55 virtual void construct(ast_stack &st) {}
56
57private:
58 //parent
59 ast_node *m_parent;
60
61 template <class T, bool OPT> friend class ast_ptr;
62 template <class T> friend class ast_list;
63 template <class T> friend class ast;
64};
65
66
67class ast_member;
68
69
70/** type of ast member vector.
71 */
72typedef std::vector<ast_member *> ast_member_vector;
73
74
75/** base class for AST nodes with children.
76 */
77class ast_container : public ast_node {
78public:
79 /** sets the container under construction to be this.
80 */
81 ast_container();
82
83 /** sets the container under construction to be this.
84 Members are not copied.
85 @param src source object.
86 */
87 ast_container(const ast_container &src);
88
89 /** the assignment operator.
90 The members are not copied.
91 @param src source object.
92 @return reference to this.
93 */
94 ast_container &operator = (const ast_container &src) {
95 return *this;
96 }
97
98 /** returns the vector of AST members.
99 @return the vector of AST members.
100 */
101 const ast_member_vector &members() const {
102 return m_members;
103 }
104
105 /** Asks all members to construct themselves from the stack.
106 The members are asked to construct themselves in reverse order.
107 from a node stack.
108 @param st stack.
109 */
110 virtual void construct(ast_stack &st);
111
112private:
113 ast_member_vector m_members;
114
115 friend class ast_member;
116};
117
118
119/** Base class for children of ast_container.
120 */
121class ast_member {
122public:
123 /** automatically registers itself to the container under construction.
124 */
125 ast_member() { _init(); }
126
127 /** automatically registers itself to the container under construction.
128 @param src source object.
129 */
130 ast_member(const ast_member &src) { _init(); }
131
132 /** the assignment operator.
133 @param src source object.
134 @return reference to this.
135 */
136 ast_member &operator = (const ast_member &src) {
137 return *this;
138 }
139
140 /** returns the container this belongs to.
141 @return the container this belongs to.
142 */
143 ast_container *container() const { return m_container; }
144
145 /** interface for filling the the member from a node stack.
146 @param st stack.
147 */
148 virtual void construct(ast_stack &st) = 0;
149
150private:
151 //the container this belongs to.
152 ast_container *m_container;
153
154 //register the AST member to the current container.
155 void _init();
156};
157
158
159/** pointer to an AST object.
160 It assumes ownership of the object.
161 It pops an object of the given type from the stack.
162 @tparam T type of object to control.
163 @tparam OPT if true, the object becomes optional.
164 */
165template <class T, bool OPT = false> class ast_ptr : public ast_member {
166public:
167 /** the default constructor.
168 @param obj object.
169 */
170 ast_ptr(T *obj = 0) : m_ptr(obj) {
171 _set_parent();
172 }
173
174 /** the copy constructor.
175 It duplicates the underlying object.
176 @param src source object.
177 */
178 ast_ptr(const ast_ptr<T, OPT> &src) :
179 m_ptr(src.m_ptr ? new T(*src.m_ptr) : 0)
180 {
181 _set_parent();
182 }
183
184 /** deletes the underlying object.
185 */
186 ~ast_ptr() {
187 delete m_ptr;
188 }
189
190 /** copies the given object.
191 The old object is deleted.
192 @param obj new object.
193 @return reference to this.
194 */
195 ast_ptr<T, OPT> &operator = (const T *obj) {
196 delete m_ptr;
197 m_ptr = obj ? new T(*obj) : 0;
198 _set_parent();
199 return *this;
200 }
201
202 /** copies the underlying object.
203 The old object is deleted.
204 @param src source object.
205 @return reference to this.
206 */
207 ast_ptr<T, OPT> &operator = (const ast_ptr<T, OPT> &src) {
208 delete m_ptr;
209 m_ptr = src.m_ptr ? new T(*src.m_ptr) : 0;
210 _set_parent();
211 return *this;
212 }
213
214 /** gets the underlying ptr value.
215 @return the underlying ptr value.
216 */
217 T *get() const {
218 return m_ptr;
219 }
220
221 /** auto conversion to the underlying object ptr.
222 @return the underlying ptr value.
223 */
224 operator T *() const {
225 return m_ptr;
226 }
227
228 /** member access.
229 @return the underlying ptr value.
230 */
231 T *operator ->() const {
232 assert(m_ptr);
233 return m_ptr;
234 }
235
236 /** Pops a node from the stack.
237 @param st stack.
238 @exception std::logic_error thrown if the node is not of the appropriate type;
239 thrown only if OPT == false or if the stack is empty.
240 */
241 virtual void construct(ast_stack &st) {
242 //check the stack node
243 if (st.empty()) throw std::logic_error("invalid AST stack");
244
245 //get the node
246 ast_node *node = st.back();
247
248 //get the object
249 T *obj = dynamic_cast<T *>(node);
250
251 //if the object is optional, simply return
252 if (OPT) {
253 if (!obj) return;
254 }
255
256 //else if the object is mandatory, throw an exception
257 else {
258 if (!obj) throw std::logic_error("invalid AST node");
259 }
260
261 //pop the node from the stack
262 st.pop_back();
263
264 //set the new object
265 delete m_ptr;
266 m_ptr = obj;
267 _set_parent();
268 }
269
270private:
271 //ptr
272 T *m_ptr;
273
274 //set parent of object
275 void _set_parent() {
276 if (m_ptr) m_ptr->m_parent = container();
277 }
278};
279
280
281/** A list of objects.
282 It pops objects of the given type from the ast stack, until no more objects can be popped.
283 It assumes ownership of objects.
284 @tparam T type of object to control.
285 */
286template <class T> class ast_list : public ast_member {
287public:
288 ///list type.
289 typedef std::list<T *> container;
290
291 ///the default constructor.
292 ast_list() {}
293
294 /** duplicates the objects of the given list.
295 @param src source object.
296 */
297 ast_list(const ast_list<T> &src) {
298 _dup(src);
299 }
300
301 /** deletes the objects.
302 */
303 ~ast_list() {
304 _clear();
305 }
306
307 /** deletes the objects of this list and duplicates the given one.
308 @param src source object.
309 @return reference to this.
310 */
311 ast_list<T> &operator = (const ast_list<T> &src) {
312 if (&src != this) {
313 _clear();
314 _dup(src);
315 }
316 return *this;
317 }
318
319 /** returns the container of objects.
320 @return the container of objects.
321 */
322 const container &objects() const {
323 return m_objects;
324 }
325
326 /** Pops objects of type T from the stack until no more objects can be popped.
327 @param st stack.
328 */
329 virtual void construct(ast_stack &st) {
330 for(;;) {
331 //if the stack is empty
332 if (st.empty()) break;
333
334 //get the node
335 ast_node *node = st.back();
336
337 //get the object
338 T *obj = dynamic_cast<T *>(node);
339
340 //if the object was not not of the appropriate type,
341 //end the list parsing
342 if (!obj) return;
343
344 //remove the node from the stack
345 st.pop_back();
346
347 //insert the object in the list, in reverse order
348 m_objects.push_front(obj);
349
350 //set the object's parent
351 obj->m_parent = ast_member::container();
352 }
353 }
354
355private:
356 //objects
357 container m_objects;
358
359 //deletes the objects of this list.
360 void _clear() {
361 while (!m_objects.empty()) {
362 delete m_objects.back();
363 m_objects.pop_back();
364 }
365 }
366
367 //duplicate the given list.
368 void _dup(const ast_list<T> &src) {
369 for(typename container::const_iterator it = src.m_objects.begin();
370 it != src.m_objects.end();
371 ++it)
372 {
373 T *obj = new T(*it);
374 m_objects.push_back(obj);
375 obj->m_parent = ast_member::container();
376 }
377 }
378};
379
380
381/** AST function which creates an object of type T
382 and pushes it to the node stack.
383 */
384template <class T> class ast {
385public:
386 /** constructor.
387 @param r rule to attach the AST function to.
388 */
389 ast(rule &r) {
390 r.set_parse_proc(&_parse_proc);
391 }
392
393private:
394 //parse proc
395 static void _parse_proc(const pos &b, const pos &e, void *d) {
396 ast_stack *st = reinterpret_cast<ast_stack *>(d);
397 T *obj = new T;
398 obj->m_begin = b;
399 obj->m_end = e;
400 obj->construct(*st);
401 st->push_back(obj);
402 }
403};
404
405
406/** parses the given input.
407 @param i input.
408 @param g root rule of grammar.
409 @param el list of errors.
410 @param ud user data, passed to the parse procedures.
411 @return pointer to ast node created, or null if there was an error.
412 The return object must be deleted by the caller.
413 */
414ast_node *parse(input &i, rule &g, error_list &el, void* ud);
415
416
417/** parses the given input.
418 @param i input.
419 @param g root rule of grammar.
420 @param el list of errors.
421 @param ast result pointer to created ast.
422 @param ud user data, passed to the parse procedures.
423 @return true on success, false on error.
424 */
425template <class T> bool parse(input &i, rule &g, error_list &el, T *&ast, void* ud = nullptr) {
426 ast_node *node = parse(i, g, el, ud);
427 ast = dynamic_cast<T *>(node);
428 if (ast) return true;
429 delete node;
430 return false;
431}
432
433
434} //namespace parserlib
435
436
437#endif //AST_HPP