diff -r ba80c3ceb6fb -r 2c3c4dc34979 stage1_2/iec.y --- a/stage1_2/iec.y Mon Jul 11 09:47:27 2011 +0100 +++ b/stage1_2/iec.y Fri Jul 29 16:03:28 2011 +0100 @@ -182,6 +182,14 @@ */ extern bool allow_function_overloading; +/* A flag to tell the compiler whether to allow the declaration + * of extensible function (i.e. functions that may have a variable number of + * input parameters, such as AND(word#33, word#44, word#55, word#66). + * This is an extension to the standard syntax. + * See comments below for details why we support this! + */ +extern bool allow_extensible_function_parameters; + /* A global flag used to tell the parser whether to include the full variable location * when printing out error messages... */ @@ -3587,15 +3595,48 @@ ; +/* NOTE: + * The syntax + * variable_name DOTDOT + * is an extension to the standard!!! + * + * In order to be able to handle extensible standard functions + * (i.e. standard functions that may have a variable number of + * input parameters, such as AND(word#33, word#44, word#55, word#66), + * we have extended the acceptable syntax to allow var_name '..' + * in an input variable declaration. + * + * This allows us to parse the declaration of standard + * extensible functions and load their interface definition + * into the abstract syntax tree just like we do to other + * user defined functions. + * This has the advantage that we can later do semantic + * checking of calls to functions (be it a standard or user defined + * function) in (almost) exactly the same way. + * + * Of course, we have a flag that disables this syntax when parsing user + * written code, so we only allow this extra syntax while parsing the + * 'header' file that declares all the standard IEC 61131-3 functions. + */ var1_list: variable_name {$$ = new var1_list_c(locloc(@$)); $$->add_element($1); variable_name_symtable.insert($1, prev_declared_variable_name_token); } +| variable_name integer DOTDOT + {$$ = new var1_list_c(locloc(@$)); $$->add_element(new extensible_input_parameter_c($1, $2, locloc(@$))); + variable_name_symtable.insert($1, prev_declared_variable_name_token); + if (!allow_extensible_function_parameters) print_err_msg(locf(@1), locl(@2), "invalid syntax in variable name declaration."); + } | var1_list ',' variable_name {$$ = $1; $$->add_element($3); variable_name_symtable.insert($3, prev_declared_variable_name_token); } + | var1_list ',' variable_name integer DOTDOT + {$$ = $1; $$->add_element(new extensible_input_parameter_c($3, $4, locloc(@$))); + variable_name_symtable.insert($3, prev_declared_variable_name_token); + if (!allow_extensible_function_parameters) print_err_msg(locf(@1), locl(@2), "invalid syntax in variable name declaration."); + } /* ERROR_CHECK_BEGIN */ | var1_list variable_name {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in variable list."); yynerrs++;} @@ -4307,13 +4348,13 @@ {$$ = new single_byte_string_spec_c(NULL, NULL);} */ STRING '[' integer ']' - {$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));} + {$$ = 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(@$));} /* | STRING ASSIGN single_byte_character_string - {$$ = new single_byte_string_spec_c(NULL, $3, locloc(@$));} + {$$ = new single_byte_string_spec_c($1, NULL, $3, locloc(@$));} */ | STRING '[' integer ']' ASSIGN single_byte_character_string - {$$ = new single_byte_string_spec_c($3, $6, locloc(@$));} + {$$ = 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(@$));} /* ERROR_CHECK_BEGIN */ | STRING '[' error ']' {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} @@ -4348,16 +4389,17 @@ double_byte_string_spec: /* WSTRING - {$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));} + {$$ = new double_byte_string_spec_c($1, NULL, NULL, locloc(@$));} */ WSTRING '[' integer ']' - {$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));} + {$$ = 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(@$));} + /* | WSTRING ASSIGN double_byte_character_string - {$$ = new double_byte_string_spec_c(NULL, $3, locloc(@$));} + {$$ = new double_byte_string_spec_c($1, NULL, $3, locloc(@$));} */ | WSTRING '[' integer ']' ASSIGN double_byte_character_string - {$$ = new double_byte_string_spec_c($3, $6, locloc(@$));} + {$$ = 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(@$));} /* ERROR_CHECK_BEGIN */ | WSTRING '[' error ']' {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;} @@ -4458,27 +4500,18 @@ /* helper symbol for var_spec */ -/* NOTE: The constructs - * - * STRING - * and - * WSTRING - * - * were removed as they are already contained - * within a simple_specification. - */ string_spec: /* STRING - {$$ = new single_byte_string_spec_c(NULL, NULL, locloc(@$));} + {$$ = new single_byte_limited_len_string_spec_c($1, NULL, locloc(@$));} */ STRING '[' integer ']' - {$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));} + {$$ = new single_byte_limited_len_string_spec_c(new string_type_name_c(locloc(@1)), $3, locloc(@$));} /* | WSTRING - {$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));} + {$$ = new double_byte_limited_len_string_spec_c($1, NULL, locloc(@$));} */ | WSTRING '[' integer ']' - {$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));} + {$$ = new double_byte_limited_len_string_spec_c(new wstring_type_name_c(locloc(@1)), $3, locloc(@$));} ; @@ -4665,11 +4698,31 @@ identifier | prev_declared_derived_function_name {$$ = $1; - if (not(allow_function_overloading)) { + if (!allow_function_overloading) { fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($1))->value); ERROR; } } +| AND + {$$ = new identifier_c("AND", locloc(@$)); + if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"AND\" not allowed. Invalid identifier\n"); + } +| OR + {$$ = new identifier_c("OR", locloc(@$)); + if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"OR\" not allowed. Invalid identifier\n"); + } +| XOR + {$$ = new identifier_c("XOR", locloc(@$)); + if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"XOR\" not allowed. Invalid identifier\n"); + } +| NOT + {$$ = new identifier_c("NOT", locloc(@$)); + if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"NOT\" not allowed. Invalid identifier\n"); + } +| MOD + {$$ = new identifier_c("MOD", locloc(@$)); + if (!allow_function_overloading) print_err_msg(locloc(@1), "Function overloading \"MOD\" not allowed. Invalid identifier\n"); + } ; @@ -7901,6 +7954,28 @@ */ bool allow_function_overloading = false; +/* | [var1_list ','] variable_name '..' */ +/* NOTE: This is an extension to the standard!!! */ +/* In order to be able to handle extensible standard functions + * (i.e. standard functions that may have a variable number of + * input parameters, such as AND(word#33, word#44, word#55, word#66), + * we have extended the acceptable syntax to allow var_name '..' + * in an input variable declaration. + * + * This allows us to parse the declaration of standard + * extensible functions and load their interface definition + * into the abstract syntax tree just like we do to other + * user defined functions. + * This has the advantage that we can later do semantic + * checking of calls to functions (be it a standard or user defined + * function) in (almost) exactly the same way. + * + * Of course, we have a flag that disables this syntax when parsing user + * written code, so we only allow this extra syntax while parsing the + * 'header' file that declares all the standard IEC 61131-3 functions. + */ +bool allow_extensible_function_parameters = false; + /* A global flag used to tell the parser whether to include the full variable location * when printing out error messages... */ @@ -7991,6 +8066,22 @@ +/* If function overloading is on, we allow several functions with the same name. + * + * However, to support standard functions, we also allow functions named + * AND, MOD, NOT, OR, XOR, ADD, ... + */ +/* +identifier_c *token_2_identifier_c(char *value, ) { + identifier_c tmp = new identifier_c(value, locloc(@$)); + if (!allow_function_overloading) { + fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($$))->value); + ERROR; + } + } +} +*/ + /* convert between an il_operator to a function name */ /* This a kludge! * It is required because our language requires more than one @@ -8124,11 +8215,6 @@ FILE *in_file = NULL, *lib_file = NULL; char *libfilename = NULL; - for(int i = 0; standard_function_names[i] != NULL; i++) - if (library_element_symtable.find_value(standard_function_names[i]) == - library_element_symtable.end_value()) - library_element_symtable.insert(standard_function_names[i], standard_function_name_token); - if((in_file = fopen(filename, "r")) == NULL) { char *errmsg = strdup2("Error opening main file ", filename); perror(errmsg); @@ -8165,6 +8251,7 @@ */ yyin = lib_file; allow_function_overloading = true; + allow_extensible_function_parameters = true; full_token_loc = full_token_loc_; current_filename = libfilename; current_tracking = GetNewTracking(yyin); @@ -8193,6 +8280,7 @@ #endif yyin = in_file; allow_function_overloading = false; + allow_extensible_function_parameters = false; full_token_loc = full_token_loc_; current_filename = filename; current_tracking = GetNewTracking(yyin);