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: /* Decomposes a variable instance name into its constituents, etisserant@0: * example: etisserant@0: * window.points[1].coordinate.x etisserant@0: * etisserant@0: * will succesfully return etisserant@0: * - window etisserant@0: * - points etisserant@0: * - coordinate etisserant@0: * - x etisserant@0: * on succesive calls to decompose_var_instance_name_c::next_part() etisserant@0: */ etisserant@0: class decompose_var_instance_name_c: null_visitor_c { etisserant@0: etisserant@0: private: etisserant@0: symbol_c *variable_name; etisserant@0: symbol_c *next_variable_name; etisserant@0: symbol_c *current_recursive_variable_name; etisserant@0: symbol_c *previously_returned_variable_name; etisserant@0: etisserant@0: public: etisserant@0: decompose_var_instance_name_c(symbol_c *variable_instance_name) { etisserant@0: variable_name = variable_instance_name; etisserant@0: next_variable_name = NULL; etisserant@0: current_recursive_variable_name = NULL; etisserant@0: previously_returned_variable_name = NULL; etisserant@0: } etisserant@0: etisserant@0: public: etisserant@0: symbol_c *next_part(void) { etisserant@0: /* We must always start from the top! etisserant@0: * See note in the structured_variable_c visitor etisserant@0: * to understand why... etisserant@0: */ etisserant@0: symbol_c *res = (symbol_c *)variable_name->accept(*this); etisserant@0: next_variable_name = current_recursive_variable_name; etisserant@0: etisserant@0: if (previously_returned_variable_name == res) etisserant@0: return NULL; etisserant@0: previously_returned_variable_name = res; etisserant@0: return res; etisserant@0: } etisserant@0: etisserant@0: public: etisserant@0: /*********************/ etisserant@0: /* B 1.4 - Variables */ etisserant@0: /*********************/ etisserant@0: void *visit(symbolic_variable_c *symbol) {return (void *)(symbol->var_name);} etisserant@0: etisserant@0: /********************************************/ etisserant@0: /* B.1.4.1 Directly Represented Variables */ etisserant@0: /********************************************/ etisserant@0: void *visit(direct_variable_c *symbol) {return (void *)symbol;} etisserant@0: etisserant@0: /*************************************/ etisserant@0: /* B.1.4.2 Multi-element Variables */ etisserant@0: /*************************************/ etisserant@0: /* subscripted_variable '[' subscript_list ']' */ etisserant@0: // SYM_REF2(array_variable_c, subscripted_variable, subscript_list) etisserant@0: void *visit(array_variable_c *symbol) { etisserant@0: /* NOTE: the subscripted_variable may itself be a structure!, etisserant@0: * so we must recursevily visit! etisserant@0: */ etisserant@0: return symbol->subscripted_variable->accept(*this); etisserant@0: } etisserant@0: etisserant@0: /* record_variable '.' field_selector */ etisserant@0: /* WARNING: input and/or output variables of function blocks etisserant@0: * may be accessed as fields of a tructured variable! etisserant@0: * Code handling a structured_variable_c must take etisserant@0: * this into account! etisserant@0: */ etisserant@0: //SYM_REF2(structured_variable_c, record_variable, field_selector) etisserant@0: void *visit(structured_variable_c *symbol) { etisserant@0: /* NOTE: The following code will not work, as structured_variable_c etisserant@0: * are grouped on the left, and not on the right! etisserant@0: * etisserant@0: * example: window.origin.x etisserant@0: * will result in etisserant@0: * s1 = structured_variable_c("window, "origin"); etisserant@0: * s2 = structured_variable_c(s1, "x"); etisserant@0: * AND NOT etisserant@0: * s1 = structured_variable_c("origin", "x"); etisserant@0: * s2 = structured_variable_c("window", s1); etisserant@0: * etisserant@0: * as the following code assumes!! etisserant@0: * etisserant@0: current_variable_name = symbol->field_selector; etisserant@0: return symbol->record_variable->accept(*this); etisserant@0: */ etisserant@0: etisserant@0: /* The correct code, is therefore more complex... */ etisserant@0: if (next_variable_name == symbol) { etisserant@0: /* NOTE: field_selector is always an identifier_c, etisserant@0: * so we do not have to recursevily visit it again... etisserant@0: * return (void *)symbol->field_selector->accept(*this); -> NOT REQUIRED!! etisserant@0: */ etisserant@0: return (void *)symbol->field_selector; etisserant@0: } etisserant@0: etisserant@0: current_recursive_variable_name = symbol; etisserant@0: return symbol->record_variable->accept(*this); etisserant@0: } etisserant@0: }; etisserant@0: etisserant@0: etisserant@0: etisserant@0: