stage1_2/iec_bison.yy
changeset 1016 91bef6704b44
parent 1014 a61f8f58f612
child 1019 1e3cefbbdee2
--- a/stage1_2/iec_bison.yy	Thu May 26 14:26:33 2016 +0100
+++ b/stage1_2/iec_bison.yy	Thu May 26 15:00:20 2016 +0100
@@ -373,6 +373,32 @@
 %type  <leaf>	prev_declared_derived_function_block_name
 %type  <leaf>	prev_declared_program_type_name
 
+/* Tokens used to help resolve a reduce/reduce conflict */
+/* The mentioned conflict only arises due to a non-standard feature added to matiec.
+ * Namely, the permission to call functions returning VOID as an ST statement.
+ *   e.g.:   FUNCTION foo: VOID
+ *             VAR_INPUT i: INT; END_VAR;
+ *             ...
+ *           END_FUNCTION
+ *
+ *           FUNCTION BAR: BOOL
+ *             VAR b: bool; END_VAR
+ *             foo(i:=42);   <--- Calling foo outside an expression. Function invocation is considered an ST statement!!
+ *           END_FUNCTION
+ *
+ *  The above function invocation may also be reduced to a formal IL function invocation, so we get a 
+ *  reduce/reduce conflict to st_statement_list/instruction_list  (or something equivalent).
+ *
+ *  We solve this by having flex determine if it is ST or IL invocation (ST ends with a ';' !!).
+ *  At the start of a function/FB/program body, flex will tell bison whether to expect ST or IL code!
+ *  This is why we need the following two tokens!
+ *
+ *  NOTE: flex was already determing whther it was parsing ST or IL code as it can only send 
+ *        EOL tokens when parsing IL. However, did this silently without telling bison about this.
+ *        Now, it does
+ */
+%token          start_ST_body_token
+%token          start_IL_body_token
 
 
 
@@ -5013,7 +5039,7 @@
 	}
 /* | FUNCTION derived_function_name ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION */
 | function_name_declaration ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION
-	{$$ = new function_declaration_c($1, new void_c(locloc(@3)), $4, $5, locloc(@$));
+	{$$ = new function_declaration_c($1, new void_type_name_c(locloc(@3)), $4, $5, locloc(@$));
 	 if (!runtime_options.disable_implicit_en_eno) 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();
@@ -5183,8 +5209,8 @@
 
 
 function_body:
-  statement_list	{$$ = $1;} /* if we leave it for the default action we get a type clash! */
-| instruction_list	{$$ = $1;} /* if we leave it for the default action we get a type clash! */
+  start_ST_body_token statement_list	{$$ = $2;}
+| start_IL_body_token instruction_list	{$$ = $2;}
 /*
 | ladder_diagram
 | function_block_diagram
@@ -5257,7 +5283,7 @@
 	{$$ = 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++;}	
+	{$$ = NULL; print_err_msg(locf(@1), locl(@2), "expecting END_FUNCTION_BLOCK before end of file."); yynerrs++;}	
 | FUNCTION_BLOCK error END_FUNCTION_BLOCK
 	{$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function block declaration."); yyerrok;}
 /* ERROR_CHECK_END */
@@ -5366,9 +5392,21 @@
 
 
 function_block_body:
-  statement_list	{$$ = $1;}
-| instruction_list	{$$ = $1;}
-| sequential_function_chart	{$$ = $1;}
+  /* NOTE: start_ST_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in ST
+   *       start_IL_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in IL
+   *     These tokens help remove a reduce/reduce conflict in bison, between a formal function invocation in IL, and a
+   *     function invocation used as a statement (a non-standard extension added to matiec) 
+   *       e.g: FUNCTION_BLOCK foo
+   *            VAR ... END_VAR
+   *              func_returning_void(in1 := 3        
+   *                                 );               --> only the presence or absence of ';' will determine whether this is a IL or ST 
+   *                                                      function invocation. (In standard ST this would be ilegal, in matiec we allow it 
+   *                                                      when activated by a command line option)
+   *            END_FUNCTION
+   */
+  start_ST_body_token statement_list	{$$ = $2;}  
+| start_IL_body_token instruction_list	{$$ = $2;}
+| sequential_function_chart		{$$ = $1;}
 /*
 | ladder_diagram
 | function_block_diagram
@@ -7867,6 +7905,7 @@
 | subprogram_control_statement
 | selection_statement
 | iteration_statement
+| function_invocation /* TODO: this must be conditional on command line parameter! */
 ;