stage1_2/iec.y
changeset 350 2c3c4dc34979
parent 328 66cd5d9893dd
equal deleted inserted replaced
341:ba80c3ceb6fb 350:2c3c4dc34979
   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;
  8163     yydebug = 1;
  8249     yydebug = 1;
  8164   #endif
  8250   #endif
  8165   */
  8251   */
  8166   yyin = lib_file;
  8252   yyin = lib_file;
  8167   allow_function_overloading = true;
  8253   allow_function_overloading = true;
       
  8254   allow_extensible_function_parameters = true;
  8168   full_token_loc = full_token_loc_;
  8255   full_token_loc = full_token_loc_;
  8169   current_filename = libfilename;
  8256   current_filename = libfilename;
  8170   current_tracking = GetNewTracking(yyin);
  8257   current_tracking = GetNewTracking(yyin);
  8171   if (yyparse() != 0)
  8258   if (yyparse() != 0)
  8172       ERROR;
  8259       ERROR;
  8191   #if YYDEBUG
  8278   #if YYDEBUG
  8192     yydebug = 1;
  8279     yydebug = 1;
  8193   #endif
  8280   #endif
  8194   yyin = in_file;
  8281   yyin = in_file;
  8195   allow_function_overloading = false;
  8282   allow_function_overloading = false;
       
  8283   allow_extensible_function_parameters = false;
  8196   full_token_loc = full_token_loc_;
  8284   full_token_loc = full_token_loc_;
  8197   current_filename = filename;
  8285   current_filename = filename;
  8198   current_tracking = GetNewTracking(yyin);
  8286   current_tracking = GetNewTracking(yyin);
  8199   {int res;
  8287   {int res;
  8200     if ((res = yyparse()) != 0) {
  8288     if ((res = yyparse()) != 0) {