diff options
author | Li Jin <dragon-fly@qq.com> | 2019-09-12 16:12:20 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2019-09-12 16:12:20 +0800 |
commit | 50353c1456324e7bd3c130fceaf400aed7880a41 (patch) | |
tree | 0afe5823040dc9fc9ab39a9d7f4af647c061d7c1 /MoonParser/ast.hpp | |
parent | 4e6f4e8124316866a08f9ddf3322fde87abc3c21 (diff) | |
download | yuescript-50353c1456324e7bd3c130fceaf400aed7880a41.tar.gz yuescript-50353c1456324e7bd3c130fceaf400aed7880a41.tar.bz2 yuescript-50353c1456324e7bd3c130fceaf400aed7880a41.zip |
spec/assign.moon and spec/bubbling.moon compiled
Diffstat (limited to 'MoonParser/ast.hpp')
-rw-r--r-- | MoonParser/ast.hpp | 471 |
1 files changed, 196 insertions, 275 deletions
diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp index 4d52dfc..982eea8 100644 --- a/MoonParser/ast.hpp +++ b/MoonParser/ast.hpp | |||
@@ -13,14 +13,14 @@ namespace parserlib { | |||
13 | 13 | ||
14 | 14 | ||
15 | class ast_node; | 15 | class ast_node; |
16 | template <class T, bool OPT> class ast_ptr; | 16 | template <class T, bool OPT, bool MEM> class ast_ptr; |
17 | template <class T> class ast_list; | 17 | template <class T> class ast_list; |
18 | template <class T> class ast; | 18 | template <class T> class ast; |
19 | 19 | ||
20 | 20 | ||
21 | /** type of AST node stack. | 21 | /** type of AST node stack. |
22 | */ | 22 | */ |
23 | typedef std::vector<ast_node *> ast_stack; | 23 | typedef std::vector<ast_node*> ast_stack; |
24 | 24 | ||
25 | extern int ast_type_id; | 25 | extern int ast_type_id; |
26 | 26 | ||
@@ -41,33 +41,24 @@ enum class traversal { | |||
41 | */ | 41 | */ |
42 | class ast_node : public input_range { | 42 | class ast_node : public input_range { |
43 | public: | 43 | public: |
44 | ///constructor. | 44 | ast_node() : _ref(0) {} |
45 | ast_node() : m_parent(nullptr) {} | 45 | |
46 | 46 | void retain() { | |
47 | /** copy constructor. | 47 | ++_ref; |
48 | @param n source object. | 48 | } |
49 | */ | 49 | |
50 | ast_node(const ast_node &n) : m_parent(nullptr) {} | 50 | void release() { |
51 | 51 | --_ref; | |
52 | ///destructor. | 52 | if (_ref == 0) { |
53 | virtual ~ast_node() {} | 53 | delete this; |
54 | 54 | } | |
55 | /** assignment operator. | 55 | } |
56 | @param n source object. | 56 | |
57 | @return reference to this. | ||
58 | */ | ||
59 | ast_node &operator = (const ast_node &n) { return *this; } | ||
60 | |||
61 | /** get the parent node. | ||
62 | @return the parent node, if there is one. | ||
63 | */ | ||
64 | ast_node *parent() const { return m_parent; } | ||
65 | |||
66 | /** interface for filling the contents of the node | 57 | /** interface for filling the contents of the node |
67 | from a node stack. | 58 | from a node stack. |
68 | @param st stack. | 59 | @param st stack. |
69 | */ | 60 | */ |
70 | virtual void construct(ast_stack &st) {} | 61 | virtual void construct(ast_stack& st) {} |
71 | 62 | ||
72 | /** interface for visiting AST tree use. | 63 | /** interface for visiting AST tree use. |
73 | */ | 64 | */ |
@@ -81,7 +72,11 @@ public: | |||
81 | 72 | ||
82 | virtual ast_node* getChild(int) const { return nullptr; } | 73 | virtual ast_node* getChild(int) const { return nullptr; } |
83 | 74 | ||
84 | virtual int getChildCount() const { return 0; } | 75 | virtual size_t getChildCount() const { return 0; } |
76 | |||
77 | virtual ast_node* getFirstChild() const { return nullptr; } | ||
78 | |||
79 | virtual ast_node* getLastChild() const { return nullptr; } | ||
85 | 80 | ||
86 | virtual size_t getId() const { return "ast_node"_id; } | 81 | virtual size_t getId() const { return "ast_node"_id; } |
87 | 82 | ||
@@ -89,10 +84,8 @@ public: | |||
89 | 84 | ||
90 | virtual int get_type() { return ast_type<ast_node>(); } | 85 | virtual int get_type() { return ast_type<ast_node>(); } |
91 | private: | 86 | private: |
92 | //parent | 87 | int _ref; |
93 | ast_node *m_parent; | 88 | template <class T, bool OPT, bool MEM> friend class ast_ptr; |
94 | |||
95 | template <class T, bool OPT> friend class ast_ptr; | ||
96 | template <class ...Args> friend class ast_choice; | 89 | template <class ...Args> friend class ast_choice; |
97 | template <class T> friend class ast_list; | 90 | template <class T> friend class ast_list; |
98 | template <class T> friend class ast; | 91 | template <class T> friend class ast; |
@@ -117,7 +110,7 @@ class ast_member; | |||
117 | 110 | ||
118 | /** type of ast member vector. | 111 | /** type of ast member vector. |
119 | */ | 112 | */ |
120 | typedef std::vector<ast_member *> ast_member_vector; | 113 | typedef std::vector<ast_member*> ast_member_vector; |
121 | 114 | ||
122 | 115 | ||
123 | /** base class for AST nodes with children. | 116 | /** base class for AST nodes with children. |
@@ -128,25 +121,10 @@ public: | |||
128 | */ | 121 | */ |
129 | ast_container(); | 122 | ast_container(); |
130 | 123 | ||
131 | /** sets the container under construction to be this. | ||
132 | Members are not copied. | ||
133 | @param src source object. | ||
134 | */ | ||
135 | ast_container(const ast_container &src); | ||
136 | |||
137 | /** the assignment operator. | ||
138 | The members are not copied. | ||
139 | @param src source object. | ||
140 | @return reference to this. | ||
141 | */ | ||
142 | ast_container &operator = (const ast_container &src) { | ||
143 | return *this; | ||
144 | } | ||
145 | |||
146 | /** returns the vector of AST members. | 124 | /** returns the vector of AST members. |
147 | @return the vector of AST members. | 125 | @return the vector of AST members. |
148 | */ | 126 | */ |
149 | const ast_member_vector &members() const { | 127 | const ast_member_vector& members() const { |
150 | return m_members; | 128 | return m_members; |
151 | } | 129 | } |
152 | 130 | ||
@@ -155,7 +133,7 @@ public: | |||
155 | from a node stack. | 133 | from a node stack. |
156 | @param st stack. | 134 | @param st stack. |
157 | */ | 135 | */ |
158 | virtual void construct(ast_stack &st) override; | 136 | virtual void construct(ast_stack& st) override; |
159 | 137 | ||
160 | virtual ast_node* getByPath(std::initializer_list<std::size_t> paths) override; | 138 | virtual ast_node* getByPath(std::initializer_list<std::size_t> paths) override; |
161 | 139 | ||
@@ -167,7 +145,11 @@ public: | |||
167 | 145 | ||
168 | virtual ast_node* getChild(int index) const override; | 146 | virtual ast_node* getChild(int index) const override; |
169 | 147 | ||
170 | virtual int getChildCount() const override; | 148 | virtual size_t getChildCount() const override; |
149 | |||
150 | virtual ast_node* getFirstChild() const override; | ||
151 | |||
152 | virtual ast_node* getLastChild() const override; | ||
171 | 153 | ||
172 | virtual size_t getId() const override { return "ast_container"_id; } | 154 | virtual size_t getId() const override { return "ast_container"_id; } |
173 | 155 | ||
@@ -185,58 +167,76 @@ class ast_member { | |||
185 | public: | 167 | public: |
186 | /** automatically registers itself to the container under construction. | 168 | /** automatically registers itself to the container under construction. |
187 | */ | 169 | */ |
188 | ast_member() { _init(); } | 170 | ast_member(bool is_member) { |
171 | if (is_member) add_to_owner(); | ||
172 | } | ||
189 | 173 | ||
190 | /** automatically registers itself to the container under construction. | 174 | virtual ~ast_member() {} |
191 | @param src source object. | ||
192 | */ | ||
193 | ast_member(const ast_member &src) { _init(); } | ||
194 | |||
195 | /** the assignment operator. | ||
196 | @param src source object. | ||
197 | @return reference to this. | ||
198 | */ | ||
199 | ast_member &operator = (const ast_member &src) { | ||
200 | return *this; | ||
201 | } | ||
202 | |||
203 | /** returns the container this belongs to. | ||
204 | @return the container this belongs to. | ||
205 | */ | ||
206 | ast_container *container() const { return m_container; } | ||
207 | 175 | ||
208 | /** interface for filling the the member from a node stack. | 176 | /** interface for filling the the member from a node stack. |
209 | @param st stack. | 177 | @param st stack. |
210 | */ | 178 | */ |
211 | virtual void construct(ast_stack &st) = 0; | 179 | virtual void construct(ast_stack& st) = 0; |
180 | |||
181 | virtual bool accept(ast_node* node) = 0; | ||
212 | 182 | ||
213 | virtual int get_type() { return ast_type<ast_member>(); } | 183 | virtual int get_type() { return ast_type<ast_member>(); } |
214 | private: | 184 | private: |
215 | //the container this belongs to. | ||
216 | ast_container *m_container; | ||
217 | |||
218 | //register the AST member to the current container. | 185 | //register the AST member to the current container. |
219 | void _init(); | 186 | void add_to_owner(); |
220 | }; | 187 | }; |
221 | 188 | ||
222 | template<class T> | 189 | template<class T> |
223 | T* ast_cast(ast_member *member) { | 190 | T* ast_cast(ast_member* member) { |
224 | return member && ast_type<T>() == member->get_type() ? static_cast<T*>(member) : nullptr; | 191 | return member && ast_type<T>() == member->get_type() ? static_cast<T*>(member) : nullptr; |
225 | } | 192 | } |
226 | 193 | ||
227 | class _ast_ptr : public ast_member { | 194 | class _ast_ptr : public ast_member { |
228 | public: | 195 | public: |
229 | _ast_ptr(ast_node *node): m_ptr(node) {} | 196 | _ast_ptr(ast_node* node, bool is_member) : ast_member(is_member), m_ptr(node) { |
197 | if (node) node->retain(); | ||
198 | } | ||
199 | |||
200 | virtual ~_ast_ptr() { | ||
201 | if (m_ptr) { | ||
202 | m_ptr->release(); | ||
203 | m_ptr = nullptr; | ||
204 | } | ||
205 | } | ||
230 | 206 | ||
231 | ast_node* get() const { | 207 | ast_node* get() const { |
232 | return m_ptr; | 208 | return m_ptr; |
233 | } | 209 | } |
234 | 210 | ||
211 | template <class T> | ||
212 | T* as() const { | ||
213 | return ast_cast<T>(m_ptr); | ||
214 | } | ||
215 | |||
216 | template <class T> | ||
217 | T* to() const { | ||
218 | assert(m_ptr->getId() == ast_type<T>()); | ||
219 | return static_cast<T*>(m_ptr); | ||
220 | } | ||
221 | |||
222 | void set(ast_node* node) { | ||
223 | if (node == m_ptr) return; | ||
224 | else if (!node) { | ||
225 | if (m_ptr) m_ptr->release(); | ||
226 | m_ptr = nullptr; | ||
227 | } | ||
228 | else if (accept(node)) { | ||
229 | if (m_ptr) m_ptr->release(); | ||
230 | m_ptr = node; | ||
231 | node->retain(); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | virtual int get_type() override { | 235 | virtual int get_type() override { |
236 | return ast_type<_ast_ptr>(); | 236 | return ast_type<_ast_ptr>(); |
237 | } | 237 | } |
238 | protected: | 238 | protected: |
239 | ast_node *m_ptr; | 239 | ast_node* m_ptr; |
240 | }; | 240 | }; |
241 | 241 | ||
242 | /** pointer to an AST object. | 242 | /** pointer to an AST object. |
@@ -245,75 +245,37 @@ protected: | |||
245 | @tparam T type of object to control. | 245 | @tparam T type of object to control. |
246 | @tparam OPT if true, the object becomes optional. | 246 | @tparam OPT if true, the object becomes optional. |
247 | */ | 247 | */ |
248 | template <class T, bool OPT = false> class ast_ptr : public _ast_ptr { | 248 | template <class T, bool OPT = false, bool MEM = true> class ast_ptr : public _ast_ptr { |
249 | public: | 249 | public: |
250 | /** the default constructor. | 250 | ast_ptr(T* node = nullptr) : _ast_ptr(node, MEM) {} |
251 | @param obj object. | ||
252 | */ | ||
253 | ast_ptr(T *obj = nullptr) : _ast_ptr(obj) { | ||
254 | _set_parent(); | ||
255 | } | ||
256 | |||
257 | /** the copy constructor. | ||
258 | It duplicates the underlying object. | ||
259 | @param src source object. | ||
260 | */ | ||
261 | ast_ptr(const ast_ptr<T, OPT> &src) : | ||
262 | _ast_ptr(src.m_ptr ? new T(*src.m_ptr) : nullptr) | ||
263 | { | ||
264 | _set_parent(); | ||
265 | } | ||
266 | 251 | ||
267 | /** deletes the underlying object. | 252 | ast_ptr(const ast_ptr<T, OPT, MEM>& other) : _ast_ptr(other.get(), MEM) {} |
268 | */ | ||
269 | ~ast_ptr() { | ||
270 | delete m_ptr; | ||
271 | } | ||
272 | 253 | ||
273 | /** copies the given object. | 254 | ast_ptr<T, OPT, MEM>& operator=(const ast_ptr<T, OPT, MEM>& other) { |
274 | The old object is deleted. | 255 | set(other.get()); |
275 | @param obj new object. | 256 | return *this; |
276 | @return reference to this. | 257 | } |
277 | */ | ||
278 | ast_ptr<T, OPT> &operator = (const T *obj) { | ||
279 | delete m_ptr; | ||
280 | m_ptr = obj ? new T(*obj) : nullptr; | ||
281 | _set_parent(); | ||
282 | return *this; | ||
283 | } | ||
284 | |||
285 | /** copies the underlying object. | ||
286 | The old object is deleted. | ||
287 | @param src source object. | ||
288 | @return reference to this. | ||
289 | */ | ||
290 | ast_ptr<T, OPT> &operator = (const ast_ptr<T, OPT> &src) { | ||
291 | delete m_ptr; | ||
292 | m_ptr = src.m_ptr ? new T(*src.m_ptr) : nullptr; | ||
293 | _set_parent(); | ||
294 | return *this; | ||
295 | } | ||
296 | 258 | ||
297 | /** gets the underlying ptr value. | 259 | /** gets the underlying ptr value. |
298 | @return the underlying ptr value. | 260 | @return the underlying ptr value. |
299 | */ | 261 | */ |
300 | T *get() const { | 262 | T* get() const { |
301 | return static_cast<T*>(m_ptr); | 263 | return static_cast<T*>(m_ptr); |
302 | } | 264 | } |
303 | 265 | ||
304 | /** auto conversion to the underlying object ptr. | 266 | /** auto conversion to the underlying object ptr. |
305 | @return the underlying ptr value. | 267 | @return the underlying ptr value. |
306 | */ | 268 | */ |
307 | operator T *() const { | 269 | operator T*() const { |
308 | return static_cast<T*>(m_ptr); | 270 | return static_cast<T*>(m_ptr); |
309 | } | 271 | } |
310 | 272 | ||
311 | /** member access. | 273 | /** member access. |
312 | @return the underlying ptr value. | 274 | @return the underlying ptr value. |
313 | */ | 275 | */ |
314 | T *operator ->() const { | 276 | T* operator->() const { |
315 | assert(m_ptr); | 277 | assert(m_ptr); |
316 | return m_ptr; | 278 | return static_cast<T*>(m_ptr); |
317 | } | 279 | } |
318 | 280 | ||
319 | /** Pops a node from the stack. | 281 | /** Pops a node from the stack. |
@@ -321,118 +283,120 @@ public: | |||
321 | @exception std::logic_error thrown if the node is not of the appropriate type; | 283 | @exception std::logic_error thrown if the node is not of the appropriate type; |
322 | thrown only if OPT == false or if the stack is empty. | 284 | thrown only if OPT == false or if the stack is empty. |
323 | */ | 285 | */ |
324 | virtual void construct(ast_stack &st) { | 286 | virtual void construct(ast_stack& st) override { |
325 | //check the stack node | 287 | //check the stack node |
326 | if (st.empty()) { | 288 | if (st.empty()) { |
327 | if (OPT) return; | 289 | if (OPT) return; |
328 | else throw std::logic_error("invalid AST stack"); | 290 | else throw std::logic_error("invalid AST stack"); |
329 | } | 291 | } |
330 | 292 | ||
331 | //get the node | 293 | ast_node* node = st.back(); |
332 | ast_node *node = st.back(); | 294 | |
333 | 295 | if (!ast_ptr::accept(node)) { | |
334 | //get the object | 296 | //if the object is optional, simply return |
335 | T *obj = std::is_same<T, ast_node>() ? static_cast<T*>(node) : ast_cast<T>(node); | 297 | if (OPT) { |
336 | 298 | return; | |
337 | //if the object is optional, simply return | 299 | } else { //else if the object is mandatory, throw an exception |
338 | if (OPT) { | 300 | throw std::logic_error("invalid AST node"); |
339 | if (!obj) return; | 301 | } |
340 | } | 302 | } |
341 | 303 | ||
342 | //else if the object is mandatory, throw an exception | ||
343 | else { | ||
344 | if (!obj) throw std::logic_error("invalid AST node"); | ||
345 | } | ||
346 | |||
347 | //pop the node from the stack | ||
348 | st.pop_back(); | 304 | st.pop_back(); |
349 | 305 | ||
350 | //set the new object | 306 | m_ptr = node; |
351 | delete m_ptr; | 307 | node->retain(); |
352 | m_ptr = obj; | ||
353 | _set_parent(); | ||
354 | } | 308 | } |
355 | private: | 309 | private: |
356 | //set parent of object | 310 | virtual bool accept(ast_node* node) override { |
357 | void _set_parent() { | 311 | return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); |
358 | if (m_ptr) m_ptr->m_parent = container(); | 312 | } |
359 | } | ||
360 | }; | 313 | }; |
361 | 314 | ||
315 | template<class T> | ||
316 | inline ast_ptr<T, false, false> new_ptr() { | ||
317 | return ast_ptr<T, false, false>(new T); | ||
318 | } | ||
319 | |||
362 | template <class ...Args> class ast_choice : public _ast_ptr { | 320 | template <class ...Args> class ast_choice : public _ast_ptr { |
363 | public: | 321 | public: |
364 | ast_choice(ast_node *obj = nullptr) : _ast_ptr(obj) { | 322 | ast_choice() : _ast_ptr(nullptr, true) {} |
365 | _set_parent(); | ||
366 | } | ||
367 | |||
368 | ast_choice(const ast_choice<Args...> &src) : | ||
369 | _ast_ptr(src.m_ptr ? new ast_node(*src.m_ptr) : nullptr) | ||
370 | { | ||
371 | _set_parent(); | ||
372 | } | ||
373 | 323 | ||
374 | ~ast_choice() { | 324 | ast_choice(const ast_choice<Args...>& other) : _ast_ptr(other.get(), true) {} |
375 | delete m_ptr; | ||
376 | } | ||
377 | |||
378 | ast_choice<Args...> &operator = (const ast_node *obj) { | ||
379 | delete m_ptr; | ||
380 | m_ptr = obj ? new ast_node(*obj) : nullptr; | ||
381 | _set_parent(); | ||
382 | return *this; | ||
383 | } | ||
384 | 325 | ||
385 | ast_choice<Args...> &operator = (const ast_choice<Args...> &src) { | 326 | ast_choice<Args...>& operator=(const ast_choice<Args...>& other) { |
386 | delete m_ptr; | 327 | set(other.get()); |
387 | m_ptr = src.m_ptr ? new ast_node(*src.m_ptr) : nullptr; | 328 | return *this; |
388 | _set_parent(); | 329 | } |
389 | return *this; | ||
390 | } | ||
391 | 330 | ||
392 | operator ast_node *() const { | 331 | operator ast_node*() const { |
393 | return m_ptr; | 332 | return m_ptr; |
394 | } | 333 | } |
395 | 334 | ||
396 | ast_node *operator ->() const { | 335 | ast_node* operator->() const { |
397 | assert(m_ptr); | 336 | assert(m_ptr); |
398 | return m_ptr; | 337 | return m_ptr; |
399 | } | 338 | } |
400 | 339 | ||
401 | virtual void construct(ast_stack &st) { | 340 | virtual void construct(ast_stack& st) override { |
402 | if (st.empty()) { | 341 | if (st.empty()) { |
403 | throw std::logic_error("invalid AST stack"); | 342 | throw std::logic_error("invalid AST stack"); |
404 | } | 343 | } |
405 | 344 | ||
406 | ast_node *node = st.back(); | 345 | ast_node* node = st.back(); |
407 | ast_node *obj = nullptr; | ||
408 | |||
409 | using swallow = bool[]; | ||
410 | (void)swallow{obj || (obj = std::is_same<Args, ast_node>() ? node : ast_cast<Args>(node))...}; | ||
411 | 346 | ||
412 | if (!obj) throw std::logic_error("invalid AST node"); | 347 | if (!ast_choice::accept(node)) throw std::logic_error("invalid AST node"); |
413 | 348 | ||
414 | st.pop_back(); | 349 | st.pop_back(); |
415 | 350 | ||
416 | delete m_ptr; | 351 | m_ptr = node; |
417 | m_ptr = obj; | 352 | node->retain(); |
418 | _set_parent(); | ||
419 | } | 353 | } |
420 | private: | 354 | private: |
421 | void _set_parent() { | 355 | virtual bool accept(ast_node* node) override { |
422 | if (m_ptr) m_ptr->m_parent = container(); | 356 | if (!node) return false; |
423 | } | 357 | using swallow = bool[]; |
358 | bool* result = nullptr; | ||
359 | (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; | ||
360 | return result; | ||
361 | } | ||
424 | }; | 362 | }; |
425 | 363 | ||
426 | class _ast_list : public ast_member { | 364 | class _ast_list : public ast_member { |
427 | public: | 365 | public: |
428 | ///list type. | 366 | typedef std::list<ast_node*> container; |
429 | typedef std::list<ast_node *> container; | ||
430 | 367 | ||
431 | virtual int get_type() override { return ast_type<_ast_list>(); } | 368 | _ast_list() : ast_member(true) {} |
369 | |||
370 | ~_ast_list() { | ||
371 | clear(); | ||
372 | } | ||
373 | |||
374 | void add(ast_node* node) { | ||
375 | if (accept(node)) { | ||
376 | m_objects.push_back(node); | ||
377 | node->retain(); | ||
378 | } | ||
379 | } | ||
432 | 380 | ||
433 | const container &objects() const { | 381 | const container& objects() const { |
434 | return m_objects; | 382 | return m_objects; |
435 | } | 383 | } |
384 | |||
385 | void clear() { | ||
386 | for(ast_node* obj : m_objects) { | ||
387 | if (obj) obj->release(); | ||
388 | } | ||
389 | m_objects.clear(); | ||
390 | } | ||
391 | |||
392 | void dup(const _ast_list& src) { | ||
393 | for(ast_node* obj : src.m_objects) { | ||
394 | m_objects.push_back(obj); | ||
395 | obj->retain(); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | virtual int get_type() override { return ast_type<_ast_list>(); } | ||
436 | protected: | 400 | protected: |
437 | container m_objects; | 401 | container m_objects; |
438 | }; | 402 | }; |
@@ -447,86 +411,39 @@ public: | |||
447 | ///the default constructor. | 411 | ///the default constructor. |
448 | ast_list() {} | 412 | ast_list() {} |
449 | 413 | ||
450 | /** duplicates the objects of the given list. | 414 | ast_list(const ast_list<T>& other) { |
451 | @param src source object. | 415 | clear(); |
452 | */ | 416 | dup(other); |
453 | ast_list(const ast_list<T> &src) { | 417 | } |
454 | _dup(src); | ||
455 | } | ||
456 | |||
457 | /** deletes the objects. | ||
458 | */ | ||
459 | ~ast_list() { | ||
460 | _clear(); | ||
461 | } | ||
462 | |||
463 | /** deletes the objects of this list and duplicates the given one. | ||
464 | @param src source object. | ||
465 | @return reference to this. | ||
466 | */ | ||
467 | ast_list<T> &operator = (const ast_list<T> &src) { | ||
468 | if (&src != this) { | ||
469 | _clear(); | ||
470 | _dup(src); | ||
471 | } | ||
472 | return *this; | ||
473 | } | ||
474 | 418 | ||
475 | /** returns the container of objects. | 419 | ast_list<T>& operator=(const ast_list<T>& other) { |
476 | @return the container of objects. | 420 | clear(); |
477 | */ | 421 | dup(other); |
478 | const container &objects() const { | 422 | return *this; |
479 | return m_objects; | 423 | } |
480 | } | ||
481 | 424 | ||
482 | /** Pops objects of type T from the stack until no more objects can be popped. | 425 | /** Pops objects of type T from the stack until no more objects can be popped. |
483 | @param st stack. | 426 | @param st stack. |
484 | */ | 427 | */ |
485 | virtual void construct(ast_stack &st) override { | 428 | virtual void construct(ast_stack &st) override { |
486 | for(;;) { | 429 | while (!st.empty()) { |
487 | //if the stack is empty | 430 | ast_node* node = st.back(); |
488 | if (st.empty()) break; | 431 | |
489 | |||
490 | //get the node | ||
491 | ast_node *node = st.back(); | ||
492 | |||
493 | //get the object | ||
494 | T *obj = std::is_same<T, ast_node>() ? static_cast<T*>(node) : ast_cast<T>(node); | ||
495 | |||
496 | //if the object was not not of the appropriate type, | 432 | //if the object was not not of the appropriate type, |
497 | //end the list parsing | 433 | //end the list parsing |
498 | if (!obj) return; | 434 | if (!ast_list::accept(node)) return; |
499 | 435 | ||
500 | //remove the node from the stack | ||
501 | st.pop_back(); | 436 | st.pop_back(); |
502 | 437 | ||
503 | //insert the object in the list, in reverse order | 438 | //insert the object in the list, in reverse order |
504 | m_objects.push_front(obj); | 439 | m_objects.push_front(node); |
505 | 440 | node->retain(); | |
506 | //set the object's parent | ||
507 | obj->m_parent = ast_member::container(); | ||
508 | } | 441 | } |
509 | } | 442 | } |
510 | private: | 443 | private: |
511 | //deletes the objects of this list. | 444 | virtual bool accept(ast_node* node) override { |
512 | void _clear() { | 445 | return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); |
513 | while (!m_objects.empty()) { | 446 | } |
514 | delete m_objects.back(); | ||
515 | m_objects.pop_back(); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | //duplicate the given list. | ||
520 | void _dup(const ast_list<T> &src) { | ||
521 | for(typename container::const_iterator it = src.m_objects.begin(); | ||
522 | it != src.m_objects.end(); | ||
523 | ++it) | ||
524 | { | ||
525 | T *obj = new T(*it); | ||
526 | m_objects.push_back(obj); | ||
527 | obj->m_parent = ast_member::container(); | ||
528 | } | ||
529 | } | ||
530 | }; | 447 | }; |
531 | 448 | ||
532 | 449 | ||
@@ -538,15 +455,15 @@ public: | |||
538 | /** constructor. | 455 | /** constructor. |
539 | @param r rule to attach the AST function to. | 456 | @param r rule to attach the AST function to. |
540 | */ | 457 | */ |
541 | ast(rule &r) { | 458 | ast(rule& r) { |
542 | r.set_parse_proc(&_parse_proc); | 459 | r.set_parse_proc(&_parse_proc); |
543 | } | 460 | } |
544 | 461 | ||
545 | private: | 462 | private: |
546 | //parse proc | 463 | //parse proc |
547 | static void _parse_proc(const pos &b, const pos &e, void *d) { | 464 | static void _parse_proc(const pos& b, const pos& e, void* d) { |
548 | ast_stack *st = reinterpret_cast<ast_stack *>(d); | 465 | ast_stack* st = reinterpret_cast<ast_stack*>(d); |
549 | T *obj = new T; | 466 | T* obj = new T; |
550 | obj->m_begin = b; | 467 | obj->m_begin = b; |
551 | obj->m_end = e; | 468 | obj->m_end = e; |
552 | obj->construct(*st); | 469 | obj->construct(*st); |
@@ -563,23 +480,27 @@ private: | |||
563 | @return pointer to ast node created, or null if there was an error. | 480 | @return pointer to ast node created, or null if there was an error. |
564 | The return object must be deleted by the caller. | 481 | The return object must be deleted by the caller. |
565 | */ | 482 | */ |
566 | ast_node *parse(input &i, rule &g, error_list &el, void* ud); | 483 | ast_node* _parse(input &i, rule &g, error_list &el, void* ud); |
567 | 484 | ||
568 | 485 | ||
569 | /** parses the given input. | 486 | /** parses the given input. |
570 | @param i input. | 487 | @param i input. |
571 | @param g root rule of grammar. | 488 | @param g root rule of grammar. |
572 | @param el list of errors. | 489 | @param el list of errors. |
573 | @param ast result pointer to created ast. | ||
574 | @param ud user data, passed to the parse procedures. | 490 | @param ud user data, passed to the parse procedures. |
575 | @return true on success, false on error. | 491 | @return ast nodes. |
576 | */ | 492 | */ |
577 | template <class T> bool parse(input &i, rule &g, error_list &el, T *&ast, void* ud = nullptr) { | 493 | template <class T> ast_ptr<T, false, false> parse(input &i, rule &g, error_list &el, void* ud = nullptr) { |
578 | ast_node *node = parse(i, g, el, ud); | 494 | ast_node* node = _parse(i, g, el, ud); |
579 | ast = ast_cast<T>(node); | 495 | T* ast = ast_cast<T>(node); |
580 | if (ast) return true; | 496 | ast_ptr<T, false, false> ptr; |
581 | delete node; | 497 | if (ast) { |
582 | return false; | 498 | ast_stack st{node}; |
499 | ptr.construct(st); | ||
500 | } else if (node) { | ||
501 | delete node; | ||
502 | } | ||
503 | return ptr; | ||
583 | } | 504 | } |
584 | 505 | ||
585 | 506 | ||