stage1_2/iec_bison.yy
changeset 952 e984cfdf3b10
parent 946 c012a64dc2fa
child 953 66697c05a147
--- 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  <leaf>	prev_declared_resource_name
 %token  <ID>	prev_declared_resource_name_token
 
+%type  <leaf>	prev_declared_configuration_name
 %token  <ID>	prev_declared_configuration_name_token
 
 // %type  <leaf>	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;