371 %token <ID> prev_declared_program_type_name_token |
371 %token <ID> prev_declared_program_type_name_token |
372 %type <leaf> prev_declared_derived_function_name |
372 %type <leaf> prev_declared_derived_function_name |
373 %type <leaf> prev_declared_derived_function_block_name |
373 %type <leaf> prev_declared_derived_function_block_name |
374 %type <leaf> prev_declared_program_type_name |
374 %type <leaf> prev_declared_program_type_name |
375 |
375 |
|
376 /* Tokens used to help resolve a reduce/reduce conflict */ |
|
377 /* The mentioned conflict only arises due to a non-standard feature added to matiec. |
|
378 * Namely, the permission to call functions returning VOID as an ST statement. |
|
379 * e.g.: FUNCTION foo: VOID |
|
380 * VAR_INPUT i: INT; END_VAR; |
|
381 * ... |
|
382 * END_FUNCTION |
|
383 * |
|
384 * FUNCTION BAR: BOOL |
|
385 * VAR b: bool; END_VAR |
|
386 * foo(i:=42); <--- Calling foo outside an expression. Function invocation is considered an ST statement!! |
|
387 * END_FUNCTION |
|
388 * |
|
389 * The above function invocation may also be reduced to a formal IL function invocation, so we get a |
|
390 * reduce/reduce conflict to st_statement_list/instruction_list (or something equivalent). |
|
391 * |
|
392 * We solve this by having flex determine if it is ST or IL invocation (ST ends with a ';' !!). |
|
393 * At the start of a function/FB/program body, flex will tell bison whether to expect ST or IL code! |
|
394 * This is why we need the following two tokens! |
|
395 * |
|
396 * NOTE: flex was already determing whther it was parsing ST or IL code as it can only send |
|
397 * EOL tokens when parsing IL. However, did this silently without telling bison about this. |
|
398 * Now, it does |
|
399 */ |
|
400 %token start_ST_body_token |
|
401 %token start_IL_body_token |
376 |
402 |
377 |
403 |
378 |
404 |
379 /**********************************************************************************/ |
405 /**********************************************************************************/ |
380 /* B XXX - Things that are missing from the standard, but should have been there! */ |
406 /* B XXX - Things that are missing from the standard, but should have been there! */ |
5011 direct_variable_symtable.pop(); |
5037 direct_variable_symtable.pop(); |
5012 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
5038 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
5013 } |
5039 } |
5014 /* | FUNCTION derived_function_name ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION */ |
5040 /* | FUNCTION derived_function_name ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION */ |
5015 | function_name_declaration ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION |
5041 | function_name_declaration ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION |
5016 {$$ = new function_declaration_c($1, new void_c(locloc(@3)), $4, $5, locloc(@$)); |
5042 {$$ = new function_declaration_c($1, new void_type_name_c(locloc(@3)), $4, $5, locloc(@$)); |
5017 if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ |
5043 if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ |
5018 variable_name_symtable.pop(); |
5044 variable_name_symtable.pop(); |
5019 direct_variable_symtable.pop(); |
5045 direct_variable_symtable.pop(); |
5020 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
5046 library_element_symtable.insert($1, prev_declared_derived_function_name_token); |
5021 } |
5047 } |
5255 /* Rule already covered by the rule to handle the preparse state! |
5281 /* Rule already covered by the rule to handle the preparse state! |
5256 | FUNCTION_BLOCK derived_function_block_name END_FUNCTION_BLOCK |
5282 | FUNCTION_BLOCK derived_function_block_name END_FUNCTION_BLOCK |
5257 {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} |
5283 {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} |
5258 */ |
5284 */ |
5259 | FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_OF_INPUT |
5285 | FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_OF_INPUT |
5260 {$$ = NULL; print_err_msg(locf(@1), locl(@2), "no variable(s) declared and body defined in function block declaration."); yynerrs++;} |
5286 {$$ = NULL; print_err_msg(locf(@1), locl(@2), "expecting END_FUNCTION_BLOCK before end of file."); yynerrs++;} |
5261 | FUNCTION_BLOCK error END_FUNCTION_BLOCK |
5287 | FUNCTION_BLOCK error END_FUNCTION_BLOCK |
5262 {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function block declaration."); yyerrok;} |
5288 {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function block declaration."); yyerrok;} |
5263 /* ERROR_CHECK_END */ |
5289 /* ERROR_CHECK_END */ |
5264 ; |
5290 ; |
5265 |
5291 |
5364 ; |
5390 ; |
5365 |
5391 |
5366 |
5392 |
5367 |
5393 |
5368 function_block_body: |
5394 function_block_body: |
5369 statement_list {$$ = $1;} |
5395 /* 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 |
5370 | instruction_list {$$ = $1;} |
5396 * start_IL_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in IL |
5371 | sequential_function_chart {$$ = $1;} |
5397 * These tokens help remove a reduce/reduce conflict in bison, between a formal function invocation in IL, and a |
|
5398 * function invocation used as a statement (a non-standard extension added to matiec) |
|
5399 * e.g: FUNCTION_BLOCK foo |
|
5400 * VAR ... END_VAR |
|
5401 * func_returning_void(in1 := 3 |
|
5402 * ); --> only the presence or absence of ';' will determine whether this is a IL or ST |
|
5403 * function invocation. (In standard ST this would be ilegal, in matiec we allow it |
|
5404 * when activated by a command line option) |
|
5405 * END_FUNCTION |
|
5406 */ |
|
5407 start_ST_body_token statement_list {$$ = $2;} |
|
5408 | start_IL_body_token instruction_list {$$ = $2;} |
|
5409 | sequential_function_chart {$$ = $1;} |
5372 /* |
5410 /* |
5373 | ladder_diagram |
5411 | ladder_diagram |
5374 | function_block_diagram |
5412 | function_block_diagram |
5375 | <other languages> |
5413 | <other languages> |
5376 */ |
5414 */ |
7865 statement: |
7903 statement: |
7866 assignment_statement |
7904 assignment_statement |
7867 | subprogram_control_statement |
7905 | subprogram_control_statement |
7868 | selection_statement |
7906 | selection_statement |
7869 | iteration_statement |
7907 | iteration_statement |
|
7908 | function_invocation /* TODO: this must be conditional on command line parameter! */ |
7870 ; |
7909 ; |
7871 |
7910 |
7872 |
7911 |
7873 /*********************************/ |
7912 /*********************************/ |
7874 /* B 3.2.1 Assignment Statements */ |
7913 /* B 3.2.1 Assignment Statements */ |