laurent@377: /* laurent@377: * matiec - a compiler for the programming languages defined in IEC 61131-3 laurent@377: * laurent@377: * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) laurent@377: * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant laurent@377: * laurent@377: * This program is free software: you can redistribute it and/or modify laurent@377: * it under the terms of the GNU General Public License as published by laurent@377: * the Free Software Foundation, either version 3 of the License, or laurent@377: * (at your option) any later version. laurent@377: * laurent@377: * This program is distributed in the hope that it will be useful, laurent@377: * but WITHOUT ANY WARRANTY; without even the implied warranty of laurent@377: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the laurent@377: * GNU General Public License for more details. laurent@377: * laurent@377: * You should have received a copy of the GNU General Public License laurent@377: * along with this program. If not, see . laurent@377: * laurent@377: * laurent@377: * This code is made available on the understanding that it will not be laurent@377: * used in safety-critical situations without a full and competent review. laurent@377: */ laurent@377: laurent@377: /* laurent@377: * An IEC 61131-3 compiler. laurent@377: * laurent@377: * Based on the laurent@377: * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) laurent@377: * laurent@377: */ laurent@377: laurent@377: laurent@377: /* laurent@377: * Array dimension iterator. laurent@377: * Iterate through the dimensions of array specification. laurent@377: * laurent@377: * This is part of the 4th stage that generates laurent@377: * a c++ source program equivalent to the IL and ST laurent@377: * code. laurent@377: */ laurent@377: laurent@377: /* Given a array_specification_c, iterate through laurent@377: * each subrange, returning the symbol of each subrange laurent@377: * ...array_dimension_iterator_c laurent@377: */ laurent@377: laurent@377: laurent@377: laurent@377: laurent@377: #include "array_dimension_iterator.hh" msousa@596: #include "../main.hh" // required for ERROR() and ERROR_MSG() macros. laurent@377: laurent@377: laurent@377: //#define DEBUG laurent@377: #ifdef DEBUG laurent@377: #define TRACE(classname) printf("\n____%s____\n",classname); laurent@377: #else laurent@377: #define TRACE(classname) laurent@377: #endif laurent@377: laurent@377: laurent@377: laurent@377: void* array_dimension_iterator_c::iterate_list(list_c *list) { laurent@377: void *res; laurent@377: for (int i = 0; i < list->n; i++) { laurent@377: res = list->elements[i]->accept(*this); laurent@377: if (res != NULL) laurent@377: return res; laurent@377: } laurent@377: return NULL; laurent@377: } laurent@377: laurent@377: /* start off at the first case element once again... */ laurent@377: void array_dimension_iterator_c::reset(void) { laurent@377: current_array_dimension = NULL; laurent@377: } laurent@377: laurent@377: laurent@377: /* initialize the iterator object. laurent@377: * We must be given a reference to a array_specification_c that will be analyzed... laurent@377: */ laurent@377: array_dimension_iterator_c::array_dimension_iterator_c(symbol_c *symbol) { laurent@377: /* do some consistency check... */ mjsousa@830: /* NOTE: We comment out the consistency check so the compiler does not bork when it encounters buggy source code. mjsousa@830: * e.g. Code that handles a non array variable as an array! mjsousa@830: * VAR v1, v2: int; END_VAR mjsousa@830: * v1 := v2[33, 45]; mjsousa@830: * The above error will be caught by the datatype checking algorithms! mjsousa@830: */ mjsousa@840: array_spec_init_c * array_spec_init = dynamic_cast(symbol); mjsousa@840: if (NULL != array_spec_init) symbol = array_spec_init->array_specification; mjsousa@840: array_specification_c* array_spec = dynamic_cast(symbol); mjsousa@830: // if (NULL == array_spec) ERROR; laurent@377: laurent@377: /* OK. Now initialize this object... */ mjsousa@830: this->array_specification = array_spec; // Set to array_spec and not symbol => will be NULL if not an array_specification_c* !! laurent@377: reset(); laurent@377: } laurent@377: laurent@377: laurent@377: laurent@377: /* Skip to the next subrange. After object creation, laurent@377: * the object references on subrange _before_ the first, so laurent@377: * this function must be called once to get the object to laurent@377: * reference the first subrange... laurent@377: * laurent@377: * Returns the subrange symbol! laurent@377: */ msousa@562: subrange_c *array_dimension_iterator_c::next(void) { mjsousa@830: if (NULL == array_specification) return NULL; /* The source code probably has a bug which will be caught somewhere else! */ laurent@377: void *res = array_specification->accept(*this); mjsousa@830: if (NULL == res) return NULL; laurent@377: laurent@377: return current_array_dimension; laurent@377: } laurent@377: laurent@377: /********************************/ laurent@377: /* B 1.3.3 - Derived data types */ laurent@377: /********************************/ laurent@377: /* signed_integer DOTDOT signed_integer */ laurent@377: void *array_dimension_iterator_c::visit(subrange_c *symbol) { laurent@377: if (current_array_dimension == symbol) { laurent@377: current_array_dimension = NULL; laurent@377: } laurent@377: else if (current_array_dimension == NULL) { laurent@377: current_array_dimension = symbol; laurent@377: return symbol; laurent@377: } laurent@377: laurent@377: /* Not found! */ laurent@377: return NULL; laurent@377: } laurent@377: laurent@377: /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */ laurent@377: void *array_dimension_iterator_c::visit(array_specification_c *symbol) { laurent@377: return symbol->array_subrange_list->accept(*this); laurent@377: } laurent@377: laurent@377: /* array_subrange_list ',' subrange */ laurent@377: void *array_dimension_iterator_c::visit(array_subrange_list_c *symbol) { laurent@377: return iterate_list(symbol); laurent@377: } laurent@377: