179 /* A global flag used to tell the parser if overloaded funtions should be allowed. |
179 /* A global flag used to tell the parser if overloaded funtions should be allowed. |
180 * The IEC 61131-3 standard allows overloaded funtions in the standard library, |
180 * The IEC 61131-3 standard allows overloaded funtions in the standard library, |
181 * but disallows them in user code... |
181 * but disallows them in user code... |
182 */ |
182 */ |
183 extern bool allow_function_overloading; |
183 extern bool allow_function_overloading; |
|
184 |
|
185 /* A flag to tell the compiler whether to allow the declaration |
|
186 * of extensible function (i.e. functions that may have a variable number of |
|
187 * input parameters, such as AND(word#33, word#44, word#55, word#66). |
|
188 * This is an extension to the standard syntax. |
|
189 * See comments below for details why we support this! |
|
190 */ |
|
191 extern bool allow_extensible_function_parameters; |
184 |
192 |
185 /* A global flag used to tell the parser whether to include the full variable location |
193 /* A global flag used to tell the parser whether to include the full variable location |
186 * when printing out error messages... |
194 * when printing out error messages... |
187 */ |
195 */ |
188 extern bool full_token_loc; |
196 extern bool full_token_loc; |
3585 } |
3593 } |
3586 /* ERROR_CHECK_END */ |
3594 /* ERROR_CHECK_END */ |
3587 ; |
3595 ; |
3588 |
3596 |
3589 |
3597 |
|
3598 /* NOTE: |
|
3599 * The syntax |
|
3600 * variable_name DOTDOT |
|
3601 * is an extension to the standard!!! |
|
3602 * |
|
3603 * In order to be able to handle extensible standard functions |
|
3604 * (i.e. standard functions that may have a variable number of |
|
3605 * input parameters, such as AND(word#33, word#44, word#55, word#66), |
|
3606 * we have extended the acceptable syntax to allow var_name '..' |
|
3607 * in an input variable declaration. |
|
3608 * |
|
3609 * This allows us to parse the declaration of standard |
|
3610 * extensible functions and load their interface definition |
|
3611 * into the abstract syntax tree just like we do to other |
|
3612 * user defined functions. |
|
3613 * This has the advantage that we can later do semantic |
|
3614 * checking of calls to functions (be it a standard or user defined |
|
3615 * function) in (almost) exactly the same way. |
|
3616 * |
|
3617 * Of course, we have a flag that disables this syntax when parsing user |
|
3618 * written code, so we only allow this extra syntax while parsing the |
|
3619 * 'header' file that declares all the standard IEC 61131-3 functions. |
|
3620 */ |
3590 var1_list: |
3621 var1_list: |
3591 variable_name |
3622 variable_name |
3592 {$$ = new var1_list_c(locloc(@$)); $$->add_element($1); |
3623 {$$ = new var1_list_c(locloc(@$)); $$->add_element($1); |
3593 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
3624 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
3594 } |
3625 } |
|
3626 | variable_name integer DOTDOT |
|
3627 {$$ = new var1_list_c(locloc(@$)); $$->add_element(new extensible_input_parameter_c($1, $2, locloc(@$))); |
|
3628 variable_name_symtable.insert($1, prev_declared_variable_name_token); |
|
3629 if (!allow_extensible_function_parameters) print_err_msg(locf(@1), locl(@2), "invalid syntax in variable name declaration."); |
|
3630 } |
3595 | var1_list ',' variable_name |
3631 | var1_list ',' variable_name |
3596 {$$ = $1; $$->add_element($3); |
3632 {$$ = $1; $$->add_element($3); |
3597 variable_name_symtable.insert($3, prev_declared_variable_name_token); |
3633 variable_name_symtable.insert($3, prev_declared_variable_name_token); |
|
3634 } |
|
3635 | var1_list ',' variable_name integer DOTDOT |
|
3636 {$$ = $1; $$->add_element(new extensible_input_parameter_c($3, $4, locloc(@$))); |
|
3637 variable_name_symtable.insert($3, prev_declared_variable_name_token); |
|
3638 if (!allow_extensible_function_parameters) print_err_msg(locf(@1), locl(@2), "invalid syntax in variable name declaration."); |
3598 } |
3639 } |
3599 /* ERROR_CHECK_BEGIN */ |
3640 /* ERROR_CHECK_BEGIN */ |
3600 | var1_list variable_name |
3641 | var1_list variable_name |
3601 {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in variable list."); yynerrs++;} |
3642 {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in variable list."); yynerrs++;} |
3602 | var1_list ',' error |
3643 | var1_list ',' error |
4305 single_byte_string_spec: |
4346 single_byte_string_spec: |
4306 /* STRING |
4347 /* STRING |
4307 {$$ = new single_byte_string_spec_c(NULL, NULL);} |
4348 {$$ = new single_byte_string_spec_c(NULL, NULL);} |
4308 */ |
4349 */ |
4309 STRING '[' integer ']' |
4350 STRING '[' integer ']' |
4310 {$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));} |
4351 {$$ = new single_byte_string_spec_c(new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$)), NULL, locloc(@$));} |
4311 /* |
4352 /* |
4312 | STRING ASSIGN single_byte_character_string |
4353 | STRING ASSIGN single_byte_character_string |
4313 {$$ = new single_byte_string_spec_c(NULL, $3, locloc(@$));} |
4354 {$$ = new single_byte_string_spec_c($1, NULL, $3, locloc(@$));} |
4314 */ |
4355 */ |
4315 | STRING '[' integer ']' ASSIGN single_byte_character_string |
4356 | STRING '[' integer ']' ASSIGN single_byte_character_string |
4316 {$$ = new single_byte_string_spec_c($3, $6, locloc(@$));} |
4357 {$$ = new single_byte_string_spec_c(new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$)), $6, locloc(@$));} |
4317 /* ERROR_CHECK_BEGIN */ |
4358 /* ERROR_CHECK_BEGIN */ |
4318 | STRING '[' error ']' |
4359 | STRING '[' error ']' |
4319 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} |
4360 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} |
4320 | STRING '[' error ']' ASSIGN single_byte_character_string |
4361 | STRING '[' error ']' ASSIGN single_byte_character_string |
4321 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} |
4362 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} |
4346 /* ERROR_CHECK_END */ |
4387 /* ERROR_CHECK_END */ |
4347 ; |
4388 ; |
4348 |
4389 |
4349 double_byte_string_spec: |
4390 double_byte_string_spec: |
4350 /* WSTRING |
4391 /* WSTRING |
4351 {$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));} |
4392 {$$ = new double_byte_string_spec_c($1, NULL, NULL, locloc(@$));} |
4352 */ |
4393 */ |
4353 WSTRING '[' integer ']' |
4394 WSTRING '[' integer ']' |
4354 {$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));} |
4395 {$$ = new double_byte_string_spec_c(new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$)), NULL, locloc(@$));} |
|
4396 |
4355 /* |
4397 /* |
4356 | WSTRING ASSIGN double_byte_character_string |
4398 | WSTRING ASSIGN double_byte_character_string |
4357 {$$ = new double_byte_string_spec_c(NULL, $3, locloc(@$));} |
4399 {$$ = new double_byte_string_spec_c($1, NULL, $3, locloc(@$));} |
4358 */ |
4400 */ |
4359 | WSTRING '[' integer ']' ASSIGN double_byte_character_string |
4401 | WSTRING '[' integer ']' ASSIGN double_byte_character_string |
4360 {$$ = new double_byte_string_spec_c($3, $6, locloc(@$));} |
4402 {$$ = new double_byte_string_spec_c(new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$)), $6, locloc(@$));} |
4361 /* ERROR_CHECK_BEGIN */ |
4403 /* ERROR_CHECK_BEGIN */ |
4362 | WSTRING '[' error ']' |
4404 | WSTRING '[' error ']' |
4363 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;} |
4405 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;} |
4364 | WSTRING '[' error ']' ASSIGN single_byte_character_string |
4406 | WSTRING '[' error ']' ASSIGN single_byte_character_string |
4365 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;} |
4407 {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;} |
4456 | string_spec |
4498 | string_spec |
4457 ; |
4499 ; |
4458 |
4500 |
4459 |
4501 |
4460 /* helper symbol for var_spec */ |
4502 /* helper symbol for var_spec */ |
4461 /* NOTE: The constructs |
|
4462 * |
|
4463 * STRING |
|
4464 * and |
|
4465 * WSTRING |
|
4466 * |
|
4467 * were removed as they are already contained |
|
4468 * within a simple_specification. |
|
4469 */ |
|
4470 string_spec: |
4503 string_spec: |
4471 /* STRING |
4504 /* STRING |
4472 {$$ = new single_byte_string_spec_c(NULL, NULL, locloc(@$));} |
4505 {$$ = new single_byte_limited_len_string_spec_c($1, NULL, locloc(@$));} |
4473 */ |
4506 */ |
4474 STRING '[' integer ']' |
4507 STRING '[' integer ']' |
4475 {$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));} |
4508 {$$ = new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$));} |
4476 /* |
4509 /* |
4477 | WSTRING |
4510 | WSTRING |
4478 {$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));} |
4511 {$$ = new double_byte_limited_len_string_spec_c($1, NULL, locloc(@$));} |
4479 */ |
4512 */ |
4480 | WSTRING '[' integer ']' |
4513 | WSTRING '[' integer ']' |
4481 {$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));} |
4514 {$$ = new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$));} |
4482 ; |
4515 ; |
4483 |
4516 |
4484 |
4517 |
4485 |
4518 |
4486 |
4519 |
4663 |
4696 |
4664 derived_function_name: |
4697 derived_function_name: |
4665 identifier |
4698 identifier |
4666 | prev_declared_derived_function_name |
4699 | prev_declared_derived_function_name |
4667 {$$ = $1; |
4700 {$$ = $1; |
4668 if (not(allow_function_overloading)) { |
4701 if (!allow_function_overloading) { |
4669 fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($1))->value); |
4702 fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($1))->value); |
4670 ERROR; |
4703 ERROR; |
4671 } |
4704 } |
|
4705 } |
|
4706 | AND |
|
4707 {$$ = new identifier_c("AND", locloc(@$)); |
|
4708 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"AND\" not allowed. Invalid identifier\n"); |
|
4709 } |
|
4710 | OR |
|
4711 {$$ = new identifier_c("OR", locloc(@$)); |
|
4712 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"OR\" not allowed. Invalid identifier\n"); |
|
4713 } |
|
4714 | XOR |
|
4715 {$$ = new identifier_c("XOR", locloc(@$)); |
|
4716 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"XOR\" not allowed. Invalid identifier\n"); |
|
4717 } |
|
4718 | NOT |
|
4719 {$$ = new identifier_c("NOT", locloc(@$)); |
|
4720 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"NOT\" not allowed. Invalid identifier\n"); |
|
4721 } |
|
4722 | MOD |
|
4723 {$$ = new identifier_c("MOD", locloc(@$)); |
|
4724 if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"MOD\" not allowed. Invalid identifier\n"); |
4672 } |
4725 } |
4673 ; |
4726 ; |
4674 |
4727 |
4675 |
4728 |
4676 function_declaration: |
4729 function_declaration: |
7899 * In essence, a parameter we would like to pass to the yyparse() function but |
7952 * In essence, a parameter we would like to pass to the yyparse() function but |
7900 * have to do it using a global variable, as the yyparse() prototype is fixed by bison. |
7953 * have to do it using a global variable, as the yyparse() prototype is fixed by bison. |
7901 */ |
7954 */ |
7902 bool allow_function_overloading = false; |
7955 bool allow_function_overloading = false; |
7903 |
7956 |
|
7957 /* | [var1_list ','] variable_name '..' */ |
|
7958 /* NOTE: This is an extension to the standard!!! */ |
|
7959 /* In order to be able to handle extensible standard functions |
|
7960 * (i.e. standard functions that may have a variable number of |
|
7961 * input parameters, such as AND(word#33, word#44, word#55, word#66), |
|
7962 * we have extended the acceptable syntax to allow var_name '..' |
|
7963 * in an input variable declaration. |
|
7964 * |
|
7965 * This allows us to parse the declaration of standard |
|
7966 * extensible functions and load their interface definition |
|
7967 * into the abstract syntax tree just like we do to other |
|
7968 * user defined functions. |
|
7969 * This has the advantage that we can later do semantic |
|
7970 * checking of calls to functions (be it a standard or user defined |
|
7971 * function) in (almost) exactly the same way. |
|
7972 * |
|
7973 * Of course, we have a flag that disables this syntax when parsing user |
|
7974 * written code, so we only allow this extra syntax while parsing the |
|
7975 * 'header' file that declares all the standard IEC 61131-3 functions. |
|
7976 */ |
|
7977 bool allow_extensible_function_parameters = false; |
|
7978 |
7904 /* A global flag used to tell the parser whether to include the full variable location |
7979 /* A global flag used to tell the parser whether to include the full variable location |
7905 * when printing out error messages... |
7980 * when printing out error messages... |
7906 */ |
7981 */ |
7907 bool full_token_loc; |
7982 bool full_token_loc; |
7908 |
7983 |
7989 //fprintf(stderr, "%s(%d-%d): %s\n", current_filename, first_line, last_line, current_error_msg); |
8064 //fprintf(stderr, "%s(%d-%d): %s\n", current_filename, first_line, last_line, current_error_msg); |
7990 } |
8065 } |
7991 |
8066 |
7992 |
8067 |
7993 |
8068 |
|
8069 /* If function overloading is on, we allow several functions with the same name. |
|
8070 * |
|
8071 * However, to support standard functions, we also allow functions named |
|
8072 * AND, MOD, NOT, OR, XOR, ADD, ... |
|
8073 */ |
|
8074 /* |
|
8075 identifier_c *token_2_identifier_c(char *value, ) { |
|
8076 identifier_c tmp = new identifier_c(value, locloc(@$)); |
|
8077 if (!allow_function_overloading) { |
|
8078 fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($$))->value); |
|
8079 ERROR; |
|
8080 } |
|
8081 } |
|
8082 } |
|
8083 */ |
|
8084 |
7994 /* convert between an il_operator to a function name */ |
8085 /* convert between an il_operator to a function name */ |
7995 /* This a kludge! |
8086 /* This a kludge! |
7996 * It is required because our language requires more than one |
8087 * It is required because our language requires more than one |
7997 * look ahead token, and bison only works with one! |
8088 * look ahead token, and bison only works with one! |
7998 */ |
8089 */ |
8122 ) { |
8213 ) { |
8123 |
8214 |
8124 FILE *in_file = NULL, *lib_file = NULL; |
8215 FILE *in_file = NULL, *lib_file = NULL; |
8125 char *libfilename = NULL; |
8216 char *libfilename = NULL; |
8126 |
8217 |
8127 for(int i = 0; standard_function_names[i] != NULL; i++) |
|
8128 if (library_element_symtable.find_value(standard_function_names[i]) == |
|
8129 library_element_symtable.end_value()) |
|
8130 library_element_symtable.insert(standard_function_names[i], standard_function_name_token); |
|
8131 |
|
8132 if((in_file = fopen(filename, "r")) == NULL) { |
8218 if((in_file = fopen(filename, "r")) == NULL) { |
8133 char *errmsg = strdup2("Error opening main file ", filename); |
8219 char *errmsg = strdup2("Error opening main file ", filename); |
8134 perror(errmsg); |
8220 perror(errmsg); |
8135 free(errmsg); |
8221 free(errmsg); |
8136 return -1; |
8222 return -1; |