diff -r f53ea4c8621c -r e984cfdf3b10 stage1_2/iec_bison.yy --- a/stage1_2/iec_bison.yy Sat Nov 29 12:10:34 2014 +0000 +++ b/stage1_2/iec_bison.yy Sat Nov 29 13:43:20 2014 +0000 @@ -1141,6 +1141,7 @@ %type prev_declared_resource_name %token prev_declared_resource_name_token +%type prev_declared_configuration_name %token prev_declared_configuration_name_token // %type prev_declared_task_name @@ -1605,20 +1606,20 @@ ; -prev_declared_variable_name : prev_declared_variable_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_fb_name : prev_declared_fb_name_token {$$ = new identifier_c($1, locloc(@$));}; - -prev_declared_simple_type_name : prev_declared_simple_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; -prev_declared_subrange_type_name : prev_declared_subrange_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; +prev_declared_variable_name: prev_declared_variable_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_fb_name: prev_declared_fb_name_token {$$ = new identifier_c($1, locloc(@$));}; + +prev_declared_simple_type_name: prev_declared_simple_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; +prev_declared_subrange_type_name: prev_declared_subrange_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; -prev_declared_array_type_name : prev_declared_array_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; -prev_declared_structure_type_name : prev_declared_structure_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; -prev_declared_string_type_name : prev_declared_string_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; -prev_declared_ref_type_name : prev_declared_ref_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; /* defined in IEC 61131-3 v3 */ - -prev_declared_derived_function_name : prev_declared_derived_function_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_array_type_name: prev_declared_array_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; +prev_declared_structure_type_name: prev_declared_structure_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; +prev_declared_string_type_name: prev_declared_string_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; +prev_declared_ref_type_name: prev_declared_ref_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; /* defined in IEC 61131-3 v3 */ + +prev_declared_derived_function_name: prev_declared_derived_function_name_token {$$ = new identifier_c($1, locloc(@$));}; prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_program_type_name : prev_declared_program_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_program_type_name: prev_declared_program_type_name_token {$$ = new identifier_c($1, locloc(@$));}; @@ -2605,12 +2606,25 @@ simple_type_declaration: /* simple_type_name ':' simple_spec_init */ /* To understand why simple_spec_init was brocken up into its consituent components in the following rules, please see note in the definition of 'enumerated_type_declaration'. */ +/* PRE_PARSING: The rules expected to be applied by the preparser. */ identifier ':' simple_specification {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} + {if (!get_preparse_state()) ERROR;} +| identifier ':' elementary_type_name {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} ASSIGN constant + {if (!get_preparse_state()) ERROR;} +| identifier ':' prev_declared_simple_type_name {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} ASSIGN constant + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| prev_declared_simple_type_name ':' simple_spec_init {$$ = new simple_type_declaration_c($1, $3, locloc(@$));} -| identifier ':' elementary_type_name {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} ASSIGN constant - {$$ = new simple_type_declaration_c($1, new simple_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));} -| identifier ':' prev_declared_simple_type_name {library_element_symtable.insert($1, prev_declared_simple_type_name_token);} ASSIGN constant - {$$ = new simple_type_declaration_c($1, new simple_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));} +/* These three rules can now be safely replaced by the original rule abvoe!! */ +/* +| prev_declared_simple_type_name ':' simple_specification + {$$ = new simple_type_declaration_c($1, $3, locloc(@$));} +| prev_declared_simple_type_name ':' elementary_type_name ASSIGN constant + {$$ = new simple_type_declaration_c($1, new simple_spec_init_c($3, $5, locf(@3), locl(@5)), locloc(@$));} +| prev_declared_simple_type_name ':' prev_declared_simple_type_name ASSIGN constant + {$$ = new simple_type_declaration_c($1, new simple_spec_init_c($3, $5, locf(@3), locl(@5)), locloc(@$));} +*/ /* ERROR_CHECK_BEGIN */ | error ':' simple_spec_init {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for data type declaration.");yyerrok;} @@ -2683,10 +2697,12 @@ subrange_type_declaration: /* subrange_type_name ':' subrange_spec_init */ - identifier ':' subrange_spec_init - {$$ = new subrange_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_subrange_type_name_token); - } +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + identifier ':' subrange_spec_init {library_element_symtable.insert($1, prev_declared_subrange_type_name_token);} + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| prev_declared_subrange_type_name ':' subrange_spec_init + {$$ = new subrange_type_declaration_c($1, $3, locloc(@$));} /* ERROR_CHECK_BEGIN */ | error ':' subrange_spec_init {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for subrange type declaration."); yyerrok;} @@ -2758,10 +2774,22 @@ * identifier ':' enumerated_spec_init * and include the library_element_symtable.insert(...) code in the rule actions! */ +/* PRE_PARSING: The rules expected to be applied by the preparser. */ identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} + {if (!get_preparse_state()) ERROR;} +| identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} ASSIGN enumerated_value + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +/* Since the enumerated type name is placed in the library_element_symtable during preparsing, we can now safely use the single rule: */ +| prev_declared_enumerated_type_name ':' enumerated_spec_init + {$$ = new enumerated_type_declaration_c($1, $3, locloc(@$));} + /* These two rules are equivalent to the above rule */ +/* +| prev_declared_enumerated_type_name ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} {$$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, NULL, locloc(@3)), locloc(@$));} -| identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} ASSIGN enumerated_value +| prev_declared_enumerated_type_name ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} ASSIGN enumerated_value {$$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));} +*/ /* ERROR_CHECK_BEGIN */ | error ':' enumerated_spec_init {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for enumerated type declaration."); yyerrok;} @@ -2849,10 +2877,12 @@ array_type_declaration: /* array_type_name ':' array_spec_init */ - identifier ':' array_spec_init - {$$ = new array_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_array_type_name_token); - } +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + identifier ':' array_spec_init {library_element_symtable.insert($1, prev_declared_array_type_name_token);} + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| prev_declared_array_type_name ':' array_spec_init + {$$ = new array_type_declaration_c($1, $3, locloc(@$));} /* ERROR_CHECK_BEGIN */ | identifier array_spec_init {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in array type declaration."); yynerrs++;} @@ -3003,10 +3033,12 @@ structure_type_declaration: /* structure_type_name ':' structure_specification */ - identifier ':' structure_specification - {$$ = new structure_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_structure_type_name_token); - } +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + identifier ':' structure_specification {library_element_symtable.insert($1, prev_declared_structure_type_name_token);} + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| prev_declared_structure_type_name ':' structure_specification + {$$ = new structure_type_declaration_c($1, $3, locloc(@$));} /* ERROR_CHECK_BEGIN */ | identifier structure_specification {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in structure type declaration."); yynerrs++;} @@ -3188,10 +3220,12 @@ string_type_declaration: /* string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */ - identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init - {$$ = new string_type_declaration_c($1, $3, $4, $5, locloc(@$)); - library_element_symtable.insert($1, prev_declared_string_type_name_token); - } +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init {library_element_symtable.insert($1, prev_declared_string_type_name_token);} + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| prev_declared_string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init + {$$ = new string_type_declaration_c($1, $3, $4, $5, locloc(@$));} ; @@ -3316,10 +3350,12 @@ ; ref_type_decl: /* defined in IEC 61131-3 v3 */ - identifier ':' ref_spec_init - {$$ = new ref_type_decl_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_ref_type_name_token); - } +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + identifier ':' ref_spec_init {library_element_symtable.insert($1, prev_declared_ref_type_name_token);} + {if (!get_preparse_state()) ERROR;} +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| prev_declared_ref_type_name ':' ref_spec_init + {$$ = new ref_type_decl_c($1, $3, locloc(@$));} ; @@ -4820,60 +4856,48 @@ derived_function_name: - identifier + identifier /* will never occur during normal parsing, only needed for preparsing to change it to a prev_declared_derived_function_name! */ | prev_declared_derived_function_name {$$ = $1; - if (!allow_function_overloading) { - fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($1))->value); - ERROR; - } + if (get_preparse_state() && !allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;} } | AND {$$ = new identifier_c("AND", locloc(@$)); - if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"AND\" not allowed. Invalid identifier\n"); + if (!allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;} } | OR {$$ = new identifier_c("OR", locloc(@$)); - if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"OR\" not allowed. Invalid identifier\n"); + if (!allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;} } | XOR {$$ = new identifier_c("XOR", locloc(@$)); - if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"XOR\" not allowed. Invalid identifier\n"); + if (!allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;} } | NOT {$$ = new identifier_c("NOT", locloc(@$)); - if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"NOT\" not allowed. Invalid identifier\n"); + if (!allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;} } | MOD {$$ = new identifier_c("MOD", locloc(@$)); - if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"MOD\" not allowed. Invalid identifier\n"); + if (!allow_function_overloading) {print_err_msg(locloc(@$), "Function overloading not allowed. Invalid identifier.\n"); yynerrs++;} } ; function_declaration: /* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ - function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + FUNCTION derived_function_name END_FUNCTION /* rule that is only expected to be used during preparse state => MUST print an error if used outside preparse() state!! */ + {$$ = NULL; + if (get_preparse_state()) {library_element_symtable.insert($2, prev_declared_derived_function_name_token);} + else {print_err_msg(locl(@1), locf(@3), "FUNCTION with no variable declarations and no body."); yynerrs++;} + } +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION {$$ = new function_declaration_c($1, $3, $4, $5, locloc(@$)); add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ variable_name_symtable.pop(); direct_variable_symtable.pop(); - if (allow_function_overloading) { - switch (library_element_symtable.find_value($1)) { - case prev_declared_derived_function_name_token: - /* do nothing, already in map. */ - break; - case BOGUS_TOKEN_ID: - /* Not yet in map. Must insert...*/ - library_element_symtable.insert($1, prev_declared_derived_function_name_token); - break; - default: - /* Already in map but associated with something else other than a funtion name! */ - ERROR; - } - } else { - library_element_symtable.insert($1, prev_declared_derived_function_name_token); - } } /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ | function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION @@ -4881,15 +4905,6 @@ add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ variable_name_symtable.pop(); direct_variable_symtable.pop(); - if (allow_function_overloading) { - switch (library_element_symtable.find_value($1)) { - case prev_declared_derived_function_name_token: /* do nothing, already in map. */ break; - case BOGUS_TOKEN_ID: library_element_symtable.insert($1, prev_declared_derived_function_name_token); break; - default: ERROR; - } - } else { - library_element_symtable.insert($1, prev_declared_derived_function_name_token); - } } /* ERROR_CHECK_BEGIN */ | function_name_declaration elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION @@ -4954,6 +4969,7 @@ * the parser to reduce it, before parsing the function body! */ function_name_declaration: + /* FUNCTION derived_function_name */ FUNCTION derived_function_name {$$ = $2; /* the function name functions as a @@ -5087,10 +5103,16 @@ function_block_declaration: - FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + FUNCTION_BLOCK derived_function_block_name END_FUNCTION_BLOCK /* rule that is only expected to be used during preparse state => MUST print an error if used outside preparse() state!! */ + {$$ = NULL; + if (get_preparse_state()) {library_element_symtable.insert($2, prev_declared_derived_function_block_name_token);} + else {print_err_msg(locl(@1), locf(@3), "FUNCTION_BLOCK with no variable declarations and no body."); yynerrs++;} + } +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| FUNCTION_BLOCK prev_declared_derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK {$$ = new function_block_declaration_c($2, $3, $4, locloc(@$)); add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ - library_element_symtable.insert($2, prev_declared_derived_function_block_name_token); /* Clear the variable_name_symtable. Since * we have finished parsing the function block, * the variable names are now out of scope, so @@ -5108,8 +5130,10 @@ {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared in function declaration."); yynerrs++;} | FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list END_FUNCTION_BLOCK {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no body defined in function block declaration."); yynerrs++;} +/* Rule already covered by the rule to handle the preparse state! | FUNCTION_BLOCK derived_function_block_name END_FUNCTION_BLOCK {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} +*/ | FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_OF_INPUT {$$ = NULL; print_err_msg(locf(@1), locl(@2), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} | FUNCTION_BLOCK error END_FUNCTION_BLOCK @@ -5240,9 +5264,15 @@ program_declaration: - PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + PROGRAM program_type_name END_PROGRAM /* rule that is only expected to be used during preparse state => MUST print an error if used outside preparse() state!! */ + {$$ = NULL; + if (get_preparse_state()) {library_element_symtable.insert($2, prev_declared_program_type_name_token);} + else {print_err_msg(locl(@1), locf(@3), "PROGRAM with no variable declarations and no body."); yynerrs++;} + } +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| PROGRAM prev_declared_program_type_name program_var_declarations_list function_block_body END_PROGRAM {$$ = new program_declaration_c($2, $3, $4, locloc(@$)); - library_element_symtable.insert($2, prev_declared_program_type_name_token); /* Clear the variable_name_symtable. Since * we have finished parsing the program declaration, * the variable names are now out of scope, so @@ -5256,13 +5286,15 @@ {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no program name defined in program declaration.");} | PROGRAM error program_var_declarations_list function_block_body END_PROGRAM {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid program name in program declaration."); yyerrok;} -| PROGRAM program_type_name function_block_body END_PROGRAM +| PROGRAM prev_declared_program_type_name function_block_body END_PROGRAM {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared in program declaration."); yynerrs++;} -| PROGRAM program_type_name program_var_declarations_list END_PROGRAM +| PROGRAM prev_declared_program_type_name program_var_declarations_list END_PROGRAM {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no body defined in program declaration."); yynerrs++;} -| PROGRAM program_type_name END_PROGRAM +/* Rule already covered by the rule to handle the preparse state! +| PROGRAM prev_declared_program_type_name END_PROGRAM {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in program declaration."); yynerrs++;} -| PROGRAM program_type_name program_var_declarations_list function_block_body END_OF_INPUT +*/ +| PROGRAM prev_declared_program_type_name program_var_declarations_list function_block_body END_OF_INPUT {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed program declaration."); yynerrs++;} | PROGRAM error END_PROGRAM {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in program declaration."); yyerrok;} @@ -5741,10 +5773,11 @@ * If it ever becomes necessary to change this interpretation of * the syntax, then this section of the syntax parser must be updated! */ -prev_declared_global_var_name: prev_declared_global_var_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_resource_name: prev_declared_resource_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_program_name: prev_declared_program_name_token {$$ = new identifier_c($1, locloc(@$));}; -// prev_declared_task_name: prev_declared_task_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_global_var_name: prev_declared_global_var_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_resource_name: prev_declared_resource_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_program_name: prev_declared_program_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_configuration_name: prev_declared_configuration_name_token {$$ = new identifier_c($1, locloc(@$));}; +// prev_declared_task_name: prev_declared_task_name_token {$$ = new identifier_c($1, locloc(@$));}; @@ -5768,7 +5801,14 @@ resource_type_name: any_identifier; configuration_declaration: - CONFIGURATION configuration_name +/* PRE_PARSING: The rules expected to be applied by the preparser. */ + CONFIGURATION configuration_name END_CONFIGURATION /* rule that is only expected to be used during preparse state */ + {$$ = NULL; + if (get_preparse_state()) {library_element_symtable.insert($2, prev_declared_configuration_name_token);} + else {print_err_msg(locl(@1), locf(@3), "no resource(s) nor program(s) defined in configuration declaration."); yynerrs++;} + } +/* STANDARD_PARSING: The rules expected to be applied after the preparser has finished. */ +| CONFIGURATION prev_declared_configuration_name global_var_declarations_list single_resource_declaration {variable_name_symtable.pop(); @@ -5777,18 +5817,16 @@ optional_instance_specific_initializations END_CONFIGURATION {$$ = new configuration_declaration_c($2, $3, $4, $6, $7, locloc(@$)); - library_element_symtable.insert($2, prev_declared_configuration_name_token); variable_name_symtable.pop(); direct_variable_symtable.pop(); } -| CONFIGURATION configuration_name +| CONFIGURATION prev_declared_configuration_name global_var_declarations_list resource_declaration_list optional_access_declarations optional_instance_specific_initializations END_CONFIGURATION {$$ = new configuration_declaration_c($2, $3, $4, $5, $6, locloc(@$)); - library_element_symtable.insert($2, prev_declared_configuration_name_token); variable_name_symtable.pop(); direct_variable_symtable.pop(); } @@ -5825,12 +5863,14 @@ optional_instance_specific_initializations END_CONFIGURATION {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid configuration name defined in configuration declaration."); yyerrok;} +/* Rule already covered by the rule to handle the preparse state! | CONFIGURATION configuration_name global_var_declarations_list optional_access_declarations optional_instance_specific_initializations END_CONFIGURATION {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no resource(s) defined in configuration declaration."); yynerrs++;} +*/ | CONFIGURATION configuration_name global_var_declarations_list error @@ -8486,28 +8526,13 @@ extern const char *INCLUDE_DIRECTORIES[]; -int stage2__(const char *filename, - symbol_c **tree_root_ref - ) { - char *libfilename = NULL; - - if (runtime_options.includedir != NULL) { - INCLUDE_DIRECTORIES[0] = runtime_options.includedir; - } - - /* first parse the standard library file... */ - /* Do not debug the standard library, even if debug flag is set! */ - /* +static int parse_files(const char *libfilename, const char *filename) { + /* first parse the standard library file... */ + /* Do not debug the standard library, even if debug flag is set! #if YYDEBUG yydebug = 1; #endif */ - - if ((libfilename = strdup3(INCLUDE_DIRECTORIES[0], "/", LIBFILE)) == NULL) { - fprintf (stderr, "Out of memory. Bailing out!\n"); - return -1; - } - FILE *libfile = NULL; if((libfile = parse_file(libfilename)) == NULL) { char *errmsg = strdup2("Error opening library file ", libfilename); @@ -8524,19 +8549,16 @@ allow_ref_dereferencing = runtime_options.ref_standard_extensions; allow_ref_to_any = runtime_options.ref_nonstand_extensions; allow_ref_to_in_derived_datatypes = runtime_options.ref_nonstand_extensions; - if (yyparse() != 0) - ERROR; + if (yyparse() != 0) ERROR; fclose(libfile); - if (yynerrs > 0) { - fprintf (stderr, "\n%d error(s) found in %s. Bailing out!\n", yynerrs /* global variable */, libfilename); - ERROR; + if (yynerrs > 0) { /* NOTE: yynerrs is a global variable */ + /* Hopefully the libraries do not contain any errors, so this should not occur! */ + fprintf (stderr, "\n%d error(s) found in %s. Bailing out!\n", yynerrs, libfilename); + return -2; } - free(libfilename); - - /* if by any chance the library is not complete, we - * now add the missing reserved keywords to the list!!! - */ + + /* if by any chance the library is not complete, we now add the missing reserved keywords to the list!!! */ for(int i = 0; standard_function_block_names[i] != NULL; i++) if (library_element_symtable.find_value(standard_function_block_names[i]) == library_element_symtable.end_value()) @@ -8551,7 +8573,7 @@ char *errmsg = strdup2("Error opening main file ", filename); perror(errmsg); free(errmsg); - return -1; + return -3; } allow_function_overloading = false; @@ -8573,7 +8595,79 @@ fprintf (stderr, "\n%d error(s) found. Bailing out!\n", yynerrs /* global variable */); exit(EXIT_FAILURE); } + + return 0; +} + + + + + +/* We parse the input source code twice!! + * 1st pass --> Pre-parsing + * ------------------------- + * The intention of the first pass is to fill up the library_element_symtable with the names of all + * the POUs (Functions, FBs, Programs and Configurations), as well as all the Derived Datatypes. + * + * During this pass POUs are only parsed until their name is obtained, and the remaining source + * code (variable declarations and body) is completely thrown away by flex. Datatype declarations + * however are parsed normally! + * + * At the end of the pre-parsing, the AST will contain only the derived datatype declarations, + * and this tree will be trown away (by simply resetting tree_root = NULL). + * More importantly, the library_element_symtable will contain the names of all the POUs and + * derived datatypes. + * + * 2st pass --> Normal parsing + * ---------------------------- + * In this second parse the whole source code is parsed correctly, and the AST is generated + * completely. + * + * However, if the pre-parsing has been done before this normal parsing, the POUs may appear + * in the source code in any order, as calling a POU (e.g. calling a function) that has not yet + * been declared will no longer generate a parsing error because the name of the function being + * called is already in the library_element_symtable. + * + * Declaring variables of datatypes that have not yet been declared will also be possible, as the + * datatypes will also already be in the library_element_symtable! + */ + +int stage2__(const char *filename, + symbol_c **tree_root_ref + ) { + char *libfilename = NULL; + + /* Determine the full path name of the standard library file... */ + if (runtime_options.includedir != NULL) + INCLUDE_DIRECTORIES[0] = runtime_options.includedir; + + if ((libfilename = strdup3(INCLUDE_DIRECTORIES[0], "/", LIBFILE)) == NULL) { + fprintf (stderr, "Out of memory. Bailing out!\n"); + exit(EXIT_FAILURE); + } + + /*******************************/ + /* Do the PRE parsing run...! */ + /*******************************/ + // fprintf (stderr, "----> Starting pre-parsing!\n"); + tree_root = NULL; + set_preparse_state(); + if (parse_files(libfilename, filename) < 0) + exit(EXIT_FAILURE); + // TODO: delete the current AST. For the moment, we leave all the objects in memory (not much of an issue in a program that always runs to completion). + + /*******************************/ + /* Do the main parsing run...! */ + /*******************************/ + // fprintf (stderr, "----> Starting normal parsing!\n"); + tree_root = NULL; + rst_preparse_state(); + if (parse_files(libfilename, filename) < 0) + exit(EXIT_FAILURE); + + /* Final clean-up... */ + free(libfilename); if (tree_root_ref != NULL) *tree_root_ref = tree_root;