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: