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: