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: /* etisserant@0: * Conversion of type declaration constructs. etisserant@0: * etisserant@0: * This is part of the 4th stage that generates etisserant@0: * a c++ source program equivalent to the IL and ST etisserant@0: * code. etisserant@0: */ etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: //#include /* required for NULL */ etisserant@0: //#include etisserant@0: //#include etisserant@0: etisserant@0: //#include "../../util/symtable.hh" etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: class generate_cc_typedecl_c: public generate_cc_base_c { etisserant@0: etisserant@0: public: etisserant@0: generate_cc_typedecl_c(stage4out_c *s4o_ptr): generate_cc_base_c(s4o_ptr) {} etisserant@0: ~generate_cc_typedecl_c(void) {} etisserant@0: etisserant@0: etisserant@0: /***************************/ etisserant@0: /* B 0 - Programming Model */ etisserant@0: /***************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /*************************/ etisserant@0: /* B.1 - Common elements */ etisserant@0: /*************************/ etisserant@0: /*******************************************/ etisserant@0: /* B 1.1 - Letters, digits and identifiers */ etisserant@0: /*******************************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /*********************/ etisserant@0: /* B 1.2 - Constants */ etisserant@0: /*********************/ etisserant@0: /* originally empty... */ etisserant@0: etisserant@0: /******************************/ etisserant@0: /* B 1.2.1 - Numeric Literals */ etisserant@0: /******************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /*******************************/ etisserant@0: /* B.1.2.2 Character Strings */ etisserant@0: /*******************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /***************************/ etisserant@0: /* B 1.2.3 - Time Literals */ etisserant@0: /***************************/ etisserant@0: /************************/ etisserant@0: /* B 1.2.3.1 - Duration */ etisserant@0: /************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /************************************/ etisserant@0: /* B 1.2.3.2 - Time of day and Date */ etisserant@0: /************************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /**********************/ etisserant@0: /* B.1.3 - Data types */ etisserant@0: /**********************/ etisserant@0: /***********************************/ etisserant@0: /* B 1.3.1 - Elementary Data Types */ etisserant@0: /***********************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /********************************/ etisserant@0: /* B.1.3.2 - Generic data types */ etisserant@0: /********************************/ etisserant@0: /* originally empty... */ etisserant@0: etisserant@0: /********************************/ etisserant@0: /* B 1.3.3 - Derived data types */ etisserant@0: /********************************/ etisserant@0: void *visit(subrange_spec_init_c *symbol) { etisserant@0: TRACE("subrange_spec_init_c"); etisserant@0: // TODO... etisserant@0: ERROR; etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: void *visit(enumerated_spec_init_c *symbol) { etisserant@0: TRACE("enumerated_spec_init_c"); etisserant@0: // TODO... etisserant@0: ERROR; etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* TYPE type_declaration_list END_TYPE */ etisserant@0: void *visit(data_type_declaration_c *symbol) { etisserant@0: TRACE("data_type_declaration_c"); etisserant@0: symbol->type_declaration_list->accept(*this); etisserant@0: s4o.print("\n\n"); etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* helper symbol for data_type_declaration */ etisserant@0: void *visit(type_declaration_list_c *symbol) { etisserant@0: TRACE("type_declaration_list_c"); etisserant@0: return print_list(symbol); etisserant@0: } etisserant@0: etisserant@0: /* simple_type_name ':' simple_spec_init */ etisserant@0: void *visit(simple_type_declaration_c *symbol) { etisserant@0: TRACE("simple_type_declaration_c"); etisserant@0: /* add this type declaration to the type symbol table... */ etisserant@0: type_symtable.insert(symbol->simple_type_name, symbol->simple_spec_init); etisserant@0: etisserant@0: s4o.print("typedef "); etisserant@0: symbol->simple_spec_init->accept(*this); etisserant@0: s4o.print(" "); etisserant@0: symbol->simple_type_name->accept(*this); etisserant@0: s4o.print(";\n"); etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* simple_specification [ASSIGN constant] */ etisserant@0: //SYM_REF2(simple_spec_init_c, simple_specification, constant) etisserant@0: // may be NULL etisserant@0: void *visit(simple_spec_init_c *symbol) { etisserant@0: TRACE("simple_spec_init_c"); etisserant@0: symbol->simple_specification->accept(*this); etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: #if 0 etisserant@0: /* subrange_type_name ':' subrange_spec_init */ etisserant@0: SYM_REF2(subrange_type_declaration_c, subrange_type_name, subrange_spec_init) etisserant@0: etisserant@0: /* subrange_specification ASSIGN signed_integer */ etisserant@0: SYM_REF2(subrange_spec_init_c, subrange_specification, signed_integer) etisserant@0: etisserant@0: /* integer_type_name '(' subrange')' */ etisserant@0: SYM_REF2(subrange_specification_c, integer_type_name, subrange) etisserant@0: etisserant@0: /* signed_integer DOTDOT signed_integer */ etisserant@0: SYM_REF2(subrange_c, lower_limit, upper_limit) etisserant@0: etisserant@0: /* enumerated_type_name ':' enumerated_spec_init */ etisserant@0: SYM_REF2(enumerated_type_declaration_c, enumerated_type_name, enumerated_spec_init) etisserant@0: etisserant@0: /* enumerated_specification ASSIGN enumerated_value */ etisserant@0: SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value) etisserant@0: etisserant@0: /* helper symbol for enumerated_specification->enumerated_spec_init */ etisserant@0: /* enumerated_value_list ',' enumerated_value */ etisserant@0: SYM_LIST(enumerated_value_list_c) etisserant@0: etisserant@0: /* enumerated_type_name '#' identifier */ etisserant@0: SYM_REF2(enumerated_value_c, type, value) etisserant@0: etisserant@0: /* identifier ':' array_spec_init */ etisserant@0: SYM_REF2(array_type_declaration_c, identifier, array_spec_init) etisserant@0: etisserant@0: /* array_specification [ASSIGN array_initialization} */ etisserant@0: /* array_initialization may be NULL ! */ etisserant@0: SYM_REF2(array_spec_init_c, array_specification, array_initialization) etisserant@0: etisserant@0: /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */ etisserant@0: SYM_REF2(array_specification_c, array_subrange_list, non_generic_type_name) etisserant@0: etisserant@0: /* helper symbol for array_specification */ etisserant@0: /* array_subrange_list ',' subrange */ etisserant@0: SYM_LIST(array_subrange_list_c) etisserant@0: etisserant@0: /* array_initialization: '[' array_initial_elements_list ']' */ etisserant@0: /* helper symbol for array_initialization */ etisserant@0: /* array_initial_elements_list ',' array_initial_elements */ etisserant@0: SYM_LIST(array_initial_elements_list_c) etisserant@0: etisserant@0: /* integer '(' [array_initial_element] ')' */ etisserant@0: /* array_initial_element may be NULL ! */ etisserant@0: SYM_REF2(array_initial_elements_c, integer, array_initial_element) etisserant@0: #endif etisserant@0: etisserant@0: /* structure_type_name ':' structure_specification */ etisserant@0: //SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification) etisserant@0: void *visit(structure_type_declaration_c *symbol) { etisserant@0: TRACE("structure_type_declaration_c"); etisserant@0: /* add this type declaration to the type symbol table... */ etisserant@0: type_symtable.insert(symbol->structure_type_name, symbol->structure_specification); etisserant@0: etisserant@0: s4o.print("typedef "); etisserant@0: symbol->structure_specification->accept(*this); etisserant@0: s4o.print(" "); etisserant@0: symbol->structure_type_name->accept(*this); etisserant@0: s4o.print(";\n"); etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* structure_type_name ASSIGN structure_initialization */ etisserant@0: /* structure_initialization may be NULL ! */ etisserant@0: //SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization) etisserant@0: void *visit(initialized_structure_c *symbol) { etisserant@0: TRACE("initialized_structure_c"); etisserant@0: symbol->structure_type_name->accept(*this); etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* helper symbol for structure_declaration */ etisserant@0: /* structure_declaration: STRUCT structure_element_declaration_list END_STRUCT */ etisserant@0: /* structure_element_declaration_list structure_element_declaration ';' */ etisserant@0: //SYM_LIST(structure_element_declaration_list_c) etisserant@0: void *visit(structure_element_declaration_list_c *symbol) { etisserant@0: TRACE("structure_element_declaration_list_c"); etisserant@0: s4o.print("struct {\n"); etisserant@0: s4o.indent_right(); etisserant@0: s4o.print(s4o.indent_spaces); etisserant@0: etisserant@0: print_list(symbol); etisserant@0: etisserant@0: s4o.indent_left(); etisserant@0: s4o.print(s4o.indent_spaces); etisserant@0: s4o.print("}"); etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* structure_element_name ':' spec_init */ etisserant@0: //SYM_REF2(structure_element_declaration_c, structure_element_name, spec_init) etisserant@0: void *visit(structure_element_declaration_c *symbol) { etisserant@0: TRACE("structure_element_declaration_c"); etisserant@0: etisserant@0: symbol->spec_init->accept(*this); etisserant@0: s4o.print(" "); etisserant@0: symbol->structure_element_name->accept(*this); etisserant@0: s4o.print(";\n"); etisserant@0: s4o.print(s4o.indent_spaces); etisserant@0: etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* helper symbol for structure_initialization */ etisserant@0: /* structure_initialization: '(' structure_element_initialization_list ')' */ etisserant@0: /* structure_element_initialization_list ',' structure_element_initialization */ etisserant@0: //SYM_LIST(structure_element_initialization_list_c) etisserant@0: void *visit(structure_element_initialization_list_c *symbol) { etisserant@0: TRACE("structure_element_initialization_list_c"); etisserant@0: etisserant@0: // TODO ??? etisserant@0: ERROR; etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: /* structure_element_name ASSIGN value */ etisserant@0: //SYM_REF2(structure_element_initialization_c, structure_element_name, value) etisserant@0: void *visit(structure_element_initialization_c *symbol) { etisserant@0: TRACE("structure_element_initialization_c"); etisserant@0: etisserant@0: // TODO ??? etisserant@0: ERROR; etisserant@0: return NULL; etisserant@0: } etisserant@0: etisserant@0: #if 0 etisserant@0: /* string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */ etisserant@0: /* etisserant@0: * NOTE: etisserant@0: * (Summary: Contrary to what is expected, the etisserant@0: * string_type_declaration_c is not used to store etisserant@0: * simple string type declarations that do not include etisserant@0: * size limits. etisserant@0: * For e.g.: etisserant@0: * str1_type: STRING := "hello!" etisserant@0: * will be stored in a simple_type_declaration_c etisserant@0: * instead of a string_type_declaration_c. etisserant@0: * The following: etisserant@0: * str2_type: STRING [64] := "hello!" etisserant@0: * will be stored in a sring_type_declaration_c etisserant@0: * etisserant@0: * Read on for why this is done... etisserant@0: * End Summary) etisserant@0: * etisserant@0: * According to the spec, the valid construct etisserant@0: * TYPE new_str_type : STRING := "hello!"; END_TYPE etisserant@0: * has two possible routes to type_declaration... etisserant@0: * etisserant@0: * Route 1: etisserant@0: * type_declaration: single_element_type_declaration etisserant@0: * single_element_type_declaration: simple_type_declaration etisserant@0: * simple_type_declaration: identifier ':' simple_spec_init etisserant@0: * simple_spec_init: simple_specification ASSIGN constant etisserant@0: * (shift: identifier <- 'new_str_type') etisserant@0: * simple_specification: elementary_type_name etisserant@0: * elementary_type_name: STRING etisserant@0: * (shift: elementary_type_name <- STRING) etisserant@0: * (reduce: simple_specification <- elementary_type_name) etisserant@0: * (shift: constant <- "hello!") etisserant@0: * (reduce: simple_spec_init: simple_specification ASSIGN constant) etisserant@0: * (reduce: ...) etisserant@0: * etisserant@0: * etisserant@0: * Route 2: etisserant@0: * type_declaration: string_type_declaration etisserant@0: * string_type_declaration: identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init etisserant@0: * (shift: identifier <- 'new_str_type') etisserant@0: * elementary_string_type_name: STRING etisserant@0: * (shift: elementary_string_type_name <- STRING) etisserant@0: * (shift: string_type_declaration_size <- empty ) etisserant@0: * string_type_declaration_init: ASSIGN character_string etisserant@0: * (shift: character_string <- "hello!") etisserant@0: * (reduce: string_type_declaration_init <- ASSIGN character_string) etisserant@0: * (reduce: string_type_declaration <- identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init ) etisserant@0: * (reduce: type_declaration <- string_type_declaration) etisserant@0: * etisserant@0: * etisserant@0: * At first glance it seems that removing route 1 would make etisserant@0: * the most sense. Unfortunately the construct 'simple_spec_init' etisserant@0: * shows up multiple times in other rules, so changing this construct etisserant@0: * would also mean changing all the rules in which it appears. etisserant@0: * I (Mario) therefore chose to remove route 2 instead. This means etisserant@0: * that the above declaration gets stored in a etisserant@0: * simple_type_declaration_c, and not in a string_type_declaration_c etisserant@0: * as would be expected! etisserant@0: */ etisserant@0: /* string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */ etisserant@0: SYM_REF4(string_type_declaration_c, string_type_name, etisserant@0: elementary_string_type_name, etisserant@0: string_type_declaration_size, etisserant@0: string_type_declaration_init) /* may be == NULL! */ etisserant@0: #endif etisserant@0: etisserant@0: /*********************/ etisserant@0: /* B 1.4 - Variables */ etisserant@0: /*********************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /********************************************/ etisserant@0: /* B.1.4.1 Directly Represented Variables */ etisserant@0: /********************************************/ etisserant@0: // direct_variable: direct_variable_token {$$ = new direct_variable_c($1);}; etisserant@0: void *visit(direct_variable_c *symbol) { etisserant@0: TRACE("direct_variable_c"); etisserant@0: /* Do not use print_token() as it will change everything into uppercase */ etisserant@0: if (strlen(symbol->value) == 0) ERROR; etisserant@0: return s4o.print(symbol->value + 1); etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /*************************************/ etisserant@0: /* B.1.4.2 Multi-element Variables */ etisserant@0: /*************************************/ etisserant@0: /* done in base class(es) */ etisserant@0: etisserant@0: /******************************************/ etisserant@0: /* B 1.4.3 - Declaration & Initialisation */ etisserant@0: /******************************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /**************************************/ etisserant@0: /* B.1.5 - Program organization units */ etisserant@0: /**************************************/ etisserant@0: /***********************/ etisserant@0: /* B 1.5.1 - Functions */ etisserant@0: /***********************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /*****************************/ etisserant@0: /* B 1.5.2 - Function Blocks */ etisserant@0: /*****************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /**********************/ etisserant@0: /* B 1.5.3 - Programs */ etisserant@0: /**********************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /*********************************************/ etisserant@0: /* B.1.6 Sequential function chart elements */ etisserant@0: /*********************************************/ etisserant@0: etisserant@0: /********************************/ etisserant@0: /* B 1.7 Configuration elements */ etisserant@0: /********************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /****************************************/ etisserant@0: /* B.2 - Language IL (Instruction List) */ etisserant@0: /****************************************/ etisserant@0: /***********************************/ etisserant@0: /* B 2.1 Instructions and Operands */ etisserant@0: /***********************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /*******************/ etisserant@0: /* B 2.2 Operators */ etisserant@0: /*******************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: etisserant@0: /***************************************/ etisserant@0: /* B.3 - Language ST (Structured Text) */ etisserant@0: /***************************************/ etisserant@0: /***********************/ etisserant@0: /* B 3.1 - Expressions */ etisserant@0: /***********************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /********************/ etisserant@0: /* B 3.2 Statements */ etisserant@0: /********************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /*********************************/ etisserant@0: /* B 3.2.1 Assignment Statements */ etisserant@0: /*********************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /*****************************************/ etisserant@0: /* B 3.2.2 Subprogram Control Statements */ etisserant@0: /*****************************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /********************************/ etisserant@0: /* B 3.2.3 Selection Statements */ etisserant@0: /********************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: /********************************/ etisserant@0: /* B 3.2.4 Iteration Statements */ etisserant@0: /********************************/ etisserant@0: /* leave for derived classes... */ etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: }; /* generate_cc_typedecl_c */ etisserant@0: etisserant@0: etisserant@0: