aboutsummaryrefslogtreecommitdiff
path: root/src/MoonP/ast.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/MoonP/ast.hpp')
-rw-r--r--src/MoonP/ast.hpp431
1 files changed, 216 insertions, 215 deletions
diff --git a/src/MoonP/ast.hpp b/src/MoonP/ast.hpp
index 38141e2..8bcfc21 100644
--- a/src/MoonP/ast.hpp
+++ b/src/MoonP/ast.hpp
@@ -1,12 +1,13 @@
1/* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li 1/* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li
2All rights reserved. 2All rights reserved.
3 3
4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 5
6 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 7
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 8Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
10THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
10 11
11#pragma once 12#pragma once
12 13
@@ -28,7 +29,7 @@ template <class T> class ast;
28 29
29 30
30/** type of AST node stack. 31/** type of AST node stack.
31 */ 32*/
32typedef std::vector<ast_node*> ast_stack; 33typedef std::vector<ast_node*> ast_stack;
33typedef std::list<ast_node*> node_container; 34typedef std::list<ast_node*> node_container;
34 35
@@ -47,7 +48,7 @@ enum class traversal {
47}; 48};
48 49
49/** Base class for AST nodes. 50/** Base class for AST nodes.
50 */ 51*/
51class ast_node : public input_range { 52class ast_node : public input_range {
52public: 53public:
53 ast_node() : _ref(0) {} 54 ast_node() : _ref(0) {}
@@ -63,14 +64,14 @@ public:
63 } 64 }
64 } 65 }
65 66
66 /** interface for filling the contents of the node 67 /** interface for filling the contents of the node
67 from a node stack. 68 from a node stack.
68 @param st stack. 69 @param st stack.
69 */ 70 */
70 virtual void construct(ast_stack&) {} 71 virtual void construct(ast_stack&) {}
71 72
72 /** interface for visiting AST tree use. 73 /** interface for visiting AST tree use.
73 */ 74 */
74 virtual traversal traverse(const std::function<traversal (ast_node*)>& func); 75 virtual traversal traverse(const std::function<traversal (ast_node*)>& func);
75 76
76 template <typename... Ts> 77 template <typename... Ts>
@@ -128,12 +129,12 @@ bool ast_is(ast_node* node) {
128class ast_member; 129class ast_member;
129 130
130/** type of ast member vector. 131/** type of ast member vector.
131 */ 132*/
132typedef std::vector<ast_member*> ast_member_vector; 133typedef std::vector<ast_member*> ast_member_vector;
133 134
134 135
135/** base class for AST nodes with children. 136/** base class for AST nodes with children.
136 */ 137*/
137class ast_container : public ast_node { 138class ast_container : public ast_node {
138public: 139public:
139 void add_members(std::initializer_list<ast_member*> members) { 140 void add_members(std::initializer_list<ast_member*> members) {
@@ -142,42 +143,42 @@ public:
142 } 143 }
143 } 144 }
144 145
145 /** returns the vector of AST members. 146 /** returns the vector of AST members.
146 @return the vector of AST members. 147 @return the vector of AST members.
147 */ 148 */
148 const ast_member_vector& members() const { 149 const ast_member_vector& members() const {
149 return m_members; 150 return m_members;
150 } 151 }
151 152
152 /** Asks all members to construct themselves from the stack. 153 /** Asks all members to construct themselves from the stack.
153 The members are asked to construct themselves in reverse order. 154 The members are asked to construct themselves in reverse order.
154 from a node stack. 155 from a node stack.
155 @param st stack. 156 @param st stack.
156 */ 157 */
157 virtual void construct(ast_stack& st) override; 158 virtual void construct(ast_stack& st) override;
158 159
159 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override; 160 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override;
160 161
161 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override; 162 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override;
162private: 163private:
163 ast_member_vector m_members; 164 ast_member_vector m_members;
164 165
165 friend class ast_member; 166 friend class ast_member;
166}; 167};
167 168
168 169
169/** Base class for children of ast_container. 170/** Base class for children of ast_container.
170 */ 171*/
171class ast_member { 172class ast_member {
172public: 173public:
173 virtual ~ast_member() {} 174 virtual ~ast_member() {}
174 175
175 /** interface for filling the the member from a node stack. 176 /** interface for filling the the member from a node stack.
176 @param st stack. 177 @param st stack.
177 */ 178 */
178 virtual void construct(ast_stack& st) = 0; 179 virtual void construct(ast_stack& st) = 0;
179 180
180 virtual bool accept(ast_node* node) = 0; 181 virtual bool accept(ast_node* node) = 0;
181 182
182 virtual int get_type() { return ast_type<ast_member>(); } 183 virtual int get_type() { return ast_type<ast_member>(); }
183}; 184};
@@ -193,12 +194,12 @@ public:
193 if (node) node->retain(); 194 if (node) node->retain();
194 } 195 }
195 196
196 virtual ~_ast_ptr() { 197 virtual ~_ast_ptr() {
197 if (m_ptr) { 198 if (m_ptr) {
198 m_ptr->release(); 199 m_ptr->release();
199 m_ptr = nullptr; 200 m_ptr = nullptr;
200 } 201 }
201 } 202 }
202 203
203 ast_node* get() const { 204 ast_node* get() const {
204 return m_ptr; 205 return m_ptr;
@@ -242,109 +243,109 @@ protected:
242}; 243};
243 244
244/** pointer to an AST object. 245/** pointer to an AST object.
245 It assumes ownership of the object. 246 It assumes ownership of the object.
246 It pops an object of the given type from the stack. 247 It pops an object of the given type from the stack.
247 @tparam Required if true, the object is required. 248 @tparam Required if true, the object is required.
248 @tparam T type of object to control. 249 @tparam T type of object to control.
249 */ 250*/
250template <bool Required, class T> class ast_ptr : public _ast_ptr { 251template <bool Required, class T> class ast_ptr : public _ast_ptr {
251public: 252public:
252 ast_ptr(T* node = nullptr) : _ast_ptr(node) {} 253 ast_ptr(T* node = nullptr) : _ast_ptr(node) {}
253 254
254 ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} 255 ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {}
255 256
256 ast_ptr& operator=(const ast_ptr& other) { 257 ast_ptr& operator=(const ast_ptr& other) {
257 set(other.get()); 258 set(other.get());
258 return *this; 259 return *this;
259 } 260 }
260 261
261 /** gets the underlying ptr value. 262 /** gets the underlying ptr value.
262 @return the underlying ptr value. 263 @return the underlying ptr value.
263 */ 264 */
264 T* get() const { 265 T* get() const {
265 return static_cast<T*>(m_ptr); 266 return static_cast<T*>(m_ptr);
266 } 267 }
267 268
268 /** auto conversion to the underlying object ptr. 269 /** auto conversion to the underlying object ptr.
269 @return the underlying ptr value. 270 @return the underlying ptr value.
270 */ 271 */
271 operator T*() const { 272 operator T*() const {
272 return static_cast<T*>(m_ptr); 273 return static_cast<T*>(m_ptr);
273 } 274 }
274 275
275 /** member access. 276 /** member access.
276 @return the underlying ptr value. 277 @return the underlying ptr value.
277 */ 278 */
278 T* operator->() const { 279 T* operator->() const {
279 assert(m_ptr); 280 assert(m_ptr);
280 return static_cast<T*>(m_ptr); 281 return static_cast<T*>(m_ptr);
281 } 282 }
282 283
283 /** Pops a node from the stack. 284 /** Pops a node from the stack.
284 @param st stack. 285 @param st stack.
285 @exception std::logic_error thrown if the node is not of the appropriate type; 286 @exception std::logic_error thrown if the node is not of the appropriate type;
286 thrown only if Required == true or if the stack is empty. 287 thrown only if Required == true or if the stack is empty.
287 */ 288 */
288 virtual void construct(ast_stack& st) override { 289 virtual void construct(ast_stack& st) override {
289 // check the stack node 290 // check the stack node
290 if (st.empty()) { 291 if (st.empty()) {
291 if (!Required) return; 292 if (!Required) return;
292 throw std::logic_error("Invalid AST stack."); 293 throw std::logic_error("Invalid AST stack.");
293 } 294 }
294 ast_node* node = st.back(); 295 ast_node* node = st.back();
295 if (!ast_ptr::accept(node)) { 296 if (!ast_ptr::accept(node)) {
296 // if the object is not required, simply return 297 // if the object is not required, simply return
297 if (!Required) return; 298 if (!Required) return;
298 // else if the object is mandatory, throw an exception 299 // else if the object is mandatory, throw an exception
299 throw std::logic_error("Invalid AST node."); 300 throw std::logic_error("Invalid AST node.");
300 } 301 }
301 st.pop_back(); 302 st.pop_back();
302 m_ptr = node; 303 m_ptr = node;
303 node->retain(); 304 node->retain();
304 } 305 }
305private: 306private:
306 virtual bool accept(ast_node* node) override { 307 virtual bool accept(ast_node* node) override {
307 return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); 308 return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type());
308 } 309 }
309}; 310};
310 311
311template <bool Required, class ...Args> class ast_sel : public _ast_ptr { 312template <bool Required, class ...Args> class ast_sel : public _ast_ptr {
312public: 313public:
313 ast_sel() : _ast_ptr(nullptr) {} 314 ast_sel() : _ast_ptr(nullptr) {}
314 315
315 ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} 316 ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {}
316 317
317 ast_sel& operator=(const ast_sel& other) { 318 ast_sel& operator=(const ast_sel& other) {
318 set(other.get()); 319 set(other.get());
319 return *this; 320 return *this;
320 } 321 }
321 322
322 operator ast_node*() const { 323 operator ast_node*() const {
323 return m_ptr; 324 return m_ptr;
324 } 325 }
325 326
326 ast_node* operator->() const { 327 ast_node* operator->() const {
327 assert(m_ptr); 328 assert(m_ptr);
328 return m_ptr; 329 return m_ptr;
329 } 330 }
330 331
331 virtual void construct(ast_stack& st) override { 332 virtual void construct(ast_stack& st) override {
332 if (st.empty()) { 333 if (st.empty()) {
333 if (!Required) return; 334 if (!Required) return;
334 throw std::logic_error("Invalid AST stack."); 335 throw std::logic_error("Invalid AST stack.");
335 } 336 }
336 ast_node* node = st.back(); 337 ast_node* node = st.back();
337 if (!ast_sel::accept(node)) { 338 if (!ast_sel::accept(node)) {
338 if (!Required) return; 339 if (!Required) return;
339 throw std::logic_error("Invalid AST node."); 340 throw std::logic_error("Invalid AST node.");
340 } 341 }
341 st.pop_back(); 342 st.pop_back();
342 m_ptr = node; 343 m_ptr = node;
343 node->retain(); 344 node->retain();
344 } 345 }
345private: 346private:
346 virtual bool accept(ast_node* node) override { 347 virtual bool accept(ast_node* node) override {
347 if (!node) return false; 348 if (!node) return false;
348 using swallow = bool[]; 349 using swallow = bool[];
349 bool result = false; 350 bool result = false;
350 (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; 351 (void)swallow{result || (result = ast_type<Args>() == node->get_type())...};
@@ -355,8 +356,8 @@ private:
355class _ast_list : public ast_member { 356class _ast_list : public ast_member {
356public: 357public:
357 ~_ast_list() { 358 ~_ast_list() {
358 clear(); 359 clear();
359 } 360 }
360 361
361 inline ast_node* back() const { 362 inline ast_node* back() const {
362 return m_objects.back(); 363 return m_objects.back();
@@ -374,14 +375,14 @@ public:
374 return m_objects.empty(); 375 return m_objects.empty();
375 } 376 }
376 377
377 void push_back(ast_node* node) { 378 void push_back(ast_node* node) {
378 assert(node && accept(node)); 379 assert(node && accept(node));
379 m_objects.push_back(node); 380 m_objects.push_back(node);
380 node->retain(); 381 node->retain();
381 } 382 }
382 383
383 void push_front(ast_node* node) { 384 void push_front(ast_node* node) {
384 assert(node && accept(node)); 385 assert(node && accept(node));
385 m_objects.push_front(node); 386 m_objects.push_front(node);
386 node->retain(); 387 node->retain();
387 } 388 }
@@ -399,22 +400,22 @@ public:
399 } 400 }
400 401
401 const node_container& objects() const { 402 const node_container& objects() const {
402 return m_objects; 403 return m_objects;
403 } 404 }
404 405
405 void clear() { 406 void clear() {
406 for(ast_node* obj : m_objects) { 407 for(ast_node* obj : m_objects) {
407 if (obj) obj->release(); 408 if (obj) obj->release();
408 } 409 }
409 m_objects.clear(); 410 m_objects.clear();
410 } 411 }
411 412
412 void dup(const _ast_list& src) { 413 void dup(const _ast_list& src) {
413 for(ast_node* obj : src.m_objects) { 414 for(ast_node* obj : src.m_objects) {
414 m_objects.push_back(obj); 415 m_objects.push_back(obj);
415 obj->retain(); 416 obj->retain();
416 } 417 }
417 } 418 }
418 419
419 virtual int get_type() override { return ast_type<_ast_list>(); } 420 virtual int get_type() override { return ast_type<_ast_list>(); }
420protected: 421protected:
@@ -422,50 +423,50 @@ protected:
422}; 423};
423 424
424/** A list of objects. 425/** A list of objects.
425 It pops objects of the given type from the ast stack, until no more objects can be popped. 426 It pops objects of the given type from the ast stack, until no more objects can be popped.
426 It assumes ownership of objects. 427 It assumes ownership of objects.
427 @tparam Required if true, the object is required. 428 @tparam Required if true, the object is required.
428 @tparam T type of object to control. 429 @tparam T type of object to control.
429 */ 430*/
430template <bool Required, class T> class ast_list : public _ast_list { 431template <bool Required, class T> class ast_list : public _ast_list {
431public: 432public:
432 ast_list() { } 433 ast_list() { }
433 434
434 ast_list(const ast_list& other) { 435 ast_list(const ast_list& other) {
435 dup(other); 436 dup(other);
436 } 437 }
437 438
438 ast_list& operator=(const ast_list& other) { 439 ast_list& operator=(const ast_list& other) {
439 clear(); 440 clear();
440 dup(other); 441 dup(other);
441 return *this; 442 return *this;
442 } 443 }
443 444
444 /** Pops objects of type T from the stack until no more objects can be popped. 445 /** Pops objects of type T from the stack until no more objects can be popped.
445 @param st stack. 446 @param st stack.
446 */ 447 */
447 virtual void construct(ast_stack &st) override { 448 virtual void construct(ast_stack &st) override {
448 while (!st.empty()) { 449 while (!st.empty()) {
449 ast_node* node = st.back(); 450 ast_node* node = st.back();
450 // if the object was not not of the appropriate type, 451 // if the object was not not of the appropriate type,
451 // end the list parsing 452 // end the list parsing
452 if (!ast_list::accept(node)) { 453 if (!ast_list::accept(node)) {
453 if (Required && m_objects.empty()) { 454 if (Required && m_objects.empty()) {
454 throw std::logic_error("Invalid AST node."); 455 throw std::logic_error("Invalid AST node.");
455 } 456 }
456 return; 457 return;
457 } 458 }
458 st.pop_back(); 459 st.pop_back();
459 // insert the object in the list, in reverse order 460 // insert the object in the list, in reverse order
460 m_objects.push_front(node); 461 m_objects.push_front(node);
461 node->retain(); 462 node->retain();
462 } 463 }
463 if (Required && m_objects.empty()) { 464 if (Required && m_objects.empty()) {
464 throw std::logic_error("Invalid AST stack."); 465 throw std::logic_error("Invalid AST stack.");
465 } 466 }
466 } 467 }
467private: 468private:
468 virtual bool accept(ast_node* node) override { 469 virtual bool accept(ast_node* node) override {
469 return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type()); 470 return node && (std::is_same<ast_node,T>() || ast_type<T>() == node->get_type());
470 } 471 }
471}; 472};
@@ -474,36 +475,36 @@ template <bool Required, class ...Args> class ast_sel_list : public _ast_list {
474public: 475public:
475 ast_sel_list() { } 476 ast_sel_list() { }
476 477
477 ast_sel_list(const ast_sel_list& other) { 478 ast_sel_list(const ast_sel_list& other) {
478 dup(other); 479 dup(other);
479 } 480 }
480 481
481 ast_sel_list& operator=(const ast_sel_list& other) { 482 ast_sel_list& operator=(const ast_sel_list& other) {
482 clear(); 483 clear();
483 dup(other); 484 dup(other);
484 return *this; 485 return *this;
485 } 486 }
486 487
487 virtual void construct(ast_stack &st) override { 488 virtual void construct(ast_stack &st) override {
488 while (!st.empty()) { 489 while (!st.empty()) {
489 ast_node* node = st.back(); 490 ast_node* node = st.back();
490 if (!ast_sel_list::accept(node)) { 491 if (!ast_sel_list::accept(node)) {
491 if (Required && m_objects.empty()) { 492 if (Required && m_objects.empty()) {
492 throw std::logic_error("Invalid AST node."); 493 throw std::logic_error("Invalid AST node.");
493 } 494 }
494 return; 495 return;
495 } 496 }
496 st.pop_back(); 497 st.pop_back();
497 m_objects.push_front(node); 498 m_objects.push_front(node);
498 node->retain(); 499 node->retain();
499 } 500 }
500 if (Required && m_objects.empty()) { 501 if (Required && m_objects.empty()) {
501 throw std::logic_error("Invalid AST stack."); 502 throw std::logic_error("Invalid AST stack.");
502 } 503 }
503 } 504 }
504private: 505private:
505 virtual bool accept(ast_node* node) override { 506 virtual bool accept(ast_node* node) override {
506 if (!node) return false; 507 if (!node) return false;
507 using swallow = bool[]; 508 using swallow = bool[];
508 bool result = false; 509 bool result = false;
509 (void)swallow{result || (result = ast_type<Args>() == node->get_type())...}; 510 (void)swallow{result || (result = ast_type<Args>() == node->get_type())...};
@@ -512,37 +513,37 @@ private:
512}; 513};
513 514
514/** AST function which creates an object of type T 515/** AST function which creates an object of type T
515 and pushes it to the node stack. 516 and pushes it to the node stack.
516 */ 517*/
517template <class T> class ast { 518template <class T> class ast {
518public: 519public:
519 /** constructor. 520 /** constructor.
520 @param r rule to attach the AST function to. 521 @param r rule to attach the AST function to.
521 */ 522 */
522 ast(rule& r) { 523 ast(rule& r) {
523 r.set_parse_proc(&_parse_proc); 524 r.set_parse_proc(&_parse_proc);
524 } 525 }
525private: 526private:
526 //parse proc 527 //parse proc
527 static void _parse_proc(const pos& b, const pos& e, void* d) { 528 static void _parse_proc(const pos& b, const pos& e, void* d) {
528 ast_stack* st = reinterpret_cast<ast_stack*>(d); 529 ast_stack* st = reinterpret_cast<ast_stack*>(d);
529 T* obj = new T; 530 T* obj = new T;
530 obj->m_begin = b; 531 obj->m_begin = b;
531 obj->m_end = e; 532 obj->m_end = e;
532 obj->construct(*st); 533 obj->construct(*st);
533 st->push_back(obj); 534 st->push_back(obj);
534 } 535 }
535}; 536};
536 537
537 538
538/** parses the given input. 539/** parses the given input.
539 @param i input. 540 @param i input.
540 @param g root rule of grammar. 541 @param g root rule of grammar.
541 @param el list of errors. 542 @param el list of errors.
542 @param ud user data, passed to the parse procedures. 543 @param ud user data, passed to the parse procedures.
543 @return pointer to ast node created, or null if there was an error. 544 @return pointer to ast node created, or null if there was an error.
544 The return object must be deleted by the caller. 545 The return object must be deleted by the caller.
545 */ 546*/
546ast_node* parse(input& i, rule& g, error_list& el, void* ud); 547ast_node* parse(input& i, rule& g, error_list& el, void* ud);
547 548
548 549