etisserant@0: /* etisserant@0: * (c) 2003 Mario de Sousa etisserant@0: * etisserant@0: * Offered to the public under the terms of the GNU General Public License etisserant@0: * as published by the Free Software Foundation; either version 2 of the etisserant@0: * License, or (at your option) any later version. etisserant@0: * etisserant@0: * This program is distributed in the hope that it will be useful, but etisserant@0: * WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General etisserant@0: * Public License for more details. etisserant@0: * etisserant@0: * This code is made available on the understanding that it will not be etisserant@0: * used in safety-critical situations without a full and competent review. etisserant@0: */ etisserant@0: etisserant@0: /* etisserant@0: * An IEC 61131-3 IL and ST compiler. etisserant@0: * etisserant@0: * Based on the etisserant@0: * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) etisserant@0: * etisserant@0: */ etisserant@0: etisserant@0: etisserant@0: /* etisserant@0: * VISITOR.CC etisserant@0: * etisserant@0: * Three base implementations of the visitor interface, etisserant@0: * that may be later extended to execute a particular algorithm. etisserant@0: * etisserant@0: * The null (class null_visitor_c) does nothing. etisserant@0: * etisserant@0: * The iterator (class iterator_visitor_c) iterates through etisserant@0: * every object in the syntax tree. etisserant@0: * etisserant@0: * The search class (class search_visitor_c) iterates through etisserant@0: * every object, until one returns a value != NULL. etisserant@0: */ etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: #include etisserant@0: etisserant@0: #include /* required for NULL */ etisserant@0: #include "visitor.hh" etisserant@0: etisserant@0: #include etisserant@0: etisserant@0: etisserant@0: /******************/ etisserant@0: /* visitor_c */ etisserant@0: /******************/ etisserant@0: etisserant@0: visitor_c::~visitor_c(void) {return;} etisserant@0: etisserant@0: etisserant@0: /******************/ etisserant@0: /* null_visitor_c */ etisserant@0: /******************/ etisserant@0: etisserant@0: null_visitor_c::~null_visitor_c(void) {return;} etisserant@0: etisserant@0: #define SYM_LIST(class_name_c) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: etisserant@0: #define SYM_TOKEN(class_name_c) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: etisserant@0: #define SYM_REF0(class_name_c) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: mario@69: #define SYM_REF1(class_name_c, ref1) \ mario@69: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} mario@69: etisserant@0: #define SYM_REF2(class_name_c, ref1, ref2) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: mario@69: #define SYM_REF3(class_name_c, ref1, ref2, ref3) \ mario@69: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} mario@69: etisserant@0: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: mario@69: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5) \ mario@69: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} mario@69: etisserant@0: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: etisserant@0: etisserant@0: #include "absyntax.def" etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: #undef SYM_LIST etisserant@0: #undef SYM_TOKEN etisserant@0: #undef SYM_REF0 mario@69: #undef SYM_REF1 etisserant@0: #undef SYM_REF2 mario@69: #undef SYM_REF3 etisserant@0: #undef SYM_REF4 mario@69: #undef SYM_REF5 etisserant@0: #undef SYM_REF6 etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: /**********************/ etisserant@0: /* iterator_visitor_c */ etisserant@0: /**********************/ etisserant@0: etisserant@0: iterator_visitor_c::~iterator_visitor_c(void) {return;} etisserant@0: etisserant@0: etisserant@0: void *iterator_visitor_c::visit_list(list_c *list) { etisserant@0: for(int i = 0; i < list->n; i++) { etisserant@0: list->elements[i]->accept(*this); etisserant@0: } etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: #define SYM_LIST(class_name_c) \ etisserant@0: void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);} etisserant@0: etisserant@0: #define SYM_TOKEN(class_name_c) \ etisserant@0: void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: etisserant@0: #define SYM_REF0(class_name_c) \ etisserant@0: void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: mario@69: #define SYM_REF1(class_name_c, ref1) \ mario@69: void *iterator_visitor_c::visit(class_name_c *symbol) { \ mario@69: if (symbol->ref1!=NULL) symbol->ref1->accept(*this); \ mario@69: return NULL; \ mario@69: } mario@69: etisserant@0: #define SYM_REF2(class_name_c, ref1, ref2) \ etisserant@0: void *iterator_visitor_c::visit(class_name_c *symbol) { \ etisserant@0: if (symbol->ref1!=NULL) symbol->ref1->accept(*this); \ etisserant@0: if (symbol->ref2!=NULL) symbol->ref2->accept(*this); \ etisserant@0: return NULL; \ etisserant@0: } etisserant@0: mario@69: #define SYM_REF3(class_name_c, ref1, ref2, ref3) \ mario@69: void *iterator_visitor_c::visit(class_name_c *symbol) { \ mario@69: if (symbol->ref1) symbol->ref1->accept(*this); \ mario@69: if (symbol->ref2) symbol->ref2->accept(*this); \ mario@69: if (symbol->ref3) symbol->ref3->accept(*this); \ mario@69: return NULL; \ mario@69: } mario@69: etisserant@0: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4) \ etisserant@0: void *iterator_visitor_c::visit(class_name_c *symbol) { \ etisserant@0: if (symbol->ref1) symbol->ref1->accept(*this); \ etisserant@0: if (symbol->ref2) symbol->ref2->accept(*this); \ etisserant@0: if (symbol->ref3) symbol->ref3->accept(*this); \ etisserant@0: if (symbol->ref4) symbol->ref4->accept(*this); \ etisserant@0: return NULL; \ etisserant@0: } etisserant@0: mario@69: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5) \ mario@69: void *iterator_visitor_c::visit(class_name_c *symbol) { \ mario@69: if (symbol->ref1) symbol->ref1->accept(*this); \ mario@69: if (symbol->ref2) symbol->ref2->accept(*this); \ mario@69: if (symbol->ref3) symbol->ref3->accept(*this); \ mario@69: if (symbol->ref4) symbol->ref4->accept(*this); \ mario@69: if (symbol->ref5) symbol->ref5->accept(*this); \ mario@69: return NULL; \ mario@69: } etisserant@0: etisserant@0: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6) \ etisserant@0: void *iterator_visitor_c::visit(class_name_c *symbol) { \ etisserant@0: if (symbol->ref1) symbol->ref1->accept(*this); \ etisserant@0: if (symbol->ref2) symbol->ref2->accept(*this); \ etisserant@0: if (symbol->ref3) symbol->ref3->accept(*this); \ etisserant@0: if (symbol->ref4) symbol->ref4->accept(*this); \ etisserant@0: if (symbol->ref5) symbol->ref5->accept(*this); \ etisserant@0: if (symbol->ref6) symbol->ref6->accept(*this); \ etisserant@0: return NULL; \ etisserant@0: } etisserant@0: etisserant@0: etisserant@0: etisserant@0: #include "absyntax.def" etisserant@0: etisserant@0: etisserant@0: etisserant@0: #undef SYM_LIST etisserant@0: #undef SYM_TOKEN etisserant@0: #undef SYM_REF0 mario@69: #undef SYM_REF1 etisserant@0: #undef SYM_REF2 mario@69: #undef SYM_REF3 etisserant@0: #undef SYM_REF4 mario@69: #undef SYM_REF5 etisserant@0: #undef SYM_REF6 etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: /********************/ etisserant@0: /* search_visitor_c */ etisserant@0: /********************/ etisserant@0: etisserant@0: search_visitor_c::~search_visitor_c(void) {return;} etisserant@0: etisserant@0: etisserant@0: void *search_visitor_c::visit_list(list_c *list) { etisserant@0: for(int i = 0; i < list->n; i++) { etisserant@0: void *res = list->elements[i]->accept(*this); etisserant@0: if (res != NULL) etisserant@0: return res; etisserant@0: } etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: #define SYM_LIST(class_name_c) \ etisserant@0: void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);} etisserant@0: etisserant@0: #define SYM_TOKEN(class_name_c) \ etisserant@0: void *search_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: etisserant@0: #define SYM_REF0(class_name_c) \ etisserant@0: void *search_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: mario@69: #define SYM_REF1(class_name_c, ref1) \ mario@69: void *search_visitor_c::visit(class_name_c *symbol) { \ mario@69: if (symbol->ref1) return symbol->ref1->accept(*this); \ mario@69: return NULL; \ mario@69: } mario@69: etisserant@0: #define SYM_REF2(class_name_c, ref1, ref2) \ etisserant@0: void *search_visitor_c::visit(class_name_c *symbol) { \ etisserant@0: void *res = NULL; \ etisserant@0: if (symbol->ref1) res = symbol->ref1->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref2) return symbol->ref2->accept(*this); \ etisserant@0: return NULL; \ etisserant@0: } etisserant@0: mario@69: #define SYM_REF3(class_name_c, ref1, ref2, ref3) \ mario@69: void *search_visitor_c::visit(class_name_c *symbol) { \ mario@69: void *res = NULL; \ mario@69: if (symbol->ref1) res = symbol->ref1->accept(*this); \ mario@69: if (res != NULL) return res; \ mario@69: if (symbol->ref2) res = symbol->ref2->accept(*this); \ mario@69: if (res != NULL) return res; \ mario@69: if (symbol->ref3) return symbol->ref3->accept(*this); \ mario@69: return NULL; \ mario@69: } mario@69: etisserant@0: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4) \ etisserant@0: void *search_visitor_c::visit(class_name_c *symbol) { \ etisserant@0: void *res = NULL; \ etisserant@0: if (symbol->ref1) res = symbol->ref1->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref2) res = symbol->ref2->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref3) res = symbol->ref3->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref4) return symbol->ref4->accept(*this); \ etisserant@0: return NULL; \ etisserant@0: } etisserant@0: mario@69: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5) \ mario@69: void *search_visitor_c::visit(class_name_c *symbol) { \ mario@69: void *res = NULL; \ mario@69: if (symbol->ref1) res = symbol->ref1->accept(*this); \ mario@69: if (res != NULL) return res; \ mario@69: if (symbol->ref2) res = symbol->ref2->accept(*this); \ mario@69: if (res != NULL) return res; \ mario@69: if (symbol->ref3) res = symbol->ref3->accept(*this); \ mario@69: if (res != NULL) return res; \ mario@69: if (symbol->ref4) res = symbol->ref4->accept(*this); \ mario@69: if (res != NULL) return res; \ mario@69: if (symbol->ref5) return symbol->ref5->accept(*this); \ mario@69: return NULL; \ mario@69: } etisserant@0: etisserant@0: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6) \ etisserant@0: void *search_visitor_c::visit(class_name_c *symbol) { \ etisserant@0: void *res = NULL; \ etisserant@0: if (symbol->ref1) res = symbol->ref1->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref2) res = symbol->ref2->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref3) res = symbol->ref3->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref4) res = symbol->ref4->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref5) res = symbol->ref5->accept(*this); \ etisserant@0: if (res != NULL) return res; \ etisserant@0: if (symbol->ref6) return symbol->ref6->accept(*this); \ etisserant@0: return NULL; \ etisserant@0: } etisserant@0: etisserant@0: etisserant@0: etisserant@0: #include "absyntax.def" etisserant@0: etisserant@0: etisserant@0: etisserant@0: #undef SYM_LIST etisserant@0: #undef SYM_TOKEN etisserant@0: #undef SYM_REF0 mario@69: #undef SYM_REF1 etisserant@0: #undef SYM_REF2 mario@69: #undef SYM_REF3 etisserant@0: #undef SYM_REF4 mario@69: #undef SYM_REF5 etisserant@0: #undef SYM_REF6 etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: