etisserant@0: /* msousa@261: * matiec - a compiler for the programming languages defined in IEC 61131-3 msousa@261: * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) Edouard@279: * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant msousa@261: * msousa@261: * This program is free software: you can redistribute it and/or modify msousa@261: * it under the terms of the GNU General Public License as published by msousa@261: * the Free Software Foundation, either version 3 of the License, or msousa@261: * (at your option) any later version. msousa@261: * msousa@261: * This program is distributed in the hope that it will be useful, msousa@261: * but WITHOUT ANY WARRANTY; without even the implied warranty of msousa@261: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the msousa@261: * GNU General Public License for more details. msousa@261: * msousa@261: * You should have received a copy of the GNU General Public License msousa@261: * along with this program. If not, see . msousa@261: * 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: /* msousa@261: * An IEC 61131-3 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: msousa@738: #define SYM_LIST(class_name_c, ...) \ etisserant@0: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: msousa@417: #define SYM_TOKEN(class_name_c, ...) \ msousa@417: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@417: msousa@417: #define SYM_REF0(class_name_c, ...) \ msousa@417: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@417: msousa@417: #define SYM_REF1(class_name_c, ref1, ...) \ mario@69: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} mario@69: msousa@350: #define SYM_REF2(class_name_c, ref1, ref2, ...) \ msousa@350: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@350: msousa@350: #define SYM_REF3(class_name_c, ref1, ref2, ref3, ...) \ msousa@350: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@350: msousa@350: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...) \ msousa@350: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@350: msousa@350: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...) \ msousa@350: void *null_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@350: msousa@350: #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: msousa@680: msousa@680: /*******************/ msousa@680: /* fcall_visitor_c */ msousa@680: /*******************/ msousa@680: msousa@680: //fcall_visitor_c::~fcall_visitor_c(void) {return;}; msousa@680: msousa@680: msousa@680: // void fcall_visitor_c::fcall(symbol_c *symbol) {return;}; msousa@680: msousa@680: #define VISIT_METHOD {fcall(symbol); return NULL;} msousa@680: msousa@680: #define SYM_LIST(class_name_c, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_TOKEN(class_name_c, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF0(class_name_c, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF1(class_name_c, ref1, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF2(class_name_c, ref1, ref2, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF3(class_name_c, ref1, ref2, ref3, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...) void *fcall_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: msousa@680: #include "../absyntax/absyntax.def" msousa@680: msousa@680: #undef VISIT_METHOD 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: msousa@680: /**********************/ msousa@680: /* iterator_visitor_c */ msousa@680: /**********************/ msousa@680: msousa@680: iterator_visitor_c::~iterator_visitor_c(void) {return;} msousa@680: msousa@680: msousa@680: void *iterator_visitor_c::visit_list(list_c *list) { etisserant@0: for(int i = 0; i < list->n; i++) { msousa@1041: list->get_element(i)->accept(*this); etisserant@0: } etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: msousa@738: #define SYM_LIST(class_name_c, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);} etisserant@0: msousa@417: #define SYM_TOKEN(class_name_c, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;} etisserant@0: msousa@417: #define SYM_REF0(class_name_c, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@680: msousa@680: #define SYM_REF1(class_name_c, ref1, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1!=NULL) symbol->ref1->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF2(class_name_c, ref1, ref2, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1!=NULL) symbol->ref1->accept(*this); \ msousa@680: if (symbol->ref2!=NULL) symbol->ref2->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF3(class_name_c, ref1, ref2, ref3, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1) symbol->ref1->accept(*this); \ msousa@680: if (symbol->ref2) symbol->ref2->accept(*this); \ msousa@680: if (symbol->ref3) symbol->ref3->accept(*this); \ msousa@680: return NULL; \ mario@69: } mario@69: msousa@350: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1) symbol->ref1->accept(*this); \ msousa@680: if (symbol->ref2) symbol->ref2->accept(*this); \ msousa@680: if (symbol->ref3) symbol->ref3->accept(*this); \ msousa@680: if (symbol->ref4) symbol->ref4->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1) symbol->ref1->accept(*this); \ msousa@680: if (symbol->ref2) symbol->ref2->accept(*this); \ msousa@680: if (symbol->ref3) symbol->ref3->accept(*this); \ msousa@680: if (symbol->ref4) symbol->ref4->accept(*this); \ msousa@680: if (symbol->ref5) symbol->ref5->accept(*this); \ mario@69: return NULL; \ mario@69: } etisserant@0: msousa@350: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...) \ msousa@680: void *iterator_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1) symbol->ref1->accept(*this); \ msousa@680: if (symbol->ref2) symbol->ref2->accept(*this); \ msousa@680: if (symbol->ref3) symbol->ref3->accept(*this); \ msousa@680: if (symbol->ref4) symbol->ref4->accept(*this); \ msousa@680: if (symbol->ref5) symbol->ref5->accept(*this); \ msousa@680: 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: msousa@680: /****************************/ msousa@680: /* fcall_iterator_visitor_c */ msousa@680: /****************************/ msousa@680: msousa@680: fcall_iterator_visitor_c::~fcall_iterator_visitor_c(void) {return;}; msousa@680: msousa@680: void fcall_iterator_visitor_c::prefix_fcall(symbol_c *symbol) {return;}; msousa@680: void fcall_iterator_visitor_c::suffix_fcall(symbol_c *symbol) {return;}; msousa@680: msousa@680: #define VISIT_METHOD {\ msousa@680: prefix_fcall(symbol); \ msousa@680: iterator_visitor_c::visit(symbol); \ msousa@680: suffix_fcall(symbol); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_LIST(class_name_c, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_TOKEN(class_name_c, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF0(class_name_c, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF1(class_name_c, ref1, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF2(class_name_c, ref1, ref2, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF3(class_name_c, ref1, ref2, ref3, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...) void *fcall_iterator_visitor_c::visit(class_name_c *symbol) VISIT_METHOD; msousa@680: msousa@680: #include "../absyntax/absyntax.def" msousa@680: msousa@680: #undef VISIT_METHOD msousa@680: msousa@680: #undef SYM_LIST msousa@680: #undef SYM_TOKEN msousa@680: #undef SYM_REF0 msousa@680: #undef SYM_REF1 msousa@680: #undef SYM_REF2 msousa@680: #undef SYM_REF3 msousa@680: #undef SYM_REF4 msousa@680: #undef SYM_REF5 msousa@680: #undef SYM_REF6 msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: /********************/ msousa@680: /* search_visitor_c */ msousa@680: /********************/ msousa@680: msousa@680: search_visitor_c::~search_visitor_c(void) {return;} msousa@680: msousa@680: msousa@680: void *search_visitor_c::visit_list(list_c *list) { msousa@680: for(int i = 0; i < list->n; i++) { msousa@1041: void *res = list->get_element(i)->accept(*this); msousa@680: if (res != NULL) msousa@680: return res; msousa@680: } msousa@680: return NULL; msousa@680: } msousa@680: msousa@680: msousa@738: #define SYM_LIST(class_name_c, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);} msousa@680: msousa@680: #define SYM_TOKEN(class_name_c, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@680: msousa@680: #define SYM_REF0(class_name_c, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) {return NULL;} msousa@680: msousa@680: #define SYM_REF1(class_name_c, ref1, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) { \ msousa@680: if (symbol->ref1) return symbol->ref1->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF2(class_name_c, ref1, ref2, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) { \ msousa@680: void *res = NULL; \ msousa@680: if (symbol->ref1) res = symbol->ref1->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref2) return symbol->ref2->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF3(class_name_c, ref1, ref2, ref3, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) { \ msousa@680: void *res = NULL; \ msousa@680: if (symbol->ref1) res = symbol->ref1->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref2) res = symbol->ref2->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref3) return symbol->ref3->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) { \ msousa@680: void *res = NULL; \ msousa@680: if (symbol->ref1) res = symbol->ref1->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref2) res = symbol->ref2->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref3) res = symbol->ref3->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref4) return symbol->ref4->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF5(class_name_c, ref1, ref2, ref3, ref4, ref5, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) { \ msousa@680: void *res = NULL; \ msousa@680: if (symbol->ref1) res = symbol->ref1->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref2) res = symbol->ref2->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref3) res = symbol->ref3->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref4) res = symbol->ref4->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref5) return symbol->ref5->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: #define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6, ...) \ msousa@680: void *search_visitor_c::visit(class_name_c *symbol) { \ msousa@680: void *res = NULL; \ msousa@680: if (symbol->ref1) res = symbol->ref1->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref2) res = symbol->ref2->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref3) res = symbol->ref3->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref4) res = symbol->ref4->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref5) res = symbol->ref5->accept(*this); \ msousa@680: if (res != NULL) return res; \ msousa@680: if (symbol->ref6) return symbol->ref6->accept(*this); \ msousa@680: return NULL; \ msousa@680: } msousa@680: msousa@680: msousa@680: msousa@680: #include "absyntax.def" msousa@680: msousa@680: msousa@680: msousa@680: #undef SYM_LIST msousa@680: #undef SYM_TOKEN msousa@680: #undef SYM_REF0 msousa@680: #undef SYM_REF1 msousa@680: #undef SYM_REF2 msousa@680: #undef SYM_REF3 msousa@680: #undef SYM_REF4 msousa@680: #undef SYM_REF5 msousa@680: #undef SYM_REF6 msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: msousa@680: