diff -r b826f13c260e -r 7a11f9e9e703 stage1_2/iec.y --- a/stage1_2/iec.y Wed Sep 07 19:28:10 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8219 +0,0 @@ -/* - * matiec - a compiler for the programming languages defined in IEC 61131-3 - * - * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) - * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * - * This code is made available on the understanding that it will not be - * used in safety-critical situations without a full and competent review. - */ - -/* - * An IEC 61131-3 compiler. - * - * Based on the - * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) - * - */ - -/* - * Stage 2 - * ======= - * - * This file contains the syntax definition of the textual - * languages IL and ST, as well as the textual version of SFC. - * The syntax parser, comprising the 2nd stage of the overall - * compiler, is generated by runing bison on this file. - */ - - - - -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ -/******* *******/ -/******* The following syntax does not have any conflicts. *******/ -/******* *******/ -/******* P L E A S E K E E P I T T H A T W A Y ! *******/ -/******* =================================================== *******/ -/******* *******/ -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ -/**********************************************************************/ - - - - -%{ -#include /* required for strdup() */ - - -/* declare the token parser generated by flex... */ -int yylex(void); - -/* declare the error handler defined at the end of this file */ -void yyerror (const char *error_msg); - -/* produce a more verbose parsing error message */ -#define YYERROR_VERBOSE - -/* Include debuging code. - * Printing of debug info must then be activated by setting - * the variable yydebug to 1. - */ -#define YYDEBUG 0 - - -/* file with declaration of absyntax classes... */ -#include "../absyntax/absyntax.hh" - -/* file with declaration of token constants. Generated by bison! */ -#include "iec.y.hh" - -/* The interface through which bison and flex interact. */ -#include "stage1_2_priv.hh" - - -#include "../absyntax_utils/add_en_eno_param_decl.hh" /* required for add_en_eno_param_decl_c */ - -/* an ugly hack!! - * We will probably not need it when we decide - * to cut down the abstract syntax down to size. - * We keep it as it is until we get to write - * stages 3 and 4 of the compiler. Who knows, - * we might just find out that we really do need - * the abstract syntax tree to stay as it is - * afterall! - */ -/* for each element in list_c * - * execute the code - */ -#define FOR_EACH_ELEMENT(elem, list, code) { \ - symbol_c *elem; \ - for(int i = 0; i < list->n; i++) { \ - elem = list->elements[i]; \ - code; \ - } \ -} - - - -/* Macros used to pass the line and column locations when - * creating a new object for the abstract syntax tree. - */ -#define locloc(foo) foo.first_line, foo.first_column, foo.first_file, foo.first_order, foo.last_line, foo.last_column, foo.last_file, foo.last_order -#define locf(foo) foo.first_line, foo.first_column, foo.first_file, foo.first_order -#define locl(foo) foo.last_line, foo.last_column, foo.last_file, foo.last_order - -/* Redefine the default action to take for each rule, so that the filenames are correctly processed... */ -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ - (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ - (Current).first_order = YYRHSLOC(Rhs, 1).first_order; \ - (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC(Rhs, N).last_column; \ - (Current).last_file = YYRHSLOC(Rhs, 1).last_file; \ - (Current).last_order = YYRHSLOC(Rhs, 1).last_order; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC(Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC(Rhs, 0).last_column; \ - (Current).first_file = (Current).last_file = \ - YYRHSLOC(Rhs, 0).last_file; \ - (Current).first_order = (Current).last_order = \ - YYRHSLOC(Rhs, 0).last_order; \ - } \ - while (0) - - -/* A macro for printing out internal parser errors... */ -#define ERROR error_exit(__FILE__,__LINE__) -/* function defined in main.cc */ -extern void error_exit(const char *file_name, int line_no); - - - -/*************************/ -/* global variables... */ -/*************************/ -/* NOTE: For some strange reason bison ver 2.3 is including these declarations - * in the iec.y.hh file, which is in turn included by flex. - * We cannot therefore define any variables over here, but merely declare - * their existance (otherwise we get errors when linking the code, since we - * would get a new variable defined each time iec.y.hh is included!). - * Even though the variables are declared 'extern' over here, they will in - * fact be defined towards the end of this same file (i.e. in the prologue) - */ - - -/* NOTE: These variable are really parameters we would like the stage2__ function to pass - * to the yyparse() function. However, the yyparse() function is created automatically - * by bison, so we cannot add parameters to this function. The only other - * option is to use global variables! yuck! - */ - -/* A global flag used to tell the parser if overloaded funtions should be allowed. - * The IEC 61131-3 standard allows overloaded funtions in the standard library, - * but disallows them in user code... - */ -extern bool allow_function_overloading; - -/* A global flag used to tell the parser whether to include the full variable location - * when printing out error messages... - */ -extern bool full_token_loc; - -/* A pointer to the root of the parsing tree that will be generated - * by bison. - */ -extern symbol_c *tree_root; - - - -/************************/ -/* forward declarations */ -/************************/ -/* The functions declared here are defined at the end of this file... */ - -/* Convert an il_operator_c into an identifier_c */ -symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator); - -/* return if current token is a syntax element */ -/* ERROR_CHECK_BEGIN */ -bool is_current_syntax_token(); -/* ERROR_CHECK_END */ - -/* print an error message */ -void print_err_msg(int first_line, - int first_column, - const char *first_filename, - long int first_order, - int last_line, - int last_column, - const char *last_filename, - long int last_order, - const char *additional_error_msg); -%} - - - - -// %glr-parser -// %expect-rr 1 - - -/* The following definitions need to be inside a '%code requires' - * so that they are also included in the header files. If this were not the case, - * YYLTYPE would be delcared as something in the iec.cc file, and another thing - * (actually the default value of YYLTYPE) in the iec.y.hh heder file. - */ -%code requires { -/* define a new data type to store the locations, so we can also store - * the filename in which the token is expressed. - */ -/* NOTE: since this code will be placed in the iec.y.hh header file, - * as well as the iec.cc file that also includes the iec.y.hh header file, - * declaring the typedef struct yyltype__local here would result in a - * compilation error when compiling iec.cc, as this struct would be - * declared twice. - * We therefore use the #if !defined YYLTYPE ... - * to make sure only the first declaration is parsed by the C++ compiler. - * - * At first glance it seems that what we really should do is delcare the - * YYLTYPE directly as an anonymous struct, thus: - * #define YYLTYPE struct{ ...} - * however, this also results in compilation errors. - * - * I (Mario) think this is kind of a hack. If you know how to - * do this re-declaration of YYLTYPE properly, please let me know! - */ -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED - typedef struct { - int first_line; - int first_column; - const char *first_file; - long int first_order; - int last_line; - int last_column; - const char *last_file; - long int last_order; - } yyltype__local; - #define YYLTYPE yyltype__local -#endif -} - - - -%union { - symbol_c *leaf; - list_c *list; - char *ID; /* token value */ -} - -/* - TODO: DO we need to define a destructor do free - memory when recovering from errors, or do the - class destructors already handle this? - Following is example on how to define - detructors, using the syntax: - %destructor { CODE } SYMBOLS -%union - { - char *string; - } - %token STRING - %type string - %destructor { free ($$); } STRING string -*/ - - - - -/*************************************/ -/* Prelimenary helpful constructs... */ -/*************************************/ -/* A token used to identify the very end of the input file - * after all includes have already been processed. - * - * Flex automatically returns the token with value 0 - * at the end of the file. We therefore specify here - * a token with that exact same value here, so we can use it - * to detect the very end of the input files. - */ -%token END_OF_INPUT 0 - -/* A bogus token that, in principle, flex MUST NEVER generate */ -/* USE 1: - * ====== - * This token is currently also being used as the default - * initialisation value of the token_id member in - * the symbol_c base class. - * - * USE 2 - * ===== - * This token may also be used in the future to remove - * mysterious reduce/reduce conflicts due to the fact - * that our grammar may not be LALR(1) but merely LR(1). - * This means that bison cannot handle it without some - * caoxing from ourselves. We will then need this token - * to do the coaxing... - */ -%token BOGUS_TOKEN_ID - -%type start - -%type any_identifier - -%token prev_declared_variable_name_token -%token prev_declared_direct_variable_token -%token prev_declared_fb_name_token -%type prev_declared_variable_name -%type prev_declared_direct_variable -%type prev_declared_fb_name - -%token prev_declared_simple_type_name_token -%token prev_declared_subrange_type_name_token -%token prev_declared_enumerated_type_name_token -%token prev_declared_array_type_name_token -%token prev_declared_structure_type_name_token -%token prev_declared_string_type_name_token - -%type prev_declared_simple_type_name -%type prev_declared_subrange_type_name -%type prev_declared_enumerated_type_name -%type prev_declared_array_type_name -%type prev_declared_structure_type_name -%type prev_declared_string_type_name - -%token prev_declared_derived_function_name_token -%token prev_declared_derived_function_block_name_token -%token prev_declared_program_type_name_token -%type prev_declared_derived_function_name -%type prev_declared_derived_function_block_name -%type prev_declared_program_type_name - - - - -/**********************************************************************************/ -/* B XXX - Things that are missing from the standard, but should have been there! */ -/**********************************************************************************/ - -/* Pragmas that our compiler will accept. - * See the comment in iec.flex for why these pragmas exist. - */ -%token disable_code_generation_pragma_token -%token enable_code_generation_pragma_token -%type disable_code_generation_pragma -%type enable_code_generation_pragma - - -/* All other pragmas that we do not support... */ -/* In most stage 4, the text inside the pragmas will simply be copied to the output file. - * This allows us to insert C code (if using stage 4 generating C code) - * inside/interningled with the IEC 61131-3 code! - */ -%token pragma_token -%type pragma - -/* The joining of all previous pragmas, i.e. any possible pragma */ -%type any_pragma - - -/* Where do these tokens belong?? They are missing from the standard! */ -/* NOTE: There are other tokens related to these 'EN' ENO', that are also - * missing from the standard. However, their location in the annex B is - * relatively obvious, so they have been inserted in what seems to us their - * correct place in order to ease understanding of the parser... - * - * please read the comment above the definition of 'variable' in section B1.4 for details. - */ -%token EN -%token ENO -%type en_identifier -%type eno_identifier - - - - -/***************************/ -/* B 0 - Programming Model */ -/***************************/ -%type library -%type library_element_declaration - - -/*******************************************/ -/* B 1.1 - Letters, digits and identifiers */ -/*******************************************/ -/* Done totally within flex... - letter - digit - octal_digit - hex_digit -*/ -%token identifier_token -%type identifier - -/*********************/ -/* B 1.2 - Constants */ -/*********************/ -%type constant -%type non_negative_constant - -/******************************/ -/* B 1.2.1 - Numeric Literals */ -/******************************/ -/* Done totally within flex... - bit -*/ -%type numeric_literal -%type integer_literal -%type signed_integer -%token integer_token -%type integer -%token binary_integer_token -%type binary_integer -%token octal_integer_token -%type octal_integer -%token hex_integer_token -%type hex_integer -%token real_token -%type real -%type signed_real -%type real_literal -// %type exponent -%type bit_string_literal -%type boolean_literal - -%token safeboolean_true_literal_token -%token safeboolean_false_literal_token -%token boolean_true_literal_token -%token boolean_false_literal_token - -%token FALSE -%token TRUE - - -/*******************************/ -/* B 1.2.2 - Character Strings */ -/*******************************/ -%token single_byte_character_string_token -%token double_byte_character_string_token - -%type character_string -%type single_byte_character_string -%type double_byte_character_string - - -/***************************/ -/* B 1.2.3 - Time Literals */ -/***************************/ -%type time_literal - - -/************************/ -/* B 1.2.3.1 - Duration */ -/************************/ -%type duration -%type interval -%type days -%type fixed_point -%type hours -%type minutes -%type seconds -%type milliseconds - -%type integer_d -%type integer_h -%type integer_m -%type integer_s -%type integer_ms -%type fixed_point_d -%type fixed_point_h -%type fixed_point_m -%type fixed_point_s -%type fixed_point_ms - -%token fixed_point_token -%token fixed_point_d_token -%token integer_d_token -%token fixed_point_h_token -%token integer_h_token -%token fixed_point_m_token -%token integer_m_token -%token fixed_point_s_token -%token integer_s_token -%token fixed_point_ms_token -%token integer_ms_token - -// %token TIME -%token T_SHARP - - -/************************************/ -/* B 1.2.3.2 - Time of day and Date */ -/************************************/ -%type time_of_day -%type daytime -%type day_hour -%type day_minute -%type day_second -%type date -%type date_literal -%type year -%type month -%type day -%type date_and_time - -// %token TIME_OF_DAY -// %token DATE -%token D_SHARP -// %token DATE_AND_TIME - - -/**********************/ -/* B 1.3 - Data Types */ -/**********************/ -/* Strangely, the following symbol does seem to be required! */ -// %type data_type_name -%type non_generic_type_name - - -/***********************************/ -/* B 1.3.1 - Elementary Data Types */ -/***********************************/ -/* NOTES: - * - * - To make the definition of bit_string_literal more - * concise, it is useful to use an extra non-terminal - * symbol (i.e. a grouping or construct) that groups the - * following elements (BYTE, WORD, DWORD, LWORD). - * Note that the definition of bit_string_type_name - * (according to the spec) includes the above elements - * and an extra BOOL. - * We could use an extra construct with the first four - * elements to be used solely in the definition of - * bit_string_literal, but with the objective of not - * having to replicate the actions (if we ever need - * to change them, they would need to be changed in both - * bit_string_type_name and the extra grouping), we - * have re-defined bit_string_type_name as only including - * the first four elements. - * In order to have our parser implement the specification - * correctly we have augmented every occurence of - * bit_string_type_name in other rules with the BOOL - * token. Since bit_string_type_name only appears in - * the rule for elementary_type_name, this does not - * seem to be a big concession to make! - * - * - We have added a helper symbol to concentrate the - * instantiation of STRING and WSTRING into a single - * location (elementary_string_type_name). - * These two elements show up in several other rules, - * but we want to create the equivalent abstract syntax - * in a single location of this file, in order to make - * possible future changes easier to edit... - */ -%type elementary_type_name -%type numeric_type_name -%type integer_type_name -%type signed_integer_type_name -%type unsigned_integer_type_name -%type real_type_name -%type date_type_name -%type bit_string_type_name -/* helper symbol to concentrate the instantiation - * of STRING and WSTRING into a single location - */ -%type elementary_string_type_name - -%token BYTE -%token WORD -%token DWORD -%token LWORD - -%token LREAL -%token REAL - -%token SINT -%token INT -%token DINT -%token LINT - -%token USINT -%token UINT -%token UDINT -%token ULINT - -%token WSTRING -%token STRING -%token BOOL - -%token TIME -%token DATE -%token DATE_AND_TIME -%token DT -%token TIME_OF_DAY -%token TOD - -/******************************************************/ -/* Symbols defined in */ -/* "Safety Software Technical Specification, */ -/* Part 1: Concepts and Function Blocks, */ -/* Version 1.0 – Official Release" */ -/* by PLCopen - Technical Committee 5 - 2006-01-31 */ -/******************************************************/ - -%token SAFEBYTE -%token SAFEWORD -%token SAFEDWORD -%token SAFELWORD - -%token SAFELREAL -%token SAFEREAL - -%token SAFESINT -%token SAFEINT -%token SAFEDINT -%token SAFELINT - -%token SAFEUSINT -%token SAFEUINT -%token SAFEUDINT -%token SAFEULINT - -%token SAFEWSTRING -%token SAFESTRING -%token SAFEBOOL - -%token SAFETIME -%token SAFEDATE -%token SAFEDATE_AND_TIME -%token SAFEDT -%token SAFETIME_OF_DAY -%token SAFETOD - -/********************************/ -/* B 1.3.2 - Generic data types */ -/********************************/ -/* Strangely, the following symbol does seem to be required! */ -// %type generic_type_name - -/* The following tokens do not seem to be used either - * but we declare them so they become reserved words... - */ -%token ANY -%token ANY_DERIVED -%token ANY_ELEMENTARY -%token ANY_MAGNITUDE -%token ANY_NUM -%token ANY_REAL -%token ANY_INT -%token ANY_BIT -%token ANY_STRING -%token ANY_DATE - - -/********************************/ -/* B 1.3.3 - Derived data types */ -/********************************/ -%type derived_type_name -%type single_element_type_name -// %type simple_type_name -// %type subrange_type_name -// %type enumerated_type_name -// %type array_type_name -// %type structure_type_name - -%type data_type_declaration -/* helper symbol for data_type_declaration */ -%type type_declaration_list -%type type_declaration -%type single_element_type_declaration - -%type simple_type_declaration -%type simple_spec_init -%type simple_specification - -%type subrange_type_declaration -%type subrange_spec_init -%type subrange_specification -%type subrange - -%type enumerated_type_declaration -%type enumerated_spec_init -%type enumerated_specification -/* helper symbol for enumerated_value */ -%type enumerated_value_list -%type enumerated_value -//%type enumerated_value_without_identifier - -%type array_type_declaration -%type array_spec_init -%type array_specification -/* helper symbol for array_specification */ -%type array_subrange_list -%type array_initialization -/* helper symbol for array_initialization */ -%type array_initial_elements_list -%type array_initial_elements -%type array_initial_element - -%type structure_type_declaration -%type structure_specification -%type initialized_structure -%type structure_declaration -/* helper symbol for structure_declaration */ -%type structure_element_declaration_list -%type structure_element_declaration -%type structure_element_name -%type structure_initialization -/* helper symbol for structure_initialization */ -%type structure_element_initialization_list -%type structure_element_initialization - -//%type string_type_name -%type string_type_declaration -/* helper symbol for string_type_declaration */ -%type string_type_declaration_size -/* helper symbol for string_type_declaration */ -%type string_type_declaration_init - -%token ASSIGN -%token DOTDOT /* ".." */ -%token TYPE -%token END_TYPE -%token ARRAY -%token OF -%token STRUCT -%token END_STRUCT - - - -/*********************/ -/* B 1.4 - Variables */ -/*********************/ -%type variable -%type symbolic_variable -/* helper symbol for prog_cnxn */ -%type any_symbolic_variable -%type variable_name - - - - -/********************************************/ -/* B.1.4.1 Directly Represented Variables */ -/********************************************/ -/* Done totally within flex... - location_prefix - size_prefix -*/ -%token direct_variable_token -//%type direct_variable - - -/*************************************/ -/* B.1.4.2 Multi-element Variables */ -/*************************************/ -%type multi_element_variable -/* helper symbol for any_symbolic_variable */ -%type any_multi_element_variable -%type array_variable -/* helper symbol for any_symbolic_variable */ -%type any_array_variable -%type subscripted_variable -/* helper symbol for any_symbolic_variable */ -%type any_subscripted_variable -%type subscript_list -%type subscript -%type structured_variable -/* helper symbol for any_symbolic_variable */ -%type any_structured_variable -%type record_variable -/* helper symbol for any_symbolic_variable */ -%type any_record_variable -%type field_selector - - -/******************************************/ -/* B 1.4.3 - Declaration & Initialisation */ -/******************************************/ -%type input_declarations -/* helper symbol for input_declarations */ -%type input_declaration_list -%type input_declaration -%type edge_declaration -/* en_param_declaration is not in the standard, but should be! */ -%type en_param_declaration -%type var_init_decl -%type var1_init_decl -%type var1_list -%type array_var_init_decl -%type structured_var_init_decl -%type fb_name_decl -/* helper symbol for fb_name_decl */ -%type fb_name_list_with_colon -/* helper symbol for fb_name_list_with_colon */ -%type var1_list_with_colon -// %type fb_name_list -// %type fb_name -%type output_declarations -%type var_output_init_decl -%type var_output_init_decl_list -/* eno_param_declaration is not in the standard, but should be! */ -%type eno_param_declaration -%type input_output_declarations -/* helper symbol for input_output_declarations */ -%type var_declaration_list -%type var_declaration -%type temp_var_decl -%type var1_declaration -%type array_var_declaration -%type structured_var_declaration -%type var_declarations -%type retentive_var_declarations -%type located_var_declarations -/* helper symbol for located_var_declarations */ -%type located_var_decl_list -%type located_var_decl -%type external_var_declarations -/* helper symbol for external_var_declarations */ -%type external_declaration_list -%type external_declaration -%type global_var_name -%type global_var_declarations -/* helper symbol for global_var_declarations */ -%type global_var_decl_list -%type global_var_decl -%type global_var_spec -%type located_var_spec_init -%type location -%type global_var_list -%type string_var_declaration -%type single_byte_string_var_declaration -%type single_byte_string_spec -%type double_byte_string_var_declaration -%type double_byte_string_spec -%type incompl_located_var_declarations -/* helper symbol for incompl_located_var_declarations */ -%type incompl_located_var_decl_list -%type incompl_located_var_decl -%type incompl_location -%type var_spec -/* helper symbol for var_spec */ -%type string_spec -/* intermediate helper symbol for: - * - non_retentive_var_decls - * - var_declarations - */ -%type var_init_decl_list - -%token incompl_location_token - -%token VAR_INPUT -%token VAR_OUTPUT -%token VAR_IN_OUT -%token VAR_EXTERNAL -%token VAR_GLOBAL -%token END_VAR -%token RETAIN -%token NON_RETAIN -%token R_EDGE -%token F_EDGE -%token AT - - -/***********************/ -/* B 1.5.1 - Functions */ -/***********************/ -// %type function_name -/* helper symbol for IL language */ -%type function_name_no_clashes -%type function_name_simpleop_clashes -//%type function_name_expression_clashes -/* helper symbols for ST language */ -//%type function_name_NOT_clashes -%type function_name_no_NOT_clashes - -//%type standard_function_name -/* helper symbols for IL language */ -%type standard_function_name_no_clashes -%type standard_function_name_simpleop_clashes -%type standard_function_name_expression_clashes -/* helper symbols for ST language */ -%type standard_function_name_NOT_clashes -%type standard_function_name_no_NOT_clashes - -%type derived_function_name -%type function_declaration -/* helper symbol for function_declaration */ -%type function_name_declaration -%type io_var_declarations -%type function_var_decls -%type function_body -%type var2_init_decl -/* intermediate helper symbol for function_declaration */ -%type io_OR_function_var_declarations_list -/* intermediate helper symbol for function_var_decls */ -%type var2_init_decl_list - -%token standard_function_name_token - -%token FUNCTION -%token END_FUNCTION -%token CONSTANT - - -/*****************************/ -/* B 1.5.2 - Function Blocks */ -/*****************************/ -%type function_block_type_name -%type standard_function_block_name -%type derived_function_block_name -%type function_block_declaration -%type other_var_declarations -%type temp_var_decls -%type non_retentive_var_decls -%type function_block_body -/* intermediate helper symbol for function_declaration */ -%type io_OR_other_var_declarations_list -/* intermediate helper symbol for temp_var_decls */ -%type temp_var_decls_list - -%token standard_function_block_name_token - -%token FUNCTION_BLOCK -%token END_FUNCTION_BLOCK -%token VAR_TEMP -// %token END_VAR -%token VAR -// %token NON_RETAIN -// %token END_VAR - - -/**********************/ -/* B 1.5.3 - Programs */ -/**********************/ -%type program_type_name -%type program_declaration -/* helper symbol for program_declaration */ -%type program_var_declarations_list - -%token PROGRAM -%token END_PROGRAM - - -/********************************************/ -/* B 1.6 Sequential Function Chart elements */ -/********************************************/ - -%type sequential_function_chart -%type sfc_network -%type initial_step -%type step -%type action_association_list -%type step_name -%type action_association -/* helper symbol for action_association */ -%type indicator_name_list -%type action_name -%type action_qualifier -%type qualifier -%type timed_qualifier -%type action_time -%type indicator_name -%type transition -%type steps -%type step_name_list -%type transition_priority -%type transition_condition -%type action -%type action_body -%type transition_name - - -// %token ASSIGN -%token ACTION -%token END_ACTION - -%token TRANSITION -%token END_TRANSITION -%token FROM -%token TO -%token PRIORITY - -%token INITIAL_STEP -%token STEP -%token END_STEP - -%token L -%token D -%token SD -%token DS -%token SL - -%token N -%token P -/* NOTE: the following two clash with the R and S IL operators. - * It will have to be handled when we include parsing of SFC... - */ -/* -%token R -%token S -*/ - - -/********************************/ -/* B 1.7 Configuration elements */ -/********************************/ -%type configuration_name -%type resource_type_name -%type configuration_declaration -// helper symbol for -// - configuration_declaration -// - resource_declaration -// -%type optional_global_var_declarations -// helper symbol for configuration_declaration -%type optional_access_declarations -// helper symbol for configuration_declaration -%type optional_instance_specific_initializations -// helper symbol for configuration_declaration -%type resource_declaration_list -%type resource_declaration -%type single_resource_declaration -// helper symbol for single_resource_declaration -%type task_configuration_list -// helper symbol for single_resource_declaration -%type program_configuration_list -%type resource_name -// %type access_declarations -// helper symbol for access_declarations -// %type access_declaration_list -// %type access_declaration -// %type access_path -// helper symbol for access_path -%type any_fb_name_list -%type global_var_reference -// %type access_name -%type program_output_reference -%type program_name -// %type direction -%type task_configuration -%type task_name -%type task_initialization -// 3 helper symbols for task_initialization -%type task_initialization_single -%type task_initialization_interval -%type task_initialization_priority - -%type data_source -%type program_configuration -// helper symbol for program_configuration -%type optional_task_name -// helper symbol for program_configuration -%type optional_prog_conf_elements -%type prog_conf_elements -%type prog_conf_element -%type fb_task -%type prog_cnxn -%type prog_data_source -%type data_sink -%type instance_specific_initializations -// helper symbol for instance_specific_initializations -%type instance_specific_init_list -%type instance_specific_init -// helper symbol for instance_specific_init -%type fb_initialization - -%type prev_declared_global_var_name -%token prev_declared_global_var_name_token - -%type prev_declared_program_name -%token prev_declared_program_name_token - -%type prev_declared_resource_name -%token prev_declared_resource_name_token - -%token prev_declared_configuration_name_token - -// %type prev_declared_task_name -// %token prev_declared_task_name_token - -%token CONFIGURATION -%token END_CONFIGURATION -%token TASK -%token RESOURCE -%token ON -%token END_RESOURCE -%token VAR_CONFIG -%token VAR_ACCESS -// %token END_VAR -%token WITH -// %token PROGRAM -// %token RETAIN -// %token NON_RETAIN -// %token PRIORITY -%token SINGLE -%token INTERVAL -%token READ_WRITE -%token READ_ONLY - - -/***********************************/ -/* B 2.1 Instructions and Operands */ -/***********************************/ -%type instruction_list -%type il_instruction -%type il_incomplete_instruction -%type label -%type il_simple_operation -// helper symbol for il_simple_operation -//%type il_simple_operator_clash_il_operand -%type il_expression -%type il_jump_operation -%type il_fb_call -%type il_formal_funct_call -// helper symbol for il_formal_funct_call -%type il_expr_operator_clash_eol_list -%type il_operand -%type il_operand_list -// helper symbol for il_simple_operation -%type il_operand_list2 -%type simple_instr_list -%type il_simple_instruction -%type il_param_list -%type il_param_instruction_list -%type il_param_instruction -%type il_param_last_instruction -%type il_param_assignment -%type il_param_out_assignment - -%token EOL - - -/*******************/ -/* B 2.2 Operators */ -/*******************/ -%token sendto_identifier_token -%type sendto_identifier - -%type LD_operator -%type LDN_operator -%type ST_operator -%type STN_operator -%type NOT_operator -%type S_operator -%type R_operator -%type S1_operator -%type R1_operator -%type CLK_operator -%type CU_operator -%type CD_operator -%type PV_operator -%type IN_operator -%type PT_operator -%type AND_operator -%type AND2_operator -%type OR_operator -%type XOR_operator -%type ANDN_operator -%type ANDN2_operator -%type ORN_operator -%type XORN_operator -%type ADD_operator -%type SUB_operator -%type MUL_operator -%type DIV_operator -%type MOD_operator -%type GT_operator -%type GE_operator -%type EQ_operator -%type LT_operator -%type LE_operator -%type NE_operator -%type CAL_operator -%type CALC_operator -%type CALCN_operator -%type RET_operator -%type RETC_operator -%type RETCN_operator -%type JMP_operator -%type JMPC_operator -%type JMPCN_operator - -%type il_simple_operator -%type il_simple_operator_clash -%type il_simple_operator_clash1 -%type il_simple_operator_clash2 -%type il_simple_operator_noclash - -//%type il_expr_operator -%type il_expr_operator_clash -%type il_expr_operator_noclash - -%type il_assign_operator -%type il_assign_out_operator -%type il_call_operator -%type il_return_operator -%type il_jump_operator - - -%token LD -%token LDN -%token ST -%token STN -%token NOT -%token S -%token R -%token S1 -%token R1 -%token CLK -%token CU -%token CD -%token PV -%token IN -%token PT -%token AND -%token AND2 /* character '&' in the source code*/ -%token OR -%token XOR -%token ANDN -%token ANDN2 /* characters '&N' in the source code */ -%token ORN -%token XORN -%token ADD -%token SUB -%token MUL -%token DIV -%token MOD -%token GT -%token GE -%token EQ -%token LT -%token LE -%token NE -%token CAL -%token CALC -%token CALCN -%token RET -%token RETC -%token RETCN -%token JMP -%token JMPC -%token JMPCN - -%token SENDTO /* "=>" */ - - -/***********************/ -/* B 3.1 - Expressions */ -/***********************/ -/* NOTE: - * - * - unary_operator, multiply_operator, - * add_operator and comparison_operator - * are not required. Their values are integrated - * directly into other rules... - */ -%type expression -%type xor_expression -%type and_expression -%type comparison -%type equ_expression -// %type comparison_operator -%type add_expression -// %type add_operator -%type term -// %type multiply_operator -%type power_expression -%type unary_expression -// %type unary_operator -%type primary_expression -%type non_negative_primary_expression -/* intermediate helper symbol for primary_expression */ -%type function_invocation - -// %token AND -// %token XOR -// %token OR -// %token MOD -// %token NOT -%token OPER_NE -%token OPER_GE -%token OPER_LE -%token OPER_EXP - - -/********************/ -/* B 3.2 Statements */ -/********************/ -%type statement_list -%type statement - - - -/*********************************/ -/* B 3.2.1 Assignment Statements */ -/*********************************/ -%type assignment_statement -// %token ASSIGN /* ":=" */ - - -/*****************************************/ -/* B 3.2.2 Subprogram Control Statements */ -/*****************************************/ -%type subprogram_control_statement -%type return_statement -%type fb_invocation -// %type param_assignment -%type param_assignment_formal -%type param_assignment_nonformal -/* helper symbols for fb_invocation */ -%type param_assignment_formal_list -%type param_assignment_nonformal_list - -// %token ASSIGN -// %token SENDTO /* "=>" */ -%token RETURN - - -/********************************/ -/* B 3.2.3 Selection Statements */ -/********************************/ -%type selection_statement -%type if_statement -%type case_statement -%type case_element -%type case_list -%type case_list_element -/* helper symbol for if_statement */ -%type elseif_statement_list -/* helper symbol for elseif_statement_list */ -%type elseif_statement -/* helper symbol for case_statement */ -%type case_element_list - -%token IF -%token THEN -%token ELSIF -%token ELSE -%token END_IF - -%token CASE -// %token OF -// %token ELSE -%token END_CASE - - - -/********************************/ -/* B 3.2.4 Iteration Statements */ -/********************************/ -%type iteration_statement -%type for_statement -%type control_variable -%type while_statement -%type repeat_statement -%type exit_statement -/* Integrated directly into for_statement */ -// %type for_list - -%token FOR -// %token ASSIGN -// %token TO -%token BY -%token DO -%token END_FOR - -%token WHILE -// %token DO -%token END_WHILE - -%token REPEAT -%token UNTIL -%token END_REPEAT - -%token EXIT - - -%% - - - - -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ -/********************************************************/ - - -start: - library {$$ = $1;} -; - - -/**********************************************************************************/ -/* B XXX - Things that are missing from the standard, but should have been there! */ -/**********************************************************************************/ - - -/* the pragmas... */ - - -disable_code_generation_pragma: - disable_code_generation_pragma_token {$$ = new disable_code_generation_pragma_c(locloc(@$));} - -enable_code_generation_pragma: - enable_code_generation_pragma_token {$$ = new enable_code_generation_pragma_c(locloc(@$));} - -pragma: - pragma_token {$$ = new pragma_c($1, locloc(@$));} - -any_pragma: - disable_code_generation_pragma -| enable_code_generation_pragma -| pragma -; - - -/* EN/ENO */ -/* Tese tokens are essentially used as variable names, so we handle them - * similarly to these... - */ -en_identifier: - EN {$$ = new identifier_c("EN", locloc(@$));} -; - -eno_identifier: - ENO {$$ = new identifier_c("ENO", locloc(@$));} -; - - - -/*************************************/ -/* Prelimenary helpful constructs... */ -/*************************************/ - -/* NOTE: - * short version: - * identifier is used for previously undeclared identifiers - * any_identifier is used when any identifier, previously - * declared or not, is required in the syntax. - * - * long version: - * When flex comes across an identifier, it first - * searches through the currently declared variables, - * functions, types, etc... to determine if it has - * been previously declared. - * Only if the identifier has not yet been declared - * will it return an identifier_token (later turned into - * an identifier symbol by the bison generated syntax parser). - * - * Some constructs in the syntax, such as when calling - * a function 'F(var1 := 1; var2 := 2);', will accept _any_ - * identifier in 'var1', even if it has been previously - * declared in the current scope, since var1 belongs to - * another scope (the variables declared in function F). - * - * For the above reason, we need to define the symbol - * any_identifier. All the symbols that may become an - * any_identifier are expected to be stored in the - * abstract syntax as a identifier_c - */ -/* NOTE: - * Type names, function names, function block type names and - * program type names are considerd keywords once they are defined, - * so may no longer be used for variable names! - * BUT the spec is confusing on this issue, as it is not clear when - * a function name should be considered as defined. If it is to be - * considered defined only from the location from where it is declared - * and onwards, it means that before it is declared its name may be - * used for variable names! - * This means that we must allow names previously used for functions - * (et. al.) to also constitue an any_identifier! - */ -any_identifier: - identifier -| prev_declared_fb_name -| prev_declared_variable_name -/**/ -| prev_declared_enumerated_type_name -| prev_declared_simple_type_name -| prev_declared_subrange_type_name -| prev_declared_array_type_name -| prev_declared_structure_type_name -| prev_declared_string_type_name -| prev_declared_derived_function_name -| prev_declared_derived_function_block_name -| prev_declared_program_type_name -/**/ -| prev_declared_resource_name -| prev_declared_program_name -| prev_declared_global_var_name -; - - -prev_declared_variable_name: prev_declared_variable_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_fb_name: prev_declared_fb_name_token {$$ = new identifier_c($1, locloc(@$));}; - -prev_declared_simple_type_name: prev_declared_simple_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_subrange_type_name: prev_declared_subrange_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_array_type_name: prev_declared_array_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_structure_type_name: prev_declared_structure_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_string_type_name: prev_declared_string_type_name_token {$$ = new identifier_c($1, locloc(@$));}; - -prev_declared_derived_function_name: prev_declared_derived_function_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_program_type_name: prev_declared_program_type_name_token {$$ = new identifier_c($1, locloc(@$));}; - - - -/***************************/ -/* B 0 - Programming Model */ -/***************************/ -library: - /* empty */ - {if (tree_root == NULL) - tree_root = new library_c(); - $$ = (list_c *)tree_root; - } -| library library_element_declaration - {$$ = $1; $$->add_element($2);} -| library any_pragma - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| library error library_element_declaration - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unknown syntax error."); yyerrok;} -| library error END_OF_INPUT - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unknown syntax error."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -library_element_declaration: - data_type_declaration -| function_declaration -| function_block_declaration -| program_declaration -| configuration_declaration -; - - - -/*******************************************/ -/* B 1.1 - Letters, digits and identifiers */ -/*******************************************/ -/* NOTE: the spec defines identifier as: - * identifier ::= (letter|('_' (letter|digit))) {['_'] (letter|digit)} - * In essence, any sequence of letters or digits, starting with a letter - * or '_'. - * - * On section 2.1.3 (pg 26) , the spec states - * "The keywords listed in annex C shall not be used for any other purpose, - * e.g., variable names or extensions as defined in 1.5.1." - * (NOTE: the spec itself does not follow this rule, as it defines standard - * functions with names identidal to keywords, e.g. 'MOD', 'NOT' !!. This is - * another issue altogether, and is worked around somewhere else...) - * - * This means that we must re-define indentifier so as to exclude - * any keywords defined in annex C. - * - * Note also that the list includes - * - Data type names - * - Function names - * - Function Block names - * This means that any named used for a function name, data type name - * or function block name, essentially becomes a keyword, and may therefore - * no longer be re-used for any other use! (see NOTE 2) - * - * In our case, excluding the keywords is achieved in the lexical parser, - * by two mechanisms: - * (1) giving higher priority to the keywords (tokens) than to identifiers, - * so when the lexical parser finds a keyword it will be parsed as a - * token before being parsed as an identifier. - * (2) when an identifier is found that is not a keyword, the lexical parser - * then looks in the global symbol table, and will not return an identifier - * if the name has been previously used as a data type name, function name, - * or function block name! (In these cases it will return a - * prev_declared_function_name_token, etc...). - * - * Unfortunately, the language (especially IL) uses tokens that are - * not defined as keywords in the spec (e.g. 'IN', 'R1', 'S1', 'PT', etc...)! - * This means that it is valid to name a function 'IN', a variable 'PT', etc... - * In order to solve this potential ambiguity, flex only parses the above - * identifiers as keywords / tokens if we are currently parsing IL code. - * When parsing all code other than IL code, the above identifiers are treated - * just like any other identifier. - * - * - * - * - * NOTE 2: - * I (Mario) find it strange that the writers of the spec really want - * names previously used for function names, data type names or function - * block names, to become full fledged keywords. I understand that they - * do not want these names being used as variable names, but how about - * enumeration values? How about structure element names? - * If we interpret the spec literally, these would not be accepted, - * which would probably burden the programmer quite a bit, in making sure - * all these name don't clash! - * - * - * - * NOTE 3: The keywords, as specified in Annex C are... - * - * - Data type names - * - Function names - * - Function Block names - * - ACTION...END_ACTION - * - ARRAY...OF - * - AT - * - CASE...OF...ELSE...END_CASE - * - CONFIGURATION...END_CONFIGURATION - * - CONSTANT - * - EN, ENO - * - EXIT - * - FALSE - * - F_EDGE - * - FOR...TO...BY...DO...END_FOR - * - FUNCTION...END_FUNCTION - * - FUNCTION_BLOCK...END_FUNCTION_BLOCK - * - IF...THEN...ELSIF...ELSE...END_IF - * - INITIAL_STEP...END_STEP - * - NOT, MOD, AND, XOR, OR - * - PROGRAM...WITH... - * - PROGRAM...END_PROGRAM - * - R_EDGE - * - READ_ONLY, READ_WRITE - * - REPEAT...UNTIL...END_REPEAT - * - RESOURCE...ON...END_RESOURCE - * - RETAIN, NON_RETAIN - * - RETURN - * - STEP...END_STEP - * - STRUCT...END_STRUCT - * - TASK - * - TRANSITION...FROM...TO...END_TRANSITION - * - TRUE - * - TYPE...END_TYPE - * - VAR...END_VAR - * - VAR_INPUT...END_VAR - * - VAR_OUTPUT...END_VAR - * - VAR_IN_OUT...END_VAR - * - VAR_TEMP...END_VAR - * - VAR_EXTERNAL...END_VAR - * - VAR_ACCESS...END_VAR - * - VAR_CONFIG...END_VAR - * - VAR_GLOBAL...END_VAR - * - WHILE...DO...END_WHILE - * - WITH - */ - -identifier: - identifier_token {$$ = new identifier_c($1, locloc(@$));} -; - - - -/*********************/ -/* B 1.2 - Constants */ -/*********************/ -constant: - numeric_literal -| character_string -| time_literal -| bit_string_literal -| boolean_literal -/* NOTE: in order to remove reduce/reduce conflicts, - * [between -9.5 being parsed as - * (i) a signed real, - * (ii) or as a real preceded by the '-' operator - * ] - * we need to define a variant of the constant construct - * where any constant is never preceded by the '-' character. - * In order to do this, we have borugh the signed_real - * directly into the definition of the constant construct - * (so we can define another non_negative_constant - * construct that does not include it!) - */ -| signed_real -/* NOTE: in order to remove reduce/reduce conflicts, - * unsigned_integer, signed_integer, binary_integer, octal_integer - * and hex_integer have been integrated directly into - * the constants construct, instead of belonging to - * both the bit_string_literal or integer_literal - * construct. - */ -/* NOTE: unsigned_integer, although used in some - * rules, is not defined in the spec! - * We therefore replaced unsigned_integer as integer - */ -/*| integer {} */ /* i.e. an unsigned_integer */ /* NOTE: already included as a signed integer! */ -| signed_integer -| binary_integer -| octal_integer -| hex_integer -; - - -/* NOTE: in order to remove reduce/reduce conflicts, - * [between -9.5 being parsed as - * (i) a signed real, - * (ii) or as a real preceded by the '-' operator - * ] - * we need to define a variant of the constant construct - * where any constant is never preceded by the '-' character. - * In order to do this, we have borugh the signed_real - * directly into the definition of the constant construct - * (so we can define another non_negative_constant - * construct that does not include it!) - */ -non_negative_constant: - numeric_literal -| character_string -| time_literal -| bit_string_literal -| boolean_literal -/* NOTE: in order to remove reduce/reduce conflicts, - * [between -9.5 being parsed as - * (i) a signed real, - * (ii) or as a real preceded by the '-' operator - * ] - * we need to define a variant of the constant construct - * where any constant is never preceded by the '-' character. - * In order to do this, we have borugh the signed_real - * directly into the definition of the constant construct - * (so we can define another non_negative_constant - * construct that does not include it!) - */ -/* | signed_real */ -| real /* an unsigned real */ -/* NOTE: in order to remove reduce/reduce conflicts, - * unsigned_integer, signed_integer, binary_integer, octal_integer - * and hex_integer have been integrated directly into - * the constants construct, instead of belonging to - * both the bit_string_literal or integer_literal - * construct. - */ -/* NOTE: unsigned_integer, although used in some - * rules, is not defined in the spec! - * We therefore replaced unsigned_integer as integer - */ -| integer /* i.e. an unsigned_integer */ -/* | signed_integer */ -| binary_integer -| octal_integer -| hex_integer -; - - -/******************************/ -/* B 1.2.1 - Numeric Literals */ -/******************************/ -/* NOTES: - * - * - integer is parsed by flex, but signed_integer - * is parsed by bison. Flex cannot parse a signed - * integer correctly! For example: '123+456' - * would be parsed by flex as an {integer} {signed_integer} - * instead of {integer} '+' {integer} - * - * - Neither flex nor bison can parse a real_literal - * completely (and correctly). - * Note that we cannot use the definition of real in bison as - * real: signed_integer '.' integer [exponent] - * exponent: {'E'|'e'} ['+'|'-'] integer - * because 123e45 would be parsed by flex as - * integer (123) identifier (e45). - * I.e., flex never hands over an 'e' directly to - * bison, but rather interprets it as an identifier. - * I guess we could jump through hoops and get it - * working in bison, but the following alternative - * seems more straight forward... - * - * We therefore had to break up the definition of - * real_literal in discrete parts: - * real_literal: [real_type_name '#'] singned_real - * signed_real: ['+'|'-'] real - * Flex handles real, while bison handles signed_real - * and real_literal. - * - * - According to the spec, integer '.' integer - * may be reduced to either a real or a fixed_point. - * It is nevertheless possible to figure out from the - * context which of the two rules should be used in - * the reduction. - * Unfortunately, due to the issue described above - * regarding the exponent of a real, the syntax - * integer '.' integer - * must be parsed by flex as a single token (i.e. - * fixed_point_token). This means we must add fixed_point - * to the definition of real! - * - * - The syntax also uses a construct - * fixed_point: integer ['.' integer] - * Notice that real is not defined based on fixed point, - * but rather off integer thus: - * real: integer '.' integer [exponent] - * This means that a real may not be composed of a single - * integer, unlike the construct fixed_point! - * This also means that a - * integer '.' integer - * could be reduced to either a real or a fixed_point - * construct. It is probably possible to decide by looking - * at the context, BUT: - * Unfortunatley, due to the reasons explained way above, - * a real (with an exponent) has to be handled by flex as a - * whole. This means that we cannot leave to bison (the syntax - * parser) the decision of how to reduce an - * integer '.' integer - * (either to real or to fixed_point) - * The decision on how to reduce it would need to be done by - * ther lexical analyser (i.e. flex). But flex cannot do this - * sort of thing. - * The solution I (Mario) adopted is to have flex return - * a real_token on (notice that exponent is no longer optional) - * integer '.' integer exponent - * and to return a fixed_point_token when it finds - * integer '.' integer - * We now redefine real and fixed_point to be - * fixed_point: fixed_point_token | integer - * real: real_token | fixed_point_token - */ -real: - real_token {$$ = new real_c($1, locloc(@$));} -| fixed_point_token {$$ = new real_c($1, locloc(@$));} -; - -integer: integer_token {$$ = new integer_c($1, locloc(@$));}; -binary_integer: binary_integer_token {$$ = new binary_integer_c($1, locloc(@$));}; -octal_integer: octal_integer_token {$$ = new octal_integer_c($1, locloc(@$));}; -hex_integer: hex_integer_token {$$ = new hex_integer_c($1, locloc(@$));}; - -numeric_literal: - integer_literal -| real_literal -; - - -integer_literal: - integer_type_name '#' signed_integer - {$$ = new integer_literal_c($1, $3, locf(@1), locl(@3));} -| integer_type_name '#' binary_integer - {$$ = new integer_literal_c($1, $3, locf(@1), locl(@3));} -| integer_type_name '#' octal_integer - {$$ = new integer_literal_c($1, $3, locf(@1), locl(@3));} -| integer_type_name '#' hex_integer - {$$ = new integer_literal_c($1, $3, locf(@1), locl(@3));} -/* NOTE: see note in the definition of constant for reason - * why signed_integer, binary_integer, octal_integer - * and hex_integer are missing here! - */ -/* ERROR_CHECK_BEGIN */ -| integer_type_name signed_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between integer type name and value in integer literal."); yynerrs++;} -| integer_type_name binary_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between integer type name and value in integer literal."); yynerrs++;} -| integer_type_name octal_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between integer type name and value in integer literal."); yynerrs++;} -| integer_type_name hex_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between integer type name and value in integer literal."); yynerrs++;} -| integer_type_name '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for integer literal.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for integer literal."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -signed_integer: - integer -| '+' integer {$$ = $2;} -| '-' integer {$$ = new neg_integer_c($2, locloc(@$));} -; - - -real_literal: -/* NOTE: see note in the definition of constant for reason - * why signed_real is missing here! - */ -/* signed_real */ - real_type_name '#' signed_real - {$$ = new real_literal_c($1, $3, locf(@1), locl(@3));} -/* ERROR_CHECK_BEGIN */ -| real_type_name signed_real - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between real type name and value in real literal."); yynerrs++;} -| real_type_name '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for real literal.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for real literal."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -signed_real: - real -| '+' real {$$ = $2;} -| '-' real {$$ = new neg_real_c($2, locloc(@2));} -; - - - -bit_string_literal: - bit_string_type_name '#' integer /* i.e. unsigned_integer */ - {$$ = new bit_string_literal_c($1, $3, locf(@1), locl(@3));} -| bit_string_type_name '#' binary_integer - {$$ = new bit_string_literal_c($1, $3, locf(@1), locl(@3));} -| bit_string_type_name '#' octal_integer - {$$ = new bit_string_literal_c($1, $3, locf(@1), locl(@3));} -| bit_string_type_name '#' hex_integer - {$$ = new bit_string_literal_c($1, $3, locf(@1), locl(@3));} -/* NOTE: see note in the definition of constant for reason - * why unsigned_integer, binary_integer, octal_integer - * and hex_integer are missing here! - */ -/* NOTE: see note under the B 1.2.1 section of token - * and grouping type definition for reason why the use of - * bit_string_type_name, although seemingly incorrect, is - * really correct here! - */ -/* ERROR_CHECK_BEGIN */ -| bit_string_type_name integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between bit string type name and value in bit string literal."); yynerrs++;} -| bit_string_type_name binary_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between bit string type name and value in bit string literal."); yynerrs++;} -| bit_string_type_name octal_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between bit string type name and value in bit string literal."); yynerrs++;} -| bit_string_type_name hex_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between bit string type name and value in bit string literal."); yynerrs++;} -| bit_string_type_name '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for bit string literal.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for bit string literal."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -boolean_literal: - boolean_true_literal_token - {$$ = new boolean_literal_c(new bool_type_name_c(locloc(@$)), - new boolean_true_c(locloc(@$)), - locloc(@$)); - } -| boolean_false_literal_token - {$$ = new boolean_literal_c(new bool_type_name_c(locloc(@$)), - new boolean_false_c(locloc(@$)), - locloc(@$)); - } -| safeboolean_true_literal_token - {$$ = new boolean_literal_c(new safebool_type_name_c(locloc(@$)), - new boolean_true_c(locloc(@$)), - locloc(@$)); - } -| safeboolean_false_literal_token - {$$ = new boolean_literal_c(new safebool_type_name_c(locloc(@$)), - new boolean_false_c(locloc(@$)), - locloc(@$)); - } -| FALSE - {$$ = new boolean_literal_c(NULL, - new boolean_false_c(locloc(@$)), - locloc(@$)); - } -| TRUE - {$$ = new boolean_literal_c(NULL, - new boolean_true_c(locloc(@$)), - locloc(@$)); - } -/* -| BOOL '#' '1' {} -| BOOL '#' '0' {} -*/ -/* NOTE: the rules - * BOOL '#' '1' - * and - * BOOL '#' '0' - * do not work as expected... - * Consider that we are using 'BOOL' and '#' as tokens - * that flex hands over to bison (yacc). Because flex would - * then parse the single '1' or '0' as an integer, - * the rule in bison would have to be - * BOOL '#' integer, followed by verifying of the - * integer has the correct value! - * - * We therefore have flex return TRUE whenever it - * comes across 'TRUE' or 'BOOL#1', and FALSE whenever - * it comes across 'FALSE' or 'BOOL#0'. - * Note that this means that flex will parse "BOOL#01" - * as FALSE followed by an integer ('1'). - * Bison should detect this as an error, so we should - * be OK. - * - * Another option would be to change the rules to accept - * BOOL '#' integer - * but then check whether the integer has a correct - * value! At the moment I feel that the first option - * is more straight forward. - */ -; - - - -/*******************************/ -/* B 1.2.2 - Character Strings */ -/*******************************/ -/* Transform the tokens given us by flex into leafs */ -single_byte_character_string: single_byte_character_string_token - {$$ = new single_byte_character_string_c($1, locloc(@$));}; - -double_byte_character_string: double_byte_character_string_token - {$$ = new double_byte_character_string_c($1, locloc(@$));}; - - -character_string: - single_byte_character_string -| double_byte_character_string -; - - - - - -/***************************/ -/* B 1.2.3 - Time Literals */ -/***************************/ -time_literal: - time_of_day -| date -| date_and_time -| duration -; - - -/************************/ -/* B 1.2.3.1 - Duration */ -/************************/ -duration: -/* (T | TIME) '#' ['-'] interval */ -/* NOTE: since TIME is also a data type, it is a keyword - * and may therefore be handled by a token. - * - * Unfortunately T is not a data type, and therefore - * not a keyword. This means that we may have variables named T! - * Flex cannot return the token TIME when it comes across a single T! - * - * We therefore have flex returning the token T_SHARP - * when it comes across 'T#' - */ - TIME '#' interval - {$$ = new duration_c(new time_type_name_c(locloc(@1)), NULL, $3, locloc(@$));} -| TIME '#' '-' interval - {$$ = new duration_c(new time_type_name_c(locloc(@1)), new neg_time_c(locloc(@$)), $4, locloc(@$));} -| T_SHARP interval - {$$ = new duration_c(new time_type_name_c(locloc(@1)), NULL, $2, locloc(@$));} -| T_SHARP '-' interval - {$$ = new duration_c(new time_type_name_c(locloc(@1)), new neg_time_c(locloc(@$)), $3, locloc(@$));} -| SAFETIME '#' interval - {$$ = new duration_c(new safetime_type_name_c(locloc(@1)), NULL, $3, locloc(@$));} -| SAFETIME '#' '-' interval - {$$ = new duration_c(new safetime_type_name_c(locloc(@1)), new neg_time_c(locloc(@$)), $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| TIME interval - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME' and interval in duration."); yynerrs++;} -| TIME '-' interval - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME' and interval in duration."); yynerrs++;} -| TIME '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for duration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for duration."); yyclearin;} - yyerrok; - } -| T_SHARP error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no value defined for duration.");} - else {print_err_msg(locf(@2), locl(@2), "invalid value for duration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -interval: - days -| hours -| minutes -| seconds -| milliseconds -; - -integer_d: integer_d_token {$$ = new integer_c($1, locloc(@$));}; -integer_h: integer_h_token {$$ = new integer_c($1, locloc(@$));}; -integer_m: integer_m_token {$$ = new integer_c($1, locloc(@$));}; -integer_s: integer_s_token {$$ = new integer_c($1, locloc(@$));}; -integer_ms: integer_ms_token {$$ = new integer_c($1, locloc(@$));}; - -fixed_point_d: - fixed_point_d_token - {$$ = new fixed_point_c($1, locloc(@$));} -| integer_d -; - -fixed_point_h: - fixed_point_h_token - {$$ = new fixed_point_c($1, locloc(@$));} -| integer_h -; - -fixed_point_m: - fixed_point_m_token - {$$ = new fixed_point_c($1, locloc(@$));} -| integer_m -; - -fixed_point_s: - fixed_point_s_token - {$$ = new fixed_point_c($1, locloc(@$));} -| integer_s -; - -fixed_point_ms: - fixed_point_ms_token - {$$ = new fixed_point_c($1, locloc(@$));} -| integer_ms -; - - -fixed_point: - fixed_point_token - {$$ = new fixed_point_c($1, locloc(@$));} -| integer -; - - -days: -/* fixed_point ('d') */ - fixed_point_d - {$$ = new days_c($1, NULL, locloc(@$));} -/*| integer ('d') ['_'] hours */ -| integer_d hours - {$$ = new days_c($1, $2, locloc(@$));} -| integer_d '_' hours - {$$ = new days_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| integer_d '_' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for hours in duration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for hours in duration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -hours: -/* fixed_point ('h') */ - fixed_point_h - {$$ = new hours_c($1, NULL, locloc(@$));} -/*| integer ('h') ['_'] minutes */ -| integer_h minutes - {$$ = new hours_c($1, $2, locloc(@$));} -| integer_h '_' minutes - {$$ = new hours_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| integer_h '_' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for minutes in duration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for minutes in duration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ - -; - -minutes: -/* fixed_point ('m') */ - fixed_point_m - {$$ = new minutes_c($1, NULL, locloc(@$));} -/*| integer ('m') ['_'] seconds */ -| integer_m seconds - {$$ = new minutes_c($1, $2, locloc(@$));} -| integer_m '_' seconds - {$$ = new minutes_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| integer_m '_' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for seconds in duration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for seconds in duration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -seconds: -/* fixed_point ('s') */ - fixed_point_s - {$$ = new seconds_c($1, NULL, locloc(@$));} -/*| integer ('s') ['_'] milliseconds */ -| integer_s milliseconds - {$$ = new seconds_c($1, $2, locloc(@$));} -| integer_s '_' milliseconds - {$$ = new seconds_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| integer_s '_' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for milliseconds in duration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for milliseconds in duration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -milliseconds: -/* fixed_point ('ms') */ - fixed_point_ms - {$$ = new milliseconds_c($1, locloc(@$));} -; - - - -/************************************/ -/* B 1.2.3.2 - Time of day and Date */ -/************************************/ -time_of_day: - TIME_OF_DAY '#' daytime - {$$ = new time_of_day_c(new tod_type_name_c(locloc(@1)), $3, locloc(@$));} -| SAFETIME_OF_DAY '#' daytime - {$$ = new time_of_day_c(new safetod_type_name_c(locloc(@1)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| TIME_OF_DAY daytime - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME_OF_DAY' and daytime in time of day."); yynerrs++;} -| TIME_OF_DAY '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for time of day.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for time of day."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -daytime: - day_hour ':' day_minute ':' day_second - {$$ = new daytime_c($1, $3, $5, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| ':' day_minute ':' day_second - {$$ = NULL; print_err_msg(locf(@1), locl(@4), "no value defined for hours in daytime."); yynerrs++;} -| error ':' day_minute ':' day_second - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid value defined for hours in daytime."); yyerrok;} -| day_hour day_minute ':' day_second - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between hours and minutes in daytime."); yynerrs++;} -| day_hour ':' ':' day_second - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no value defined for minutes in daytime."); yynerrs++;} -| day_hour ':' error ':' day_second - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid value defined for minutes in daytime."); yyerrok;} -| day_hour ':' day_minute day_second - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "':' missing between minutes and seconds in daytime."); yynerrs++;} -| day_hour ':' day_minute ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@4), locf(@5), "no value defined for seconds in daytime.");} - else {print_err_msg(locf(@5), locl(@5), "invalid value for seconds in daytime."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -day_hour: integer; -day_minute: integer; -day_second: fixed_point; - - -date: - DATE '#' date_literal - {$$ = new date_c(new date_type_name_c(locloc(@1)), $3, locloc(@$));} -| D_SHARP date_literal - {$$ = new date_c(new date_type_name_c(locloc(@1)), $2, locloc(@$));} -| SAFEDATE '#' date_literal - {$$ = new date_c(new safedate_type_name_c(locloc(@1)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| DATE date_literal - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'DATE' and date literal in date."); yynerrs++;} -| DATE '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for date.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for date."); yyclearin;} - yyerrok; - } -| D_SHARP error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no value defined for date.");} - else {print_err_msg(locf(@2), locl(@2), "invalid value for date."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -date_literal: - year '-' month '-' day - {$$ = new date_literal_c($1, $3, $5, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| '-' month '-' day - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no value defined for year in date literal."); yynerrs++;} -| year month '-' day - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'-' missing between year and month in date literal."); yynerrs++;} -| year '-' '-' day - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no value defined for month in date literal."); yynerrs++;} -| year '-' error '-' day - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid value defined for month in date literal."); yyerrok;} -| year '-' month day - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "'-' missing between month and day in date literal."); yynerrs++;} -| year '-' month '-' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@4), locf(@5), "no value defined for day in date literal.");} - else {print_err_msg(locf(@5), locl(@5), "invalid value for day in date literal."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -year: integer; -month: integer; -day: integer; - - -date_and_time: - DATE_AND_TIME '#' date_literal '-' daytime - {$$ = new date_and_time_c(new dt_type_name_c(locloc(@1)), $3, $5, locloc(@$));} -| SAFEDATE_AND_TIME '#' date_literal '-' daytime - {$$ = new date_and_time_c(new safedt_type_name_c(locloc(@1)), $3, $5, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| DATE_AND_TIME date_literal '-' daytime - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'DATE_AND_TIME' and date literal in date and time."); yynerrs++;} -| DATE_AND_TIME '#' '-' daytime - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no value defined for date literal in date and time."); yynerrs++;} -| DATE_AND_TIME '#' error '-' daytime - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid value for date literal in date and time."); yyerrok;} -| DATE_AND_TIME '#' date_literal daytime - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "'-' missing between date literal and daytime in date and time."); yynerrs++;} -| DATE_AND_TIME '#' date_literal '-' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@4), locf(@5), "no value defined for daytime in date and time.");} - else {print_err_msg(locf(@5), locl(@5), "invalid value for daytime in date and time."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - - - - -/**********************/ -/* B 1.3 - Data Types */ -/**********************/ -/* Strangely, the following symbol does seem to be required! */ -/* -data_type_name: - non_generic_type_name -| generic_type_name -; -*/ - -non_generic_type_name: - elementary_type_name -| derived_type_name -; - - - -/***********************************/ -/* B 1.3.1 - Elementary Data Types */ -/***********************************/ - /******************************************************/ - /* SAFExxxx Symbols defined in */ - /* "Safety Software Technical Specification, */ - /* Part 1: Concepts and Function Blocks, */ - /* Version 1.0 – Official Release" */ - /* by PLCopen - Technical Committee 5 - 2006-01-31 */ - /******************************************************/ - -elementary_type_name: - numeric_type_name -| date_type_name -| bit_string_type_name -| elementary_string_type_name -| TIME {$$ = new time_type_name_c(locloc(@$));} -| BOOL {$$ = new bool_type_name_c(locloc(@$));} -/* NOTE: see note under the B 1.2.1 section of token - * and grouping type definition for reason why BOOL - * was added to this definition. - */ -| SAFETIME {$$ = new safetime_type_name_c(locloc(@$));} -| SAFEBOOL {$$ = new safebool_type_name_c(locloc(@$));} -; - -numeric_type_name: - integer_type_name -| real_type_name -; - -integer_type_name: - signed_integer_type_name -| unsigned_integer_type_name -; - -signed_integer_type_name: - SINT {$$ = new sint_type_name_c(locloc(@$));} -| INT {$$ = new int_type_name_c(locloc(@$));} -| DINT {$$ = new dint_type_name_c(locloc(@$));} -| LINT {$$ = new lint_type_name_c(locloc(@$));} -| SAFESINT {$$ = new safesint_type_name_c(locloc(@$));} -| SAFEINT {$$ = new safeint_type_name_c(locloc(@$));} -| SAFEDINT {$$ = new safedint_type_name_c(locloc(@$));} -| SAFELINT {$$ = new safelint_type_name_c(locloc(@$));} -; - -unsigned_integer_type_name: - USINT {$$ = new usint_type_name_c(locloc(@$));} -| UINT {$$ = new uint_type_name_c(locloc(@$));} -| UDINT {$$ = new udint_type_name_c(locloc(@$));} -| ULINT {$$ = new ulint_type_name_c(locloc(@$));} -| SAFEUSINT {$$ = new safeusint_type_name_c(locloc(@$));} -| SAFEUINT {$$ = new safeuint_type_name_c(locloc(@$));} -| SAFEUDINT {$$ = new safeudint_type_name_c(locloc(@$));} -| SAFEULINT {$$ = new safeulint_type_name_c(locloc(@$));} -; - -real_type_name: - REAL {$$ = new real_type_name_c(locloc(@$));} -| LREAL {$$ = new lreal_type_name_c(locloc(@$));} -| SAFEREAL {$$ = new safereal_type_name_c(locloc(@$));} -| SAFELREAL {$$ = new safelreal_type_name_c(locloc(@$));} -; - -date_type_name: - DATE {$$ = new date_type_name_c(locloc(@$));} -| TIME_OF_DAY {$$ = new tod_type_name_c(locloc(@$));} -| TOD {$$ = new tod_type_name_c(locloc(@$));} -| DATE_AND_TIME {$$ = new dt_type_name_c(locloc(@$));} -| DT {$$ = new dt_type_name_c(locloc(@$));} -| SAFEDATE {$$ = new safedate_type_name_c(locloc(@$));} -| SAFETIME_OF_DAY {$$ = new safetod_type_name_c(locloc(@$));} -| SAFETOD {$$ = new safetod_type_name_c(locloc(@$));} -| SAFEDATE_AND_TIME {$$ = new safedt_type_name_c(locloc(@$));} -| SAFEDT {$$ = new safedt_type_name_c(locloc(@$));} -; - - -bit_string_type_name: - BYTE {$$ = new byte_type_name_c(locloc(@$));} -| WORD {$$ = new word_type_name_c(locloc(@$));} -| DWORD {$$ = new dword_type_name_c(locloc(@$));} -| LWORD {$$ = new lword_type_name_c(locloc(@$));} -| SAFEBYTE {$$ = new safebyte_type_name_c(locloc(@$));} -| SAFEWORD {$$ = new safeword_type_name_c(locloc(@$));} -| SAFEDWORD {$$ = new safedword_type_name_c(locloc(@$));} -| SAFELWORD {$$ = new safelword_type_name_c(locloc(@$));} -/* NOTE: see note under the B 1.2.1 section of token - * and grouping type definition for reason why the BOOL - * was omitted from this definition. - */ -; - - -/* Helper symbol to concentrate the instantiation - * of STRING and WSTRING into a single location. - * - * These two elements show up in several other rules, - * but we want to create the equivalent abstract syntax - * in a single location of this file, in order to make - * possible future changes easier to edit... - */ -elementary_string_type_name: - STRING {$$ = new string_type_name_c(locloc(@$));} -| WSTRING {$$ = new wstring_type_name_c(locloc(@$));} -| SAFESTRING {$$ = new safestring_type_name_c(locloc(@$));} -| SAFEWSTRING {$$ = new safewstring_type_name_c(locloc(@$));} -; - - - -/********************************/ -/* B 1.3.2 - Generic data types */ -/********************************/ -/* Strangely, the following symbol does not seem to be required! */ -/* -generic_type_name: - ANY -| ANY_DERIVED -| ANY_ELEMENTARY -| ANY_MAGNITUDE -| ANY_NUM -| ANY_REAL -| ANY_INT -| ANY_BIT -| ANY_STRING -| ANY_DATE -; -*/ - - -/********************************/ -/* B 1.3.3 - Derived data types */ -/********************************/ - -derived_type_name: - single_element_type_name -| prev_declared_array_type_name -| prev_declared_structure_type_name -| prev_declared_string_type_name -; - -single_element_type_name: - prev_declared_simple_type_name -/* Include the following if arrays of function blocks are to be allowed! - * Since the standard does not allow them, - * we leave it commented out for the time being... - */ -//| prev_declared_derived_function_block_name -| prev_declared_subrange_type_name -| prev_declared_enumerated_type_name -; - -/* NOTE: in order to remove a reduce/reduce conflict, - * all occurences of simple_type_name, etc... - * have been replaced with identifier! - */ -/* -simple_type_name: identifier; -subrange_type_name: identifier; -enumerated_type_name: identifier; -array_type_name: identifier; -structure_type_name: identifier; -*/ - -data_type_declaration: - TYPE type_declaration_list END_TYPE - {$$ = new data_type_declaration_c($2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| TYPE END_TYPE - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no data type declared in data type(s) declaration."); yynerrs++;} -| TYPE error type_declaration_list END_TYPE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'TYPE' in data type(s) declaration."); yyerrok;} -| TYPE type_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed data type(s) declaration."); yyerrok;} -| TYPE error END_TYPE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in data type(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for data_type_declaration */ -type_declaration_list: - type_declaration ';' - {$$ = new type_declaration_list_c(locloc(@$)); $$->add_element($1);} -| type_declaration_list type_declaration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new type_declaration_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid data type declaration."); yyerrok;} -| type_declaration error - {$$ = new type_declaration_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of data type declaration."); yyerrok;} -| type_declaration_list type_declaration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of data type declaration."); yyerrok;} -| type_declaration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid data type declaration."); yyerrok;} -| type_declaration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after data type declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -type_declaration: - single_element_type_declaration -| array_type_declaration -| structure_type_declaration -| string_type_declaration -; - -single_element_type_declaration: - simple_type_declaration -| subrange_type_declaration -| enumerated_type_declaration -; - -simple_type_declaration: -/* simple_type_name ':' simple_spec_init */ - identifier ':' simple_spec_init - {$$ = new simple_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_simple_type_name_token); - } -/* ERROR_CHECK_BEGIN */ -| error ':' simple_spec_init - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for data type declaration.");yyerrok;} -| identifier simple_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in simple type declaration."); yynerrs++;} -| identifier ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in data type declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in data type declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -simple_spec_init: - simple_specification - /* The following commented line was changed to the - * next two lines so that we wouldn't - * have the first element of a simple_spec_init_c() - * pointing to another simple_spec_init_c! - */ -/* -| simple_specification ASSIGN constant - {$$ = new simple_spec_init_c($1, $3);} -*/ -| elementary_type_name ASSIGN constant - {$$ = new simple_spec_init_c($1, $3, locloc(@$));} -| prev_declared_simple_type_name ASSIGN constant - {$$ = new simple_spec_init_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| elementary_type_name constant - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in specification with initialization."); yynerrs++;} -| prev_declared_simple_type_name constant - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in specification with initialization."); yynerrs++;} -| elementary_type_name ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in specification with initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid initial value in specification with initialization."); yyclearin;} - yyerrok; - } -| prev_declared_simple_type_name ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in specification with initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid initial value in specification with initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* When converting to C/C++, we need to know whether - * the elementary_type_name is being used in a variable - * declaration or elsewhere (ex. declaration of a derived - * type), so the abstract syntax has the elementary_type_name - * wrapped inside a simple_spec_init_c. - * The exact same thing occurs with prev_declared_simple_type_name. - * - * This is why in the definition of simple_spec_init, - * simple_specification was brocken up into its - * constituent components... - */ -simple_specification: -// elementary_type_name | simple_type_name - elementary_type_name - {$$ = new simple_spec_init_c($1, NULL, locloc(@$));} -| prev_declared_simple_type_name - {$$ = new simple_spec_init_c($1, NULL, locloc(@$));} -; - - -subrange_type_declaration: -/* subrange_type_name ':' subrange_spec_init */ - identifier ':' subrange_spec_init - {$$ = new subrange_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_subrange_type_name_token); - } -/* ERROR_CHECK_BEGIN */ -| error ':' subrange_spec_init - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for subrange type declaration."); yyerrok;} -| identifier subrange_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in subrange type declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -subrange_spec_init: - subrange_specification - {$$ = new subrange_spec_init_c($1, NULL, locloc(@$));} -| subrange_specification ASSIGN signed_integer - {$$ = new subrange_spec_init_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| subrange_specification signed_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in subrange specification with initialization."); yynerrs++;} -| subrange_specification ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in subrange specification with initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid initial value in subrange specification with initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -subrange_specification: - integer_type_name '(' subrange ')' - {$$ = new subrange_specification_c($1, $3, locloc(@$));} -| prev_declared_subrange_type_name - {$$ = new subrange_specification_c($1, NULL, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| integer_type_name '(' ')' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no subrange defined in subrange specification."); yynerrs++;} -| integer_type_name '(' error ')' - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid subrange defined in subrange specification."); yyerrok;} -| integer_type_name '(' subrange error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing after subrange defined in subrange specification."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -subrange: - signed_integer DOTDOT signed_integer - {$$ = new subrange_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| signed_integer signed_integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'..' missing between bounds in subrange definition."); yynerrs++;} -| signed_integer DOTDOT error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for upper bound in subrange definition.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for upper bound in subrange definition."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -enumerated_type_declaration: -/* enumerated_type_name ':' enumerated_spec_init */ - identifier ':' enumerated_spec_init - {$$ = new enumerated_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_enumerated_type_name_token); - } -/* ERROR_CHECK_BEGIN */ -| error ':' enumerated_spec_init - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid name defined for enumerated type declaration."); yyerrok;} -| identifier enumerated_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in enumerated type declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -enumerated_spec_init: - enumerated_specification - {$$ = new enumerated_spec_init_c($1, NULL, locloc(@$));} -| enumerated_specification ASSIGN enumerated_value - {$$ = new enumerated_spec_init_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| enumerated_specification enumerated_value - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in enumerated specification with initialization."); yynerrs++;} -| enumerated_specification ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined in enumerated specification with initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value in enumerated specification with initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -enumerated_specification: - '(' enumerated_value_list ')' - {$$ = $2;} -| prev_declared_enumerated_type_name -/* ERROR_CHECK_BEGIN */ -| '(' ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no enumerated value list defined in enumerated specification."); yynerrs++;} -| '(' error ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid enumerated value list defined in enumerated specification.");yyerrok;} -| '(' enumerated_value_list error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing at the end of enumerated specification."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for enumerated_specification */ -enumerated_value_list: - enumerated_value - {$$ = new enumerated_value_list_c(locloc(@$)); $$->add_element($1);} -| enumerated_value_list ',' enumerated_value - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| enumerated_value_list enumerated_value - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in enumerated value list.");} -| enumerated_value_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined in enumerated value list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value in enumerated value list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -enumerated_value: - identifier - {$$ = new enumerated_value_c(NULL, $1, locloc(@$));} -| prev_declared_enumerated_type_name '#' any_identifier - {$$ = new enumerated_value_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| prev_declared_enumerated_type_name any_identifier - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between enumerated type name and value in enumerated literal."); yynerrs++;} -| prev_declared_enumerated_type_name '#' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for enumerated literal.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for enumerated literal."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -/* -enumerated_value_without_identifier: - prev_declared_enumerated_type_name '#' any_identifier - {$$ = new enumerated_value_c($1, $3, locloc(@$));} -; -*/ - - -array_type_declaration: -/* array_type_name ':' array_spec_init */ - identifier ':' array_spec_init - {$$ = new array_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_array_type_name_token); - } -/* ERROR_CHECK_BEGIN */ -| identifier array_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in array type declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -array_spec_init: - array_specification - {$$ = new array_spec_init_c($1, NULL, locloc(@$));} -| array_specification ASSIGN array_initialization - {$$ = new array_spec_init_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| array_specification array_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in array specification with initialization."); yynerrs++;} -| array_specification ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in array specification with initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid initial value in array specification with initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -array_specification: - prev_declared_array_type_name -| ARRAY '[' array_subrange_list ']' OF non_generic_type_name - {$$ = new array_specification_c($3, $6, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| ARRAY array_subrange_list ']' OF non_generic_type_name - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'[' missing before subrange list in array specification."); yynerrs++;} -| ARRAY '[' ']' OF non_generic_type_name - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no subrange list defined in array specification."); yynerrs++;} -| ARRAY '[' error ']' OF non_generic_type_name - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid subrange list defined in array specification."); yyerrok;} -| ARRAY OF non_generic_type_name - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no subrange list defined in array specification."); yynerrs++;} -| ARRAY error OF non_generic_type_name - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid subrange list defined in array specification."); yyerrok;} -| ARRAY '[' array_subrange_list OF non_generic_type_name - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "']' missing after subrange list in array specification."); yynerrs++;} -| ARRAY '[' array_subrange_list ']' non_generic_type_name - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "'OF' missing between subrange list and item type name in array specification."); yynerrs++;} -| ARRAY '[' array_subrange_list ']' OF error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no item data type defined in array specification.");} - else {print_err_msg(locf(@3), locl(@3), "invalid item data type in array specification."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* helper symbol for array_specification */ -array_subrange_list: - subrange - {$$ = new array_subrange_list_c(locloc(@$)); $$->add_element($1);} -| array_subrange_list ',' subrange - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| array_subrange_list subrange - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in subrange list."); yynerrs++;} -| array_subrange_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no subrange defined in subrange list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid subrange in subrange list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -array_initialization: - '[' array_initial_elements_list ']' - {$$ = $2;} -/* ERROR_CHECK_BEGIN */ -| '[' ']' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no initial values list defined in array initialization."); yynerrs++;} -| '[' error ']' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid initial values list defined in array initialization."); yyerrok;} -| '[' array_initial_elements_list error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "']' missing at the end of array initialization."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for array_initialization */ -array_initial_elements_list: - array_initial_elements - {$$ = new array_initial_elements_list_c(locloc(@$)); $$->add_element($1);} -| array_initial_elements_list ',' array_initial_elements - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN -| array_initial_elements_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no array initial value in array initial values list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid array initial value in array initial values list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -array_initial_elements: - array_initial_element -| integer '(' ')' -| integer '(' array_initial_element ')' - {$$ = new array_initial_elements_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| integer '(' error ')' - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid array initial value in array initial values list."); yyerrok;} -| integer '(' array_initial_element error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing at the end of array initial value in array initial values list."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -array_initial_element: - constant -| enumerated_value -| structure_initialization -| array_initialization -; - - - -structure_type_declaration: -/* structure_type_name ':' structure_specification */ - identifier ':' structure_specification - {$$ = new structure_type_declaration_c($1, $3, locloc(@$)); - library_element_symtable.insert($1, prev_declared_structure_type_name_token); - } -/* ERROR_CHECK_BEGIN */ -| identifier structure_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between data type name and specification in structure type declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -structure_specification: - structure_declaration -| initialized_structure -; - - -initialized_structure: - prev_declared_structure_type_name - {$$ = new initialized_structure_c($1, NULL, locloc(@$));} -| prev_declared_structure_type_name ASSIGN structure_initialization - {$$ = new initialized_structure_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| prev_declared_structure_type_name structure_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in structure specification with initialization."); yynerrs++;} -| prev_declared_structure_type_name ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined in structure specification with initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value in structure specification with initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -structure_declaration: - STRUCT structure_element_declaration_list END_STRUCT - {$$ = $2;} -/* ERROR_CHECK_BEGIN */ -| STRUCT END_STRUCT - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no structure element declared in structure type declaration."); yynerrs++;} -| STRUCT error structure_element_declaration_list END_STRUCT - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'STRUCT' in structure type declaration."); yyerrok;} -| STRUCT structure_element_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed structure type declaration."); yyerrok;} -| STRUCT error END_STRUCT - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in structure type declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for structure_declaration */ -structure_element_declaration_list: - structure_element_declaration ';' - {$$ = new structure_element_declaration_list_c(locloc(@$)); $$->add_element($1);} -| structure_element_declaration_list structure_element_declaration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new structure_element_declaration_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid structure element declaration."); yyerrok;} -| structure_element_declaration error - {$$ = new structure_element_declaration_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of structure element declaration."); yyerrok;} -| structure_element_declaration_list structure_element_declaration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of structure element declaration."); yyerrok;} -| structure_element_declaration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid structure element declaration."); yyerrok;} -| structure_element_declaration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after structure element declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -structure_element_declaration: - structure_element_name ':' simple_spec_init - {$$ = new structure_element_declaration_c($1, $3, locloc(@$));} -| structure_element_name ':' subrange_spec_init - {$$ = new structure_element_declaration_c($1, $3, locloc(@$));} -| structure_element_name ':' enumerated_spec_init - {$$ = new structure_element_declaration_c($1, $3, locloc(@$));} -| structure_element_name ':' array_spec_init - {$$ = new structure_element_declaration_c($1, $3, locloc(@$));} -| structure_element_name ':' initialized_structure - {$$ = new structure_element_declaration_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| structure_element_name simple_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between structure element name and simple specification."); yynerrs++;} -| structure_element_name subrange_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between structure element name and subrange specification."); yynerrs++;} -| structure_element_name enumerated_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between structure element name and enumerated specification."); yynerrs++;} -| structure_element_name array_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between structure element name and array specification."); yynerrs++;} -| structure_element_name initialized_structure - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between structure element name and structure specification."); yynerrs++;} -| structure_element_name ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in structure element declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in structure element declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -structure_element_name: any_identifier; - - -structure_initialization: - '(' structure_element_initialization_list ')' - {$$ = $2;} -/* ERROR_CHECK_BEGIN */ -| '(' error ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid structure element initialization list in structure initialization."); yyerrok;} -| '(' structure_element_initialization_list error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "expecting ')' at the end of structure element initialization list in structure initialization."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for structure_initialization */ -structure_element_initialization_list: - structure_element_initialization - {$$ = new structure_element_initialization_list_c(locloc(@$)); $$->add_element($1);} -| structure_element_initialization_list ',' structure_element_initialization - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN -| structure_element_initialization_list structure_element_initialization - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in structure element initialization list in structure initialization."); yynerrs++;} -| structure_element_initialization_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no structure element initialization defined in structure initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid structure element initialization in structure initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -structure_element_initialization: - structure_element_name ASSIGN constant - {$$ = new structure_element_initialization_c($1, $3, locloc(@$));} -| structure_element_name ASSIGN enumerated_value - {$$ = new structure_element_initialization_c($1, $3, locloc(@$));} -| structure_element_name ASSIGN array_initialization - {$$ = new structure_element_initialization_c($1, $3, locloc(@$));} -| structure_element_name ASSIGN structure_initialization - {$$ = new structure_element_initialization_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| structure_element_name constant - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in structure element initialization."); yynerrs++;} -| structure_element_name enumerated_value - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in enumerated structure element initialization."); yynerrs++;} -| structure_element_name array_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in array structure element initialization."); yynerrs++;} -| structure_element_name structure_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing in structured structure element initialization."); yynerrs++;} -| structure_element_name ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in structured structure element initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid initial value in structured structure element initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* NOTE: in order to remove a reduce/reduce conflict, - * all occurences of string_type_name - * have been replaced with identifier! - */ -/* -string_type_name: identifier; -*/ - -string_type_declaration: -/* string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */ - identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init - {$$ = new string_type_declaration_c($1, $3, $4, $5, locloc(@$)); - library_element_symtable.insert($1, prev_declared_string_type_name_token); - } -; - - -/* helper symbol for string_type_declaration */ -string_type_declaration_size: - '[' integer ']' - {$$ = $2;} -/* REMOVED !! */ -//| /* empty */ -// {$$ = NULL;} -; -/* The syntax contains a reduce/reduce conflict. - * The optional '[' ']' - * has been changed to become mandatory to remove the conflict. - * - * The conflict arises because - * new_str_type : STRING := "hello!" - * may be reduced to a string_type_declaration OR - * a simple_type_declaration. - * - * Our change forces it to be reduced to a - * simple_type_declaration! - * We chose this option because changing the definition - * of simple_spec_init would force us to change all the other - * rules in which it appears. The change we made has no - * side-effects! - */ - -/* helper symbol for string_type_declaration */ -string_type_declaration_init: - /* empty */ - {$$ = NULL;} -| ASSIGN character_string - {$$ = $2;} -; - - - -/*********************/ -/* B 1.4 - Variables */ -/*********************/ -/* NOTE: The standard is erroneous in it's definition of 'variable' because: - * - The standard considers 'ENO' as a keyword... - * - ...=> which means that it may never be parsed as an 'identifier'... - * - ...=> and therefore may never be used as the name of a variable inside an expression. - * - However, a function/FB must be able to assign the ENO parameter - * it's value, doing it in an assignment statement, and therefore using the 'ENO' - * character sequence as an identifier! - * The obvious solution is to also allow the ENO keyword to be - * used as the name of a variable. Note that this variable may be used - * even though it is not explicitly declared as a function/FB variable, - * as the standard requires us to define it implicitly in this case! - * There are three ways of achieving this: - * (i) simply not define EN and ENO as keywords in flex (lexical analyser) - * and let them be considered 'identifiers'. Aditionally, add some code - * so that if they are not explicitly declared, we add them automatically to - * the declaration of each Functions and FB, where they would then be parsed - * as a previously_declared_variable. - * This approach has the advantage the EN and ENO would automatically be valid - * in every location where it needs to be valid, namely in the explicit declaration - * of these same variables, or when they are used within expressions. - * However, this approach has the drawback that - * EN and ENO could then also be used anywhere a standard identifier is allowed, - * including in the naming of Functions, FBs, Programs, Configurations, Resources, - * SFC Actions, SFC Steps, etc... - * This would mean that we would then have to add a lexical analysis check - * within the bison code (syntax analyser) to all the above constructs to make sure - * that the identifier being used is not EN or ENO. - * (ii) The other approach is to define EN and ENO as keywords / tokens in flex - * (lexical analyser) and then change the syntax in bison to acomodate - * these tokens wherever they could correctly appear. - * This has the drawback that we need to do some changes to the synax defintion. - * (iii) Yet a another option is to mix the above two methods. - * Define EN and ENO as tokens in flex, but change (only) the syntax for - * variable declaration to allow these tokens to also be used in declaring variables. - * From this point onwards these tokens are then considered a previously_declared_variable, - * since flex will first check for this before even checking for tokens. - * - * I (Mario) cuurretnly (2011) believe the cleanest method of achieving this goal - * is to use option (iii) - * However, considering that: - * - I have already previously implemented option (ii); - * - option (iii) requires that flex parse the previously_declared_variable - * before parsing any token. We already support this (remeber that this is - * used mainly to allow some IL operators as well as PRIORITY, etc. tokens - * to be used as identifiers, since the standard does not define them as keywords), - * but this part of the code in flex is often commented out as usually people do not expect - * us to follow the standard in the strict sense, but rather consider those - * tokens as keywords; - * considering the above, we currently carry on using option (ii). - */ -variable: - symbolic_variable -| prev_declared_direct_variable -| eno_identifier - {$$ = new symbolic_variable_c($1, locloc(@$));} -; - - -symbolic_variable: -/* NOTE: To be entirely correct, variable_name must be replacemed by - * prev_declared_variable_name | prev_declared_fb_name | prev_declared_global_var_name - */ - prev_declared_fb_name - {$$ = new symbolic_variable_c($1, locloc(@$));} -| prev_declared_global_var_name - {$$ = new symbolic_variable_c($1, locloc(@$));} -| prev_declared_variable_name - {$$ = new symbolic_variable_c($1, locloc(@$));} -| multi_element_variable -/* -| identifier - {$$ = new symbolic_variable_c($1, locloc(@$));} -*/ -; - - -/* NOTE: in section B 1.7, when configuring a program, symbolic_variable - * is used. Nevertheless, during the parsing of a configuration, - * the variables in question are out of scope, so we should - * be allowing any_identifier instead of prev_declared_variable_name! - * - * We therefore need a new any_symbolic_variable construct that - * allows the use of any_identifier instead of previously declared - * variables, function blocks, etc... - */ -any_symbolic_variable: -// variable_name -> replaced by any_identifier - any_identifier - {$$ = new symbolic_variable_c($1, locloc(@$));} -| any_multi_element_variable -; - - -/* for yet undeclared variable names ! */ -variable_name: identifier; - - - - - -/********************************************/ -/* B.1.4.1 Directly Represented Variables */ -/********************************************/ -prev_declared_direct_variable: prev_declared_direct_variable_token {$$ = new direct_variable_c($1, locloc(@$));}; - - - - -/*************************************/ -/* B.1.4.2 Multi-element Variables */ -/*************************************/ -multi_element_variable: - array_variable -| structured_variable -; - -/* please see note above any_symbolic_variable */ -any_multi_element_variable: - any_array_variable -| any_structured_variable -; - - -array_variable: - subscripted_variable '[' subscript_list ']' - {$$ = new array_variable_c($1, $3, locloc(@$));} -; - -/* please see note above any_symbolic_variable */ -any_array_variable: - any_subscripted_variable '[' subscript_list ']' - {$$ = new array_variable_c($1, $3, locloc(@$));} -; - - -subscripted_variable: - symbolic_variable -; - - -/* please see note above any_symbolic_variable */ -any_subscripted_variable: - any_symbolic_variable -; - - -subscript_list: - subscript - {$$ = new subscript_list_c(locloc(@$)); $$->add_element($1);} -| subscript_list ',' subscript - {$$ = $1; $$->add_element($3);} -; - - -subscript: expression; - - -structured_variable: - record_variable '.' field_selector - {$$ = new structured_variable_c($1, $3, locloc(@$));} -; - - -/* please see note above any_symbolic_variable */ -any_structured_variable: - any_record_variable '.' field_selector - {$$ = new structured_variable_c($1, $3, locloc(@$));} -; - - - -record_variable: - symbolic_variable -; - - -/* please see note above any_symbolic_variable */ -any_record_variable: - any_symbolic_variable -; - - -field_selector: - any_identifier -| eno_identifier -; - - - - - - -/******************************************/ -/* B 1.4.3 - Declaration & Initialisation */ -/******************************************/ -input_declarations: - VAR_INPUT input_declaration_list END_VAR - {$$ = new input_declarations_c(NULL, $2, new explicit_definition_c(), locloc(@$));} -| VAR_INPUT RETAIN input_declaration_list END_VAR - {$$ = new input_declarations_c(new retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));} -| VAR_INPUT NON_RETAIN input_declaration_list END_VAR - {$$ = new input_declarations_c(new non_retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_INPUT END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in input variable(s) declaration."); yynerrs++;} -| VAR_INPUT RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in retentive input variable(s) declaration."); yynerrs++;} -| VAR_INPUT NON_RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in non-retentive input variable(s) declaration."); yynerrs++;} -| VAR_INPUT error input_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_INPUT' in input variable(s) declaration."); yyerrok;} -| VAR_INPUT RETAIN error input_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive input variable(s) declaration."); yyerrok;} -| VAR_INPUT NON_RETAIN error input_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'NON_RETAIN' in non-retentive input variable(s) declaration."); yyerrok;} -| VAR_INPUT input_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed input variable(s) declaration."); yyerrok;} -| VAR_INPUT RETAIN input_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed retentive input variable(s) declaration."); yyerrok;} -| VAR_INPUT NON_RETAIN input_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed non-retentive input variable(s) declaration."); yyerrok;} -| VAR_INPUT error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in input variable(s) declaration."); yyerrok;} -| VAR_INPUT RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in retentive input variable(s) declaration."); yyerrok;} -| VAR_INPUT NON_RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in non-retentive input variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for input_declarations */ -input_declaration_list: - input_declaration ';' - {$$ = new input_declaration_list_c(locloc(@$)); $$->add_element($1);} -| input_declaration_list input_declaration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new input_declaration_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid input variable(s) declaration."); yyerrok;} -| input_declaration error - {$$ = new input_declaration_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of input variable(s) declaration."); yyerrok;} -| input_declaration_list input_declaration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of input variable(s) declaration."); yyerrok;} -| input_declaration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid input variable(s) declaration."); yyerrok;} -| input_declaration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after input variable(s) declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: The formal definition of 'input_declaration' as defined in the standard is erroneous, - * as it does not allow a user defined 'EN' input parameter. However, - * The semantic description of the languages clearly states that this is allowed. - * We have added the 'en_param_declaration' clause to cover for this. - */ -input_declaration: - var_init_decl -| edge_declaration -| en_param_declaration -; - - -edge_declaration: - var1_list ':' BOOL R_EDGE - {$$ = new edge_declaration_c(new raising_edge_option_c(locloc(@3)), $1, locloc(@$));} -| var1_list ':' BOOL F_EDGE - {$$ = new edge_declaration_c(new falling_edge_option_c(locloc(@3)), $1, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list BOOL R_EDGE - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in edge declaration."); yynerrs++;} -| var1_list BOOL F_EDGE - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in edge declaration."); yynerrs++;} -| var1_list ':' BOOL R_EDGE F_EDGE - {$$ = NULL; print_err_msg(locl(@5), locf(@5), "'R_EDGE' and 'F_EDGE' can't be present at the same time in edge declaration."); yynerrs++;} -| var1_list ':' BOOL F_EDGE R_EDGE - {$$ = NULL; print_err_msg(locl(@5), locf(@5), "'R_EDGE' and 'F_EDGE' can't be present at the same time in edge declaration."); yynerrs++;} -| var1_list ':' R_EDGE - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in edge declaration."); yynerrs++;} -| var1_list ':' F_EDGE - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in edge declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: The formal definition of the standard is erroneous, as it simply does not - * consider the EN and ENO keywords! - * The semantic description of the languages clearly states that these may be - * used in several ways. One of them is to declare an EN input parameter. - * We have added the 'en_param_declaration' clause to cover for this. - * - * Please read the comment above the definition of 'variable' in section B1.4 for details. - */ -en_param_declaration: - en_identifier ':' BOOL ASSIGN boolean_literal - {$$ = new en_param_declaration_c($1, new bool_type_name_c(locloc(@$)), $5, new explicit_definition_c(), locloc(@$));} -| en_identifier ':' BOOL ASSIGN integer - {$$ = new en_param_declaration_c($1, new bool_type_name_c(locloc(@$)), $5, new explicit_definition_c(), locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| en_identifier BOOL ASSIGN boolean_literal - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in EN declaration."); yynerrs++;} -| en_identifier BOOL ASSIGN integer - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in EN declaration."); yynerrs++;} -| en_identifier ':' ASSIGN boolean_literal - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in EN declaration."); yynerrs++;} -| en_identifier ':' ASSIGN integer - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'BOOL' missing in EN declaration."); yynerrs++;} -| en_identifier ':' BOOL ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in EN declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in EN declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -var_init_decl: - var1_init_decl -| array_var_init_decl -| structured_var_init_decl -| fb_name_decl -| string_var_declaration -; - - - - -var1_init_decl: - var1_list ':' simple_spec_init - {$$ = new var1_init_decl_c($1, $3, locloc(@$));} -| var1_list ':' subrange_spec_init - {$$ = new var1_init_decl_c($1, $3, locloc(@$));} -| var1_list ':' enumerated_spec_init - {$$ = new var1_init_decl_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list simple_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and simple specification."); yynerrs++;} -| var1_list subrange_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and subrange specification."); yynerrs++;} -| var1_list enumerated_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and enumerated specification."); yynerrs++;} -| var1_list ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -var1_list: - variable_name - {$$ = new var1_list_c(locloc(@$)); $$->add_element($1); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } - | var1_list ',' variable_name - {$$ = $1; $$->add_element($3); - variable_name_symtable.insert($3, prev_declared_variable_name_token); - } -/* ERROR_CHECK_BEGIN */ -| var1_list variable_name - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in variable list."); yynerrs++;} -| var1_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no variable name defined in variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid variable name in variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -array_var_init_decl: - var1_list ':' array_spec_init - {$$ = new array_var_init_decl_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list array_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and array specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -structured_var_init_decl: - var1_list ':' initialized_structure - {$$ = new structured_var_init_decl_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list initialized_structure - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and structured specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: see notes above fb_name_list and var1_list - * for reason why ':' was removed from this rule! - * In essence, to remove a shift/reduce conflict, - * the ':' was moved to var1_list and fb_name_list! - */ -fb_name_decl: -/* fb_name_list ':' function_block_type_name */ - fb_name_list_with_colon function_block_type_name - {$$ = new fb_name_decl_c($1, $2, NULL, locloc(@$));} -/*| fb_name_list ':' function_block_type_name ASSIGN structure_initialization */ -| fb_name_list_with_colon function_block_type_name ASSIGN structure_initialization - {$$ = new fb_name_decl_c($1, $2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| fb_name_list_with_colon ASSIGN structure_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block type name defined in function block declaration with initialization."); yynerrs++;} -| fb_name_list_with_colon function_block_type_name structure_initialization - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "':=' missing in function block declaration with initialization."); yynerrs++;} -| fb_name_list_with_colon function_block_type_name ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no initialization defined in function block declaration.");} - else {print_err_msg(locf(@4), locl(@4), "invalid initialization in function block declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -/* NOTE: In order to remove a reduce/reduce conflict between - * var1_list and fb_name_list, which are identical to each - * other, fb_name_list has been redefined to be a var1_list. - * - * In order to remove a further shift/reduce conflict, var1_list - * is imediately transfomred into var1_list_with_colon - * (i.e. it includes the ':' following the list), which - * means that fb_name_list is built from a - * var1_list_with_colon after all! - */ -/* -fb_name_list: - (* fb_name *) - identifier - {$$ = new fb_name_list_c($1); - variable_name_symtable.insert($1, prev_declared_fb_name_token); - } -(* | fb_name_list ',' fb_name *) -| fb_name_list ',' identifier - {$$ = $1; $$->add_element($3); - variable_name_symtable.insert($3, prev_declared_fb_name_token); - } -; -*/ - -fb_name_list_with_colon: - var1_list_with_colon - {$$ = new fb_name_list_c(locloc(@$)); - /* fill up the new fb_name_list_c object with the references - * contained in the var1_list_c object. - */ - FOR_EACH_ELEMENT(elem, $1, {$$->add_element(elem);}); - delete $1; - /* change the tokens associated with the symbols stored in - * the variable name symbol table from prev_declared_variable_name_token - * to prev_declared_fb_name_token - */ - FOR_EACH_ELEMENT(elem, $$, {variable_name_symtable.set(elem, prev_declared_fb_name_token);}); - } -; - -/* helper symbol for fb_name_list_with_colon */ -var1_list_with_colon: - var1_list ':' -; - - -// fb_name: identifier; - - - -output_declarations: - VAR_OUTPUT var_output_init_decl_list END_VAR - {$$ = new output_declarations_c(NULL, $2, new explicit_definition_c(), locloc(@$));} -| VAR_OUTPUT RETAIN var_output_init_decl_list END_VAR - {$$ = new output_declarations_c(new retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));} -| VAR_OUTPUT NON_RETAIN var_output_init_decl_list END_VAR - {$$ = new output_declarations_c(new non_retain_option_c(locloc(@2)), $3, new explicit_definition_c(), locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_OUTPUT END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in output variable(s) declaration."); yynerrs++;} -| VAR_OUTPUT RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in retentive output variable(s) declaration."); yynerrs++;} -| VAR_OUTPUT NON_RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in non-retentive output variable(s) declaration."); yynerrs++;} -| VAR_OUTPUT error var_output_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_OUPUT' in output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT RETAIN error var_output_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT NON_RETAIN error var_output_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'NON_RETAIN' in non-retentive output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT var_output_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT RETAIN var_output_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed retentive output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT NON_RETAIN var_output_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed non-retentive output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in retentive output variable(s) declaration."); yyerrok;} -| VAR_OUTPUT NON_RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in non-retentive output variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: The formal definition of 'var_output_init_decl' as defined in the standard is erroneous, - * as it does not allow a user defined 'ENO' output parameter. However, - * The semantic description of the languages clearly states that this is allowed. - * We have added the 'eno_param_declaration' clause to cover for this. - * - * Please read the comment above the definition of 'variable' in section B1.4 for details. - */ -var_output_init_decl: - var_init_decl -| eno_param_declaration -; - -var_output_init_decl_list: - var_output_init_decl ';' - {$$ = new var_init_decl_list_c(locloc(@$)); $$->add_element($1);} -| var_output_init_decl_list var_output_init_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| var_output_init_decl_list var_output_init_decl error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of variable(s) declaration."); yyerrok;} -| var_output_init_decl_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: The formal definition of the standard is erroneous, as it simply does not - * consider the EN and ENO keywords! - * The semantic description of the languages clearly states that these may be - * used in several ways. One of them is to declare an ENO output parameter. - * We have added the 'eno_param_declaration' clause to cover for this. - * - * Please read the comment above the definition of 'variable' in section B1.4 for details. - */ -eno_param_declaration: - eno_identifier ':' BOOL - /* NOTE We do _NOT_ include this variable in the previously_declared_variable symbol table! - * Please read the comment above the definition of 'variable' for the reason for this. - */ - {$$ = new eno_param_declaration_c($1, new bool_type_name_c(locloc(@$)), new explicit_definition_c(), locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| eno_identifier BOOL - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in ENO declaration."); yynerrs++;} -| eno_identifier ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in ENO declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in ENO declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -input_output_declarations: - VAR_IN_OUT var_declaration_list END_VAR - {$$ = new input_output_declarations_c($2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_IN_OUT END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in in_out variable(s) declaration."); yynerrs++;} -| VAR_IN_OUT error var_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_IN_OUT' in in_out variable(s) declaration."); yyerrok;} -| VAR_IN_OUT var_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed in_out variable(s) declaration."); yyerrok;} -| VAR_IN_OUT error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in in_out variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -/* helper symbol for input_output_declarations */ -var_declaration_list: - var_declaration ';' - {$$ = new var_declaration_list_c(locloc(@$)); $$->add_element($1);} -| var_declaration_list var_declaration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new var_declaration_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid variable(s) declaration."); yyerrok;} -| var_declaration error - {$$ = new var_declaration_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of variable(s) declaration."); yyerrok;} -| var_declaration_list var_declaration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of variable(s) declaration."); yyerrok;} -| var_declaration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid variable(s) declaration."); yyerrok;} -| var_declaration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after variable(s) declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -var_declaration: - temp_var_decl -| fb_name_decl -; - - -temp_var_decl: - var1_declaration -| array_var_declaration -| structured_var_declaration -| string_var_declaration -; - -var1_declaration: - var1_list ':' simple_specification - {$$ = new var1_init_decl_c($1, $3, locloc(@$));} -| var1_list ':' subrange_specification - {$$ = new var1_init_decl_c($1, $3, locloc(@$));} -| var1_list ':' enumerated_specification - {$$ = new var1_init_decl_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list simple_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and simple specification."); yynerrs++;} -| var1_list subrange_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and subrange specification."); yynerrs++;} -| var1_list enumerated_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and enumerated specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - - -array_var_declaration: - var1_list ':' array_specification - {$$ = new array_var_declaration_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list array_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and array specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -structured_var_declaration: - var1_list ':' prev_declared_structure_type_name - {$$ = new structured_var_declaration_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list prev_declared_structure_type_name - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and structured specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -var_declarations: - VAR var_init_decl_list END_VAR - {$$ = new var_declarations_c(NULL, $2, locloc(@$));} -| VAR CONSTANT var_init_decl_list END_VAR - {$$ = new var_declarations_c(new constant_option_c(locloc(@2)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in variable(s) declaration."); yynerrs++;} -| VAR CONSTANT END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in constant variable(s) declaration."); yynerrs++;} -| VAR error var_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@3), "unexpected token after 'VAR' in variable(s) declaration."); yyerrok;} -| VAR CONSTANT error var_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'CONSTANT' in constant variable(s) declaration."); yyerrok;} -| VAR var_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed variable(s) declaration."); yyerrok;} -| VAR CONSTANT var_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed constant variable(s) declaration."); yyerrok;} -| VAR error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in variable(s) declaration."); yyerrok;} -| VAR CONSTANT error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in constant variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -retentive_var_declarations: - VAR RETAIN var_init_decl_list END_VAR - {$$ = new retentive_var_declarations_c($3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in retentive variable(s) declaration."); yynerrs++;} -| VAR RETAIN error var_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive variable(s) declaration."); yyerrok;} -| VAR RETAIN var_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed retentive variable(s) declaration."); yyerrok;} -| VAR RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in retentive variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -located_var_declarations: - VAR located_var_decl_list END_VAR - {$$ = new located_var_declarations_c(NULL, $2, locloc(@$));} -| VAR CONSTANT located_var_decl_list END_VAR - {$$ = new located_var_declarations_c(new constant_option_c(locloc(@2)), $3, locloc(@$));} -| VAR RETAIN located_var_decl_list END_VAR - {$$ = new located_var_declarations_c(new retain_option_c(locloc(@2)), $3, locloc(@$));} -| VAR NON_RETAIN located_var_decl_list END_VAR - {$$ = new located_var_declarations_c(new non_retain_option_c(locloc(@2)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR NON_RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in non-retentive located variable(s) declaration."); yynerrs++;} -| VAR error located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR' in located variable(s) declaration."); yyerrok;} -| VAR CONSTANT error located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'CONSTANT' in constant located variable(s) declaration."); yyerrok;} -| VAR RETAIN error located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive located variable(s) declaration."); yyerrok;} -| VAR NON_RETAIN error located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'NON_RETAIN' in non-retentive located variable(s) declaration."); yyerrok;} -| VAR located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed located variable(s) declaration."); yyerrok;} -| VAR CONSTANT located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed constant located variable(s) declaration."); yyerrok;} -| VAR RETAIN located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed retentive located variable(s) declaration."); yyerrok;} -| VAR NON_RETAIN located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed non-retentive located variable(s) declaration."); yyerrok;} -| VAR NON_RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in non retentive variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for located_var_declarations */ -located_var_decl_list: - located_var_decl ';' - {$$ = new located_var_decl_list_c(locloc(@$)); $$->add_element($1);} -| located_var_decl_list located_var_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new located_var_decl_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid located variable declaration."); yyerrok;} -| located_var_decl error - {$$ = new located_var_decl_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of located variable declaration."); yyerrok;} -| located_var_decl_list located_var_decl error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of located variable declaration."); yyerrok;} -| located_var_decl_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid located variable declaration."); yyerrok;} -| located_var_decl_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after located variable declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -located_var_decl: - variable_name location ':' located_var_spec_init - {$$ = new located_var_decl_c($1, $2, $4, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } -| location ':' located_var_spec_init - {$$ = new located_var_decl_c(NULL, $1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| variable_name location located_var_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between located variable location and specification."); yynerrs++;} -| location located_var_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between located variable location and specification."); yynerrs++;} -| variable_name location ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in located variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in located variable declaration."); yyclearin;} - yyerrok; - } -| location ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in located variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in located variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - - -external_var_declarations: - VAR_EXTERNAL external_declaration_list END_VAR - {$$ = new external_var_declarations_c(NULL, $2, locloc(@$));} -| VAR_EXTERNAL CONSTANT external_declaration_list END_VAR - {$$ = new external_var_declarations_c(new constant_option_c(locloc(@2)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_EXTERNAL END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in external variable(s) declaration."); yynerrs++;} -| VAR_EXTERNAL CONSTANT END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in constant external variable(s) declaration."); yynerrs++;} -| VAR_EXTERNAL error external_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_EXTERNAL' in external variable(s) declaration."); yyerrok;} -| VAR_EXTERNAL CONSTANT error external_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'CONSTANT' in constant external variable(s) declaration."); yyerrok;} -| VAR_EXTERNAL external_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed external variable(s) declaration."); yyerrok;} -| VAR_EXTERNAL CONSTANT external_declaration_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed constant external variable(s) declaration."); yyerrok;} -| VAR_EXTERNAL error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in external variable(s) declaration."); yyerrok;} -| VAR_EXTERNAL CONSTANT error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in constant external variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for external_var_declarations */ -external_declaration_list: - external_declaration ';' - {$$ = new external_declaration_list_c(locloc(@$)); $$->add_element($1);} -| external_declaration_list external_declaration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new external_declaration_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid external variable declaration."); yyerrok;} -| external_declaration error - {$$ = new external_declaration_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of external variable declaration."); yyerrok;} -| external_declaration_list external_declaration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of external variable declaration."); yyerrok;} -| external_declaration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid external variable declaration."); yyerrok;} -| external_declaration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after external variable declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -external_declaration: - global_var_name ':' simple_specification - {$$ = new external_declaration_c($1, $3, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } -| global_var_name ':' subrange_specification - {$$ = new external_declaration_c($1, $3, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } -| global_var_name ':' enumerated_specification - {$$ = new external_declaration_c($1, $3, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } -| global_var_name ':' array_specification - {$$ = new external_declaration_c($1, $3, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } -| global_var_name ':' prev_declared_structure_type_name - {$$ = new external_declaration_c($1, $3, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_variable_name_token); - } -| global_var_name ':' function_block_type_name - {$$ = new external_declaration_c($1, $3, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_fb_name_token); - } -/* ERROR_CHECK_BEGIN */ -| global_var_name simple_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and simple specification."); yynerrs++;} -| global_var_name subrange_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and subrange specification."); yynerrs++;} -| global_var_name enumerated_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and enumerated specification."); yynerrs++;} -| global_var_name array_specification - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and array specification."); yynerrs++;} -| global_var_name prev_declared_structure_type_name - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and structured specification."); yynerrs++;} -| global_var_name function_block_type_name - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and function block type specification."); yynerrs++;} -| global_var_name ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in external variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in external variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -global_var_name: identifier; - - -global_var_declarations: - VAR_GLOBAL global_var_decl_list END_VAR - {$$ = new global_var_declarations_c(NULL, $2, locloc(@$));} -| VAR_GLOBAL CONSTANT global_var_decl_list END_VAR - {$$ = new global_var_declarations_c(new constant_option_c(locloc(@2)), $3, locloc(@$));} -| VAR_GLOBAL RETAIN global_var_decl_list END_VAR - {$$ = new global_var_declarations_c(new retain_option_c(locloc(@2)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_GLOBAL END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in global variable(s) declaration."); yynerrs++;} -| VAR_GLOBAL CONSTANT END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in constant global variable(s) declaration."); yynerrs++;} -| VAR_GLOBAL RETAIN END_VAR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable declared in retentive global variable(s) declaration."); yynerrs++;} -| VAR_GLOBAL error global_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_GLOBAL' in global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL CONSTANT error global_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'CONSTANT' in constant global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL RETAIN error global_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL global_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL CONSTANT global_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed constant global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL RETAIN global_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed retentive global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL CONSTANT error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in constant global variable(s) declaration."); yyerrok;} -| VAR_GLOBAL RETAIN error END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unknown error in constant global variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for global_var_declarations */ -global_var_decl_list: - global_var_decl ';' - {$$ = new global_var_decl_list_c(locloc(@$)); $$->add_element($1);} -| global_var_decl_list global_var_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new global_var_decl_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid global variable(s) declaration."); yyerrok;} -| global_var_decl error - {$$ = new global_var_decl_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of global variable(s) declaration."); yyerrok;} -| global_var_decl_list global_var_decl error - {$$ = $1; print_err_msg(locl(@1), locf(@2), "';' missing at end of global variable(s) declaration."); yyerrok;} -| global_var_decl_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid global variable(s) declaration."); yyerrok;} -| global_var_decl_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after global variable(s) declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -global_var_decl: -/* NOTE : This possibility defined in standard has no sense and generate a conflict (disabled) - global_var_spec ':' - {$$ = new global_var_decl_c($1, NULL, locloc(@$));} -*/ - global_var_spec ':' located_var_spec_init - {$$ = new global_var_decl_c($1, $3, locloc(@$));} -| global_var_spec ':' function_block_type_name - {$$ = new global_var_decl_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| global_var_list located_var_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between global variable list and type specification."); yynerrs++;} -| global_var_name location located_var_spec_init - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between global variable specification and type specification."); yynerrs++;} -| global_var_spec function_block_type_name - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between global variable specification and function block type specification."); yynerrs++;} -| global_var_spec ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in global variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in global variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -global_var_spec: - global_var_list {$$ = $1;} -| location - {$$ = new global_var_spec_c(NULL, $1, locloc(@$));} -| global_var_name location - {$$ = new global_var_spec_c($1, $2, locloc(@$)); - variable_name_symtable.insert($1, prev_declared_global_var_name_token); - } -; - - -located_var_spec_init: - simple_spec_init -| subrange_spec_init -| enumerated_spec_init -| array_spec_init -| initialized_structure -| single_byte_string_spec -| double_byte_string_spec -; - - -location: - AT direct_variable_token - {$$ = new location_c(new direct_variable_c($2, locloc(@$)), locloc(@$)); - direct_variable_symtable.insert($2, prev_declared_direct_variable_token); - } -/* ERROR_CHECK_BEGIN */ -| AT error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no location defined in location declaration.");} - else {print_err_msg(locf(@2), locl(@2), "invalid location in global location declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -global_var_list: - global_var_name - {$$ = new global_var_list_c(locloc(@$)); $$->add_element($1); - variable_name_symtable.insert($1, prev_declared_global_var_name_token); - } -| global_var_list ',' global_var_name - {$$ = $1; $$->add_element($3); - variable_name_symtable.insert($3, prev_declared_global_var_name_token); - } -/* ERROR_CHECK_BEGIN */ -| global_var_list global_var_name - {$$ = new global_var_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "',' missing in global variable list."); yynerrs++;} -| global_var_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no variable name defined in global variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid variable name in global variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -string_var_declaration: - single_byte_string_var_declaration -| double_byte_string_var_declaration -; - -single_byte_string_var_declaration: - var1_list ':' single_byte_string_spec - {$$ = new single_byte_string_var_declaration_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list single_byte_string_spec - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and string type specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -/* NOTE: The constructs - * - * [W]STRING - * and - * [W]STRING ASSIGN single_byte_character_string - * - * were removed as they are already contained - * within a other constructs. - * - * single_byte_string_spec is used in: - * - single_byte_string_var_declaration -> - * -> string_var_declaration ---> var_init_decl - * |--> temp_var_decl - * |--> var2_init_decl - * - located_var_spec_init - * - * STRING [ASSIGN string_constant] -> elementary_string_type_name -> - * -> simple_spec -> simple_specification -> simple_spec_init -> - * -> located_var_spec_init - * - * STRING [ASSIGN string_constant] -> elementary_string_type_name -> - * -> simple_spec -> simple_specification -> simple_spec_init -> - * -> var1_init_decl -> var_init_decl - * - * STRING [ASSIGN string_constant] -> elementary_string_type_name -> - * -> simple_spec -> simple_specification -> simple_spec_init -> - * -> var1_init_decl -> var2_init_decl - * - * STRING [ASSIGN string_constant] -> elementary_string_type_name -> - * -> simple_spec -> simple_specification -> - * -> var1_declaration -> temp_var_decl - */ -single_byte_string_spec: -/* STRING - {$$ = new single_byte_string_spec_c(NULL, NULL);} -*/ - STRING '[' integer ']' - {$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));} -/* -| STRING ASSIGN single_byte_character_string - {$$ = new single_byte_string_spec_c(NULL, $3, locloc(@$));} -*/ -| STRING '[' integer ']' ASSIGN single_byte_character_string - {$$ = new single_byte_string_spec_c($3, $6, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| STRING '[' error ']' - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} -| STRING '[' error ']' ASSIGN single_byte_character_string - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited string type specification."); yyerrok;} -| STRING '[' ']' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "missing length value for limited string type specification."); yynerrs++;} -| STRING '[' ']' ASSIGN single_byte_character_string - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "missing length value for limited string type specification."); yynerrs++;} -| STRING '[' integer error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "expecting ']' after length definition for limited string type specification."); yyerrok;} -| STRING '[' integer ']' single_byte_character_string - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "':=' missing before limited string type initialization."); yynerrs++;} -| STRING '[' integer ']' ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@5), locf(@6), "no initial value defined in limited string type initialization.");} - else {print_err_msg(locf(@6), locl(@6), "invalid initial value in limited string type initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -double_byte_string_var_declaration: - var1_list ':' double_byte_string_spec - {$$ = new double_byte_string_var_declaration_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| var1_list double_byte_string_spec - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and double byte string type specification."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -double_byte_string_spec: -/* WSTRING - {$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));} -*/ - WSTRING '[' integer ']' - {$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));} -/* -| WSTRING ASSIGN double_byte_character_string - {$$ = new double_byte_string_spec_c(NULL, $3, locloc(@$));} -*/ -| WSTRING '[' integer ']' ASSIGN double_byte_character_string - {$$ = new double_byte_string_spec_c($3, $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;} -| WSTRING '[' error ']' ASSIGN single_byte_character_string - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid length value for limited double byte string type specification."); yyerrok;} -| WSTRING '[' ']' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "missing length value for limited double byte string type specification."); yynerrs++;} -| WSTRING '[' ']' ASSIGN single_byte_character_string - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "missing length value for limited double byte string type specification."); yynerrs++;} -| WSTRING '[' integer error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "expecting ']' after length definition for limited double byte string type specification."); yyerrok;} -| WSTRING '[' integer ']' single_byte_character_string - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "':=' missing before limited double byte string type initialization."); yynerrs++;} -| WSTRING '[' integer ']' ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@5), locf(@6), "no initial value defined double byte in limited string type initialization.");} - else {print_err_msg(locf(@6), locl(@6), "invalid initial value in limited double byte string type initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -incompl_located_var_declarations: - VAR incompl_located_var_decl_list END_VAR - {$$ = new incompl_located_var_declarations_c(NULL, $2, locloc(@$));} -| VAR RETAIN incompl_located_var_decl_list END_VAR - {$$ = new incompl_located_var_declarations_c(new retain_option_c(locloc(@2)), $3, locloc(@$));} -| VAR NON_RETAIN incompl_located_var_decl_list END_VAR - {$$ = new incompl_located_var_declarations_c(new non_retain_option_c(locloc(@2)), $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR incompl_located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed incomplete located variable(s) declaration."); yyerrok;} -| VAR RETAIN incompl_located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed incomplete retentive located variable(s) declaration."); yyerrok;} -| VAR NON_RETAIN incompl_located_var_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed incomplete non-retentive located variable(s) declaration."); yyerrok;} -| VAR error incompl_located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR' in incomplete located variable(s) declaration."); yyerrok;} -| VAR RETAIN error incompl_located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive located variable(s) declaration."); yyerrok;} -| VAR NON_RETAIN error incompl_located_var_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'NON_RETAIN' in non-retentive located variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for incompl_located_var_declarations */ -incompl_located_var_decl_list: - incompl_located_var_decl ';' - {$$ = new incompl_located_var_decl_list_c(locloc(@$)); $$->add_element($1);} -| incompl_located_var_decl_list incompl_located_var_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| incompl_located_var_decl error - {$$ = new incompl_located_var_decl_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of incomplete located variable declaration."); yyerrok;} -| incompl_located_var_decl_list incompl_located_var_decl error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of incomplete located variable declaration."); yyerrok;} -| incompl_located_var_decl_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid incomplete located variable declaration."); yyerrok;} -| incompl_located_var_decl_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after incomplete located variable declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -incompl_located_var_decl: - variable_name incompl_location ':' var_spec - {$$ = new incompl_located_var_decl_c($1, $2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| variable_name incompl_location var_spec - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between incomplete located variable and type specification."); yynerrs++; - } -| variable_name incompl_location ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no specification defined in incomplete located variable declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid specification in incomplete located variable declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -incompl_location: - AT incompl_location_token - {$$ = new incompl_location_c($2, locloc(@$));} -; - - -var_spec: - simple_specification -| subrange_specification -| enumerated_specification -| array_specification -| prev_declared_structure_type_name -| string_spec -; - - -/* 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(@$));} -*/ - STRING '[' integer ']' - {$$ = new single_byte_string_spec_c($3, NULL, locloc(@$));} -/* -| WSTRING - {$$ = new double_byte_string_spec_c(NULL, NULL, locloc(@$));} -*/ -| WSTRING '[' integer ']' - {$$ = new double_byte_string_spec_c($3, NULL, locloc(@$));} -; - - - - -/* intermediate helper symbol for: - * - non_retentive_var_decls - * - var_declarations - */ -var_init_decl_list: - var_init_decl ';' - {$$ = new var_init_decl_list_c(locloc(@$)); $$->add_element($1);} -| var_init_decl_list var_init_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| var_init_decl_list var_init_decl error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of variable(s) declaration."); yyerrok;} -| var_init_decl_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - - -/***********************/ -/* B 1.5.1 - Functions */ -/***********************/ -/* -function_name: - prev_declared_derived_function_name -| standard_function_name -; -*/ - -/* The following rules should be set such as: - * function_name: function_name_no_clashes | function_name_simpleop_clashes | function_name_expression_clashes - * function_name: function_name_no_NOT_clashes | function_name_NOT_clashes; - */ - -function_name_no_clashes: prev_declared_derived_function_name | standard_function_name_no_clashes; -function_name_simpleop_clashes: standard_function_name_simpleop_clashes; -//function_name_expression_clashes: standard_function_name_expression_clashes; - -function_name_no_NOT_clashes: prev_declared_derived_function_name | standard_function_name_no_NOT_clashes; -//function_name_NOT_clashes: standard_function_name_NOT_clashes; - - -/* NOTE: The list of standard function names - * includes the standard functions MOD(), NOT() - * - * Strangely enough, MOD and NOT are reserved keywords, - * so shouldn't be used for function names. - * - * The specification contradicts itself! - * Our workaround is to treat MOD as a token, - * but to include this token as a - * standard_function_name. - * - * The names of all other standard functions get - * preloaded into the library_element_symbol_table - * with the token value of - * standard_function_name_token - * Actually, simply for completeness, MOD is also - * loaded into the library_element_symbol_table, but - * it is irrelevant since flex will catch MOD as a - * token, before it interprets it as an identifier, - * and looks in the library_element_symbol_table to check - * whether it has been previously declared. - * - * NOTE: The same as the above also occurs with the IL - * operators NOT AND OR XOR ADD SUB MUL DIV MOD - * GT GE EQ LT LE NE. - * Note that MOD is once again in the list! - * Anyway, we give these the same treatement as - * MOD, since we are writing a parser for ST and - * IL simultaneously. If this were not the case, - * the ST parser would not need the tokens NOT AND ... - * - * NOTE: Note that 'NOT' is special, as it conflicts - * with two operators: the IL 'NOT' operator, and - * the unary operator 'NOT' in ST!! - * - * NOTE: The IL language is ambiguous, since using NOT, AND, ... - * may be interpreted as either an IL operator, or - * as a standard function call! - * I (Mario) opted to interpret it as an IL operator. - * This requires changing the syntax for IL language - * function calling, to exclude all function with - * names that clash with IL operators. I therefore - * created the constructs - * function_name_without_clashes - * standard_function_name_without_clashes - * to include all function names, except those that clash - * with IL operators. These constructs are only used - * within the IL language! - */ -/* The following rules should be set such as: - * standard_function_name: standard_function_name_no_clashes | standard_function_name_simpleop_clashes | standard_function_name_expression_clashes - * standard_function_name: standard_function_name_no_NOT_clashes | standard_function_name_NOT_clashes; - */ - -/* -standard_function_name: - standard_function_name_no_clashes -| standard_function_name_expression_clashes -| standard_function_name_NOT_clashes -//| standard_function_name_simpleop_only_clashes -; -*/ - -standard_function_name_no_NOT_clashes: - standard_function_name_no_clashes -| standard_function_name_expression_clashes -//| standard_function_name_simpleop_only_clashes -; - -standard_function_name_no_clashes: - standard_function_name_token - {$$ = new identifier_c($1, locloc(@$));} -; - - -standard_function_name_simpleop_clashes: - standard_function_name_NOT_clashes -//| standard_function_name_simpleop_only_clashes -; - -standard_function_name_NOT_clashes: - NOT - {$$ = new identifier_c(strdup("NOT"), locloc(@$));} -; - -/* Add here any other IL simple operators that collide - * with standard function names! - * Don't forget to uncomment the equivalent lines in - * - standard_function_name_simpleop_clashes - * - standard_function_name - * - standard_function_name_no_NOT_clashes - */ -/* -standard_function_name_simpleop_only_clashes: -; -*/ - -standard_function_name_expression_clashes: - AND {$$ = new identifier_c(strdup("AND"), locloc(@$));} -| OR {$$ = new identifier_c(strdup("OR"), locloc(@$));} -| XOR {$$ = new identifier_c(strdup("XOR"), locloc(@$));} -| ADD {$$ = new identifier_c(strdup("ADD"), locloc(@$));} -| SUB {$$ = new identifier_c(strdup("SUB"), locloc(@$));} -| MUL {$$ = new identifier_c(strdup("MUL"), locloc(@$));} -| DIV {$$ = new identifier_c(strdup("DIV"), locloc(@$));} -| MOD {$$ = new identifier_c(strdup("MOD"), locloc(@$));} -| GT {$$ = new identifier_c(strdup("GT"), locloc(@$));} -| GE {$$ = new identifier_c(strdup("GE"), locloc(@$));} -| EQ {$$ = new identifier_c(strdup("EQ"), locloc(@$));} -| LT {$$ = new identifier_c(strdup("LT"), locloc(@$));} -| LE {$$ = new identifier_c(strdup("LE"), locloc(@$));} -| NE {$$ = new identifier_c(strdup("NE"), locloc(@$));} -/* - AND_operator {$$ = il_operator_c_2_identifier_c($1);} -//NOTE: AND2 (corresponding to the source code string '&') does not clash -// with a standard function name, so should be commented out! -//| AND2_operator {$$ = il_operator_c_2_identifier_c($1);} -| OR_operator {$$ = il_operator_c_2_identifier_c($1);} -| XOR_operator {$$ = il_operator_c_2_identifier_c($1);} -| ADD_operator {$$ = il_operator_c_2_identifier_c($1);} -| SUB_operator {$$ = il_operator_c_2_identifier_c($1);} -| MUL_operator {$$ = il_operator_c_2_identifier_c($1);} -| DIV_operator {$$ = il_operator_c_2_identifier_c($1);} -| MOD_operator {$$ = il_operator_c_2_identifier_c($1);} -| GT_operator {$$ = il_operator_c_2_identifier_c($1);} -| GE_operator {$$ = il_operator_c_2_identifier_c($1);} -| EQ_operator {$$ = il_operator_c_2_identifier_c($1);} -| LT_operator {$$ = il_operator_c_2_identifier_c($1);} -| LE_operator {$$ = il_operator_c_2_identifier_c($1);} -| NE_operator {$$ = il_operator_c_2_identifier_c($1);} -*/ -; - - -derived_function_name: - identifier -| prev_declared_derived_function_name - {$$ = $1; - if (not(allow_function_overloading)) { - fprintf(stderr, "Function overloading not allowed. Invalid identifier %s\n", ((token_c *)($1))->value); - ERROR; - } - } -; - - -function_declaration: -/* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ - function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION - {$$ = new function_declaration_c($1, $3, $4, $5, locloc(@$)); - 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(); - if (allow_function_overloading) { - switch (library_element_symtable.find_value($1)) { - case prev_declared_derived_function_name_token: - /* do nothing, already in map. */ - break; - case BOGUS_TOKEN_ID: - /* Not yet in map. Must insert...*/ - library_element_symtable.insert($1, prev_declared_derived_function_name_token); - break; - default: - /* Already in map but associated with something else other than a funtion name! */ - ERROR; - } - } else { - library_element_symtable.insert($1, prev_declared_derived_function_name_token); - } - } -/* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ -| function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION - {$$ = new function_declaration_c($1, $3, $4, $5, locloc(@$)); - 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(); - if (allow_function_overloading) { - switch (library_element_symtable.find_value($1)) { - case prev_declared_derived_function_name_token: /* do nothing, already in map. */ break; - case BOGUS_TOKEN_ID: library_element_symtable.insert($1, prev_declared_derived_function_name_token); break; - default: ERROR; - } - } else { - library_element_symtable.insert($1, prev_declared_derived_function_name_token); - } - } -/* ERROR_CHECK_BEGIN */ -| function_name_declaration elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing after function name in function declaration."); yynerrs++;} -| function_name_declaration derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing after function name in function declaration."); yynerrs++;} -| function_name_declaration ':' io_OR_function_var_declarations_list function_body END_FUNCTION - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no return type defined in function declaration."); yynerrs++;} -| function_name_declaration ':' error io_OR_function_var_declarations_list function_body END_FUNCTION - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid return type defined in function declaration."); yyerrok;} -| function_name_declaration ':' elementary_type_name function_body END_FUNCTION - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no variable(s) declared in function declaration."); yynerrs++;} -| function_name_declaration ':' derived_type_name function_body END_FUNCTION - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no variable(s) declared in function declaration."); yynerrs++;} -| function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list END_FUNCTION - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "no body defined in function declaration."); yynerrs++;} -| function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list END_FUNCTION - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "no body defined in function declaration."); yynerrs++;} -| function_name_declaration ':' elementary_type_name END_FUNCTION - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no variable(s) declared and body defined in function declaration."); yynerrs++;} -| function_name_declaration ':' derived_type_name END_FUNCTION - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no variable(s) declared and body defined in function declaration."); yynerrs++;} -| function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locf(@3), "unclosed function declaration."); yynerrs++;} -| function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list function_body END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "unclosed function declaration."); yynerrs++;} -| function_name_declaration error END_FUNCTION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -/* helper symbol for function_declaration */ -/* NOTE: due to reduce/reduce conflicts between identifiers - * being reduced to either a variable or an enumerator value, - * we were forced to keep a symbol table of the names - * of all declared variables. Variables are no longer - * created from simple identifier_token, but from - * prev_declared_variable_name_token. - * - * BUT, in functions the function name itself may be used as - * a variable! In order to be able to parse this correctly, - * the token parser (flex) must return a prev_declared_variable_name_token - * when it comes across the function name, while parsing - * the function itself. - * We do this by inserting the function name into the variable - * symbol table, and having flex return a prev_declared_variable_name_token - * whenever it comes across it. - * When we finish parsing the function the variable name - * symbol table is cleared of all entries, and the function - * name is inserted into the library element symbol table. This - * means that from then onwards flex will return a - * derived_function_name_token whenever it comes across the - * function name. - * - * In order to insert the function name into the variable_name - * symbol table BEFORE the function body gets parsed, we - * need the parser to reduce a construct that contains the - * the function name. That is why we created this extra - * construct (function_name_declaration), i.e. to force - * the parser to reduce it, before parsing the function body! - */ -function_name_declaration: - FUNCTION derived_function_name - {$$ = $2; - /* the function name functions as a - * variable within the function itself! - * - * Remember that the variable_name_symtable - * is cleared once the end of the function - * is parsed. - */ - variable_name_symtable.insert($2, prev_declared_variable_name_token); - } -/* ERROR_CHECK_BEGIN */ -| FUNCTION error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no function name defined in function declaration.");} - else {print_err_msg(locf(@2), locl(@2), "invalid function name in function declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -/* intermediate helper symbol for function_declaration */ -io_OR_function_var_declarations_list: - io_var_declarations - {$$ = new var_declarations_list_c(locloc(@1));$$->add_element($1);} -| function_var_decls - {$$ = new var_declarations_list_c(locloc(@1));$$->add_element($1);} -| io_OR_function_var_declarations_list io_var_declarations - {$$ = $1; $$->add_element($2);} -| io_OR_function_var_declarations_list function_var_decls - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| io_OR_function_var_declarations_list retentive_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected retentive variable(s) declaration in function declaration."); yynerrs++;} -| io_OR_function_var_declarations_list located_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected located variable(s) declaration in function declaration."); yynerrs++;} -| io_OR_function_var_declarations_list external_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected external variable(s) declaration in function declaration."); yynerrs++;} -| io_OR_function_var_declarations_list global_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected global variable(s) declaration in function declaration."); yynerrs++;} -| io_OR_function_var_declarations_list incompl_located_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected incomplete located variable(s) declaration in function declaration."); yynerrs++;} -| io_OR_function_var_declarations_list temp_var_decls - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected temporary located variable(s) declaration in function declaration."); yynerrs++;} -| io_OR_function_var_declarations_list non_retentive_var_decls - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected non-retentive variable(s) declaration in function declaration."); yynerrs++;} -/*| io_OR_function_var_declarations_list access_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected access variable(s) declaration in function declaration."); yynerrs++;}*/ -| io_OR_function_var_declarations_list instance_specific_initializations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected instance specific initialization(s) in function declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -io_var_declarations: - input_declarations -| output_declarations -| input_output_declarations -; - - -function_var_decls: - VAR CONSTANT var2_init_decl_list END_VAR - {$$ = new function_var_decls_c(new constant_option_c(locloc(@2)), $3, locloc(@$));} -| VAR var2_init_decl_list END_VAR - {$$ = new function_var_decls_c(NULL, $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR error var2_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR' in function variable(s) declaration."); yyerrok;} -| VAR CONSTANT error var2_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'CONSTANT' in constant function variable(s) declaration."); yyerrok;} -| VAR var2_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed function variable(s) declaration."); yyerrok;} -| VAR CONSTANT var2_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed constant function variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* intermediate helper symbol for function_var_decls */ -var2_init_decl_list: - var2_init_decl ';' - {$$ = new var2_init_decl_list_c(locloc(@$)); $$->add_element($1);} -| var2_init_decl_list var2_init_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| var2_init_decl error - {$$ = new var2_init_decl_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of function variable(s) declaration."); yyerrok;} -| var2_init_decl_list var2_init_decl error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of function variable(s) declaration."); yyerrok;} -| var2_init_decl_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid function variable(s) declaration."); yyerrok;} -| var2_init_decl_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after function variable(s) declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -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! */ -/* -| ladder_diagram -| function_block_diagram -*/ -; - - -var2_init_decl: - var1_init_decl -| array_var_init_decl -| structured_var_init_decl -| string_var_declaration -; - - - -/*****************************/ -/* B 1.5.2 - Function Blocks */ -/*****************************/ -function_block_type_name: - prev_declared_derived_function_block_name -| standard_function_block_name -; - - -standard_function_block_name: standard_function_block_name_token {$$ = new identifier_c($1, locloc(@$));}; - -derived_function_block_name: identifier; - - -function_block_declaration: - FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK - {$$ = new function_block_declaration_c($2, $3, $4, locloc(@$)); - add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */ - library_element_symtable.insert($2, prev_declared_derived_function_block_name_token); - /* Clear the variable_name_symtable. Since - * we have finished parsing the function block, - * the variable names are now out of scope, so - * are no longer valid! - */ - variable_name_symtable.pop(); - direct_variable_symtable.pop(); - } -/* ERROR_CHECK_BEGIN */ -| FUNCTION_BLOCK io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block name defined in function block declaration."); yynerrs++;} -| FUNCTION_BLOCK error io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid function block name in function block declaration."); yyerrok;} -| FUNCTION_BLOCK derived_function_block_name function_block_body END_FUNCTION_BLOCK - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared in function declaration."); yynerrs++;} -| FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list END_FUNCTION_BLOCK - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no body defined in function block declaration."); yynerrs++;} -| FUNCTION_BLOCK derived_function_block_name END_FUNCTION_BLOCK - {$$ = 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++;} -| FUNCTION_BLOCK error END_FUNCTION_BLOCK - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function block declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -/* intermediate helper symbol for function_declaration */ -/* { io_var_declarations | other_var_declarations } */ -/* - * NOTE: we re-use the var_declarations_list_c - */ -io_OR_other_var_declarations_list: - io_var_declarations - {$$ = new var_declarations_list_c(locloc(@$));$$->add_element($1);} -| other_var_declarations - {$$ = new var_declarations_list_c(locloc(@$));$$->add_element($1);} -| io_OR_other_var_declarations_list io_var_declarations - {$$ = $1; $$->add_element($2);} -| io_OR_other_var_declarations_list other_var_declarations - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| io_OR_other_var_declarations_list located_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected located variable(s) declaration in function block declaration."); yynerrs++;} -| io_OR_other_var_declarations_list global_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected global variable(s) declaration in function block declaration."); yynerrs++;} -/*| io_OR_other_var_declarations_list access_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected access variable(s) declaration in function block declaration."); yynerrs++;}*/ -| io_OR_other_var_declarations_list instance_specific_initializations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected instance specific initialization(s) in function block declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -/* NOTE: - * The IEC specification gives the following definition: - * other_var_declarations ::= - * external_var_declarations - * | var_declarations - * | retentive_var_declarations - * | non_retentive_var_declarations - * | temp_var_decls - * | incompl_located_var_declarations - * - * Nvertheless, the symbol non_retentive_var_declarations - * is not defined in the spec. This seems to me (Mario) - * to be a typo, so non_retentive_var_declarations - * has been replaced with non_retentive_var_decls - * in the following rule! - */ -other_var_declarations: - temp_var_decls -| non_retentive_var_decls -| external_var_declarations -| var_declarations -| retentive_var_declarations -| incompl_located_var_declarations -; - - -temp_var_decls: - VAR_TEMP temp_var_decls_list END_VAR - {$$ = new temp_var_decls_c($2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_TEMP END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in temporary variable(s) declaration."); yynerrs++;} -| VAR_TEMP temp_var_decls_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "unclosed temporary variable(s) declaration."); yyerrok;} -| VAR_TEMP error temp_var_decls_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_TEMP' in function variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* intermediate helper symbol for temp_var_decls */ -temp_var_decls_list: - temp_var_decl ';' - {$$ = new temp_var_decls_list_c(locloc(@$)); $$->add_element($1);} -| temp_var_decls_list temp_var_decl ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new temp_var_decls_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid temporary variable(s) declaration."); yyerrok;} -| temp_var_decl error - {$$ = new temp_var_decls_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at end of temporary variable(s) declaration."); yyerrok;} -| temp_var_decls_list temp_var_decl error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of temporary variable(s) declaration."); yyerrok;} -| temp_var_decls_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid temporary variable(s) declaration."); yyerrok;} -| temp_var_decls_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after temporary variable(s) declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -non_retentive_var_decls: - VAR NON_RETAIN var_init_decl_list END_VAR - {$$ = new non_retentive_var_decls_c($3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR NON_RETAIN var_init_decl_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unclosed non-retentive temporary variable(s) declaration."); yyerrok;} -| VAR NON_RETAIN error var_init_decl_list END_VAR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'NON_RETAIN' in non-retentive temporary variable(s) declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -function_block_body: - statement_list {$$ = $1;} -| instruction_list {$$ = $1;} -| sequential_function_chart {$$ = $1;} -/* -| ladder_diagram -| function_block_diagram -| -*/ -; - - - - -/**********************/ -/* B 1.5.3 - Programs */ -/**********************/ -program_type_name: identifier; - - -program_declaration: - PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM - {$$ = new program_declaration_c($2, $3, $4, locloc(@$)); - library_element_symtable.insert($2, prev_declared_program_type_name_token); - /* Clear the variable_name_symtable. Since - * we have finished parsing the program declaration, - * the variable names are now out of scope, so - * are no longer valid! - */ - variable_name_symtable.pop(); - direct_variable_symtable.pop(); - } -/* ERROR_CHECK_BEGIN */ -| PROGRAM program_var_declarations_list function_block_body END_PROGRAM - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no program name defined in program declaration.");} -| PROGRAM error program_var_declarations_list function_block_body END_PROGRAM - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid program name in program declaration."); yyerrok;} -| PROGRAM program_type_name function_block_body END_PROGRAM - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared in program declaration."); yynerrs++;} -| PROGRAM program_type_name program_var_declarations_list END_PROGRAM - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no body defined in program declaration."); yynerrs++;} -| PROGRAM program_type_name END_PROGRAM - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in program declaration."); yynerrs++;} -| PROGRAM program_type_name program_var_declarations_list function_block_body END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed program declaration."); yynerrs++;} -| PROGRAM error END_PROGRAM - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in program declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for program_declaration */ -/* - * NOTE: we re-use the var_declarations_list_c - */ -program_var_declarations_list: - io_var_declarations - {$$ = new var_declarations_list_c(locloc(@$)); $$->add_element($1);} -| other_var_declarations - {$$ = new var_declarations_list_c(locloc(@$)); $$->add_element($1);} -| located_var_declarations - {$$ = new var_declarations_list_c(locloc(@$)); $$->add_element($1);} -| program_var_declarations_list io_var_declarations - {$$ = $1; $$->add_element($2);} -| program_var_declarations_list other_var_declarations - {$$ = $1; $$->add_element($2);} -| program_var_declarations_list located_var_declarations - {$$ = $1; $$->add_element($2);} -/* -| program_var_declarations_list program_access_decls - {$$ = $1; $$->add_element($2);} -*/ -/* ERROR_CHECK_BEGIN */ -| program_var_declarations_list global_var_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected global variable(s) declaration in function block declaration."); yynerrs++;} -/*| program_var_declarations_list access_declarations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected access variable(s) declaration in function block declaration."); yynerrs++;}*/ -| program_var_declarations_list instance_specific_initializations - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected instance specific initialization(s) in function block declaration."); yynerrs++; - } -/* ERROR_CHECK_END */ -; - - -/* TODO ... */ -/* -program_access_decls: - VAR_ACCESS program_access_decl_list END_VAR -; -*/ - -/* helper symbol for program_access_decls */ -/* -program_access_decl_list: - program_access_decl ';' -| program_access_decl_list program_access_decl ';' -; -*/ - -/* -program_access_decl: - access_name ':' symbolic_variable ':' non_generic_type_name -| access_name ':' symbolic_variable ':' non_generic_type_name direction -; -*/ - - - -/********************************************/ -/* B 1.6 Sequential Function Chart elements * -/********************************************/ - -sequential_function_chart: - sfc_network - {$$ = new sequential_function_chart_c(locloc(@$)); $$->add_element($1);} -| sequential_function_chart sfc_network - {$$ = $1; $$->add_element($2);} -; - -sfc_network: - initial_step - {$$ = new sfc_network_c(locloc(@$)); $$->add_element($1);} -| sfc_network step - {$$ = $1; $$->add_element($2);} -| sfc_network transition - {$$ = $1; $$->add_element($2);} -| sfc_network action - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| sfc_network error - {$$ = $1; print_err_msg(locl(@1), locf(@2), "unexpected token after SFC network in sequencial function chart."); yyerrok;} -/* ERROR_CHECK_END */ -; - -initial_step: - INITIAL_STEP step_name ':' action_association_list END_STEP -// INITIAL_STEP identifier ':' action_association_list END_STEP - {$$ = new initial_step_c($2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| INITIAL_STEP ':' action_association_list END_STEP - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "no step name defined in initial step declaration."); yynerrs++;} -| INITIAL_STEP error ':' action_association_list END_STEP - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid step name defined in initial step declaration."); yyerrok;} -| INITIAL_STEP step_name action_association_list END_STEP - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "':' missing after step name in initial step declaration."); yynerrs++;} -| INITIAL_STEP step_name ':' error END_STEP - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid action association list in initial step declaration."); yyerrok;} -| INITIAL_STEP step_name ':' action_association_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "unclosed initial step declaration."); yynerrs++;} -| INITIAL_STEP error END_STEP - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in initial step declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -step: - STEP step_name ':' action_association_list END_STEP -// STEP identifier ':' action_association_list END_STEP - {$$ = new step_c($2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| STEP ':' action_association_list END_STEP - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no step name defined in step declaration."); yynerrs++;} -| STEP error ':' action_association_list END_STEP - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid step name defined in step declaration."); yyerrok;} -| STEP step_name action_association_list END_STEP - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "':' missing after step name in step declaration."); yynerrs++;} -| STEP step_name ':' error END_STEP - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid action association list in step declaration."); yyerrok;} -| STEP step_name ':' action_association_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "invalid action association list in step declaration."); yynerrs++;} -| STEP error END_STEP - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in step declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for: - * - initial_step - * - step - */ -action_association_list: - /* empty */ - {$$ = new action_association_list_c(locloc(@$));} -| action_association_list action_association ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| action_association_list action_association error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at end of action association declaration."); yyerrok;} -| action_association_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after action association declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -// step_name: identifier; -step_name: any_identifier; - -action_association: - action_name '(' {cmd_goto_sfc_qualifier_state();} action_qualifier {cmd_pop_state();} indicator_name_list ')' - {$$ = new action_association_c($1, $4, $6, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -/*| action_name '(' error ')' - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid qualifier defined in action association."); yyerrok;}*/ -/* ERROR_CHECK_END */ -; - -/* helper symbol for action_association */ -indicator_name_list: - /* empty */ - {$$ = new indicator_name_list_c(locloc(@$));} -| indicator_name_list ',' indicator_name - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| indicator_name_list indicator_name - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing at end of action association declaration."); yynerrs++;} -| indicator_name_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no indicator defined in indicator list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid indicator in indicator list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -// action_name: identifier; -action_name: any_identifier; - -action_qualifier: - /* empty */ - {$$ = NULL;} -| qualifier - {$$ = new action_qualifier_c($1, NULL, locloc(@$));} -| timed_qualifier ',' action_time - {$$ = new action_qualifier_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| timed_qualifier action_time - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "',' missing between timed qualifier and action time in action qualifier."); yynerrs++;} -| timed_qualifier ',' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no action time defined in action qualifier.");} - else {print_err_msg(locf(@3), locl(@3), "invalid action time in action qualifier."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -qualifier: - N {$$ = new qualifier_c(strdup("N"), locloc(@$));} -| R {$$ = new qualifier_c(strdup("R"), locloc(@$));} -| S {$$ = new qualifier_c(strdup("S"), locloc(@$));} -| P {$$ = new qualifier_c(strdup("P"), locloc(@$));} -; - -timed_qualifier: - L {$$ = new timed_qualifier_c(strdup("L"), locloc(@$));} -| D {$$ = new timed_qualifier_c(strdup("D"), locloc(@$));} -| SD {$$ = new timed_qualifier_c(strdup("SD"), locloc(@$));} -| DS {$$ = new timed_qualifier_c(strdup("DS"), locloc(@$));} -| SL {$$ = new timed_qualifier_c(strdup("SL"), locloc(@$));} -; - -action_time: - duration -| variable -; - -indicator_name: variable; - -// transition_name: identifier; -transition_name: any_identifier; - - -steps: - step_name - {$$ = new steps_c($1, NULL, locloc(@$));} -| '(' step_name_list ')' - {$$ = new steps_c(NULL, $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| '(' step_name_list error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "expecting ')' at the end of step list in transition declaration."); yyerrok;} -| '(' error ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid step list in transition declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -step_name_list: - step_name ',' step_name - {$$ = new step_name_list_c(locloc(@$)); $$->add_element($1); $$->add_element($3);} -| step_name_list ',' step_name - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| step_name_list step_name - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in step list."); yynerrs++;} -| step_name_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no step name defined in step list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid step name in step list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -/* NOTE: flex will automatically pop() out of body_state to previous state. - * We do not need to give a command from bison to return to previous flex state, - * after forcing flex to go to body_state. - */ -transition: - TRANSITION transition_priority - FROM steps TO steps - {cmd_goto_body_state();} transition_condition - END_TRANSITION - {$$ = new transition_c(NULL, $2, $4, $6, $8, locloc(@$));} -//| TRANSITION identifier FROM steps TO steps ... -| TRANSITION transition_name transition_priority - FROM steps TO steps - {cmd_goto_body_state();} transition_condition - END_TRANSITION - {$$ = new transition_c($2, $3, $5, $7, $9, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| TRANSITION error transition_priority FROM steps TO steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid transition name defined in transition declaration."); yyerrok;} -| TRANSITION transition_name error FROM steps TO steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid transition priority defined in transition declaration."); yyerrok;} -| TRANSITION transition_priority FROM TO steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no origin step(s) defined in transition declaration."); yynerrs++;} -| TRANSITION transition_name transition_priority FROM TO steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "no origin step(s) defined in transition declaration."); yynerrs++;} -| TRANSITION transition_priority FROM error TO steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid origin step(s) defined in transition declaration."); yyerrok;} -| TRANSITION transition_name transition_priority FROM error TO steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locf(@5), locl(@5), "invalid origin step(s) defined in transition declaration."); yyerrok;} -| TRANSITION transition_priority FROM steps steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "'TO' missing between origin step(s) and destination step(s) in transition declaration."); yynerrs++;} -| TRANSITION transition_name transition_priority FROM steps steps {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@5), locf(@6), "'TO' missing between origin step(s) and destination step(s) in transition declaration."); yynerrs++;} -| TRANSITION transition_priority FROM steps TO {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@5), locf(@7), "no destination step(s) defined in transition declaration."); yynerrs++;} -| TRANSITION transition_name transition_priority FROM steps TO {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@6), locf(@8), "no destination step(s) defined in transition declaration."); yynerrs++;} -| TRANSITION transition_priority FROM steps TO error {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locf(@6), locl(@6), "invalid destination step(s) defined in transition declaration."); yyerrok;} -| TRANSITION transition_name transition_priority FROM steps TO error {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locf(@7), locl(@7), "invalid destination step(s) defined in transition declaration."); yyerrok;} -| TRANSITION transition_priority {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@2), locf(@4), "no origin and destination step(s) defined in transition declaration."); yynerrs++;} -| TRANSITION transition_name transition_priority {cmd_goto_body_state();} transition_condition END_TRANSITION - {$$ = NULL; print_err_msg(locl(@3), locf(@5), "no origin and destination step(s) defined in transition declaration."); yynerrs++;} -/*| TRANSITION transition_priority FROM steps TO steps {cmd_goto_body_state();} transition_condition error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@6), "unclosed transition declaration."); yyerrok;} -| TRANSITION transition_name transition_priority FROM steps TO steps {cmd_goto_body_state();} transition_condition error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@7), "unclosed transition declaration."); yyerrok;}*/ -| TRANSITION error END_TRANSITION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in transition declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -transition_priority: - /* empty */ - {$$ = NULL;} -| '(' {cmd_goto_sfc_priority_state();} PRIORITY {cmd_pop_state();} ASSIGN integer ')' - {$$ = $6;} -/* ERROR_CHECK_BEGIN -| '(' ASSIGN integer ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'PRIORITY' missing between '(' and ':=' in transition declaration with priority."); yynerrs++;} -| '(' error ASSIGN integer ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "expecting 'PRIORITY' between '(' and ':=' in transition declaration with priority."); yyerrok;} - ERROR_CHECK_END */ -; - - -transition_condition: - ':' eol_list simple_instr_list - {$$ = new transition_condition_c($3, NULL, locloc(@$));} -| ASSIGN expression ';' - {$$ = new transition_condition_c(NULL, $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| eol_list simple_instr_list - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing before IL condition in transition declaration."); yynerrs++;} -| ':' eol_list error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no instructions defined in IL condition of transition declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid instructions in IL condition of transition declaration."); yyclearin;} - yyerrok; - } -| ASSIGN ';' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no expression defined in ST condition of transition declaration."); yynerrs++;} -| ASSIGN error ';' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid expression defined in ST condition of transition declaration."); yyerrok;} -| ASSIGN expression error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "expecting ';' after expression defined in ST condition of transition declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -action: -// ACTION identifier ':' ... - ACTION action_name {cmd_goto_body_state();} action_body END_ACTION - {$$ = new action_c($2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| ACTION {cmd_goto_body_state();} action_body END_ACTION - {$$ = NULL; print_err_msg(locl(@1), locf(@3), "no action name defined in action declaration."); yynerrs++;} -| ACTION error {cmd_goto_body_state();} action_body END_ACTION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid action name defined in action declaration."); yyerrok;} -| ACTION action_name {cmd_goto_body_state();} function_block_body END_ACTION - {$$ = NULL; print_err_msg(locl(@2), locf(@4), "':' missing after action name in action declaration."); yynerrs++;} -/*| ACTION action_name {cmd_goto_body_state();} action_body END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed action declaration."); yyerrok;}*/ -| ACTION error END_ACTION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in action declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -action_body: - ':' function_block_body - {$$ = $2;} -/* ERROR_CHECK_BEGIN */ -| ':' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no body defined in action declaration.");} - else {print_err_msg(locf(@2), locl(@2), "invalid body defined in action declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -/********************************/ -/* B 1.7 Configuration elements */ -/********************************/ -/* NOTE: - * It is not clear from reading the specification to which namespace - * the names of resources, tasks and programs belong to. - * - * The following syntax assumes that resource and program names belong to the - * same namespace as the variables defined within - * the resource/configuration (i.e. VAR_GLOBAL). - * Task names belong to a namespace all of their own, since they don't - * produce conflicts in the syntax parser, so we might just as well - * leave them be! ;-) - * The above decision was made taking into - * account that inside a VAR_CONFIG declaration global variables - * may be referenced starting off from the resource name as: - * resource_name.program_name.variable_name - * Notice how resource names and program names are used in a very similar - * manner as are variable names. - * Using a single namespace for all the above mentioned names - * also makes it easier to write the syntax parser!! ;-) Using a private - * namespace for each of the name types (resource names, program names, - * global varaiable names), i.e. letting the names be re-used across - * each of the groups (resource, program, global variables), produces - * reduce/reduce conflicts in the syntax parser. Actually, it is only - * the resource names that need to be distinguished into a - * prev_declared_resource_name so as not to conflict with [gloabl] variable - * names in the 'data' construct. - * The program names are only tracked to make sure that two programs do not - * get the same name. - * - * Using a single namespace does have the drawback that the user will - * not be able to re-use names for resources or programs if these - * have already been used to name a variable! - * - * If it ever becomes necessary to change this interpretation of - * the syntax, then this section of the syntax parser must be updated! - */ -prev_declared_global_var_name: prev_declared_global_var_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_resource_name: prev_declared_resource_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_program_name: prev_declared_program_name_token {$$ = new identifier_c($1, locloc(@$));}; -// prev_declared_task_name: prev_declared_task_name_token {$$ = new identifier_c($1, locloc(@$));}; - - - - - - -configuration_name: identifier; - -/* NOTE: The specification states that valid resource type names - * are implementation defined, i.e. each implementaion will define - * what resource types it supports. - * We are implementing this syntax parser to be used by any - * implementation, so at the moment we accept any identifier - * as a resource type name. - * This implementation should probably be changed in the future. We - * should probably have a resource_type_name_token, and let the - * implementation load the global symbol library with the - * accepted resource type names before parsing the code. - * - */ -resource_type_name: any_identifier; - -configuration_declaration: - CONFIGURATION configuration_name - optional_global_var_declarations - single_resource_declaration - {variable_name_symtable.pop(); - direct_variable_symtable.pop();} - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = new configuration_declaration_c($2, $3, $4, $6, $7, locloc(@$)); - library_element_symtable.insert($2, prev_declared_configuration_name_token); - variable_name_symtable.pop(); - direct_variable_symtable.pop(); - } -| CONFIGURATION configuration_name - optional_global_var_declarations - resource_declaration_list - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = new configuration_declaration_c($2, $3, $4, $5, $6, locloc(@$)); - library_element_symtable.insert($2, prev_declared_configuration_name_token); - variable_name_symtable.pop(); - direct_variable_symtable.pop(); -} -/* ERROR_CHECK_BEGIN */ -| CONFIGURATION - optional_global_var_declarations - single_resource_declaration - {variable_name_symtable.pop(); - direct_variable_symtable.pop();} - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no configuration name defined in configuration declaration."); yynerrs++;} -| CONFIGURATION - optional_global_var_declarations - resource_declaration_list - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no configuration name defined in configuration declaration."); yynerrs++;} -| CONFIGURATION error - optional_global_var_declarations - single_resource_declaration - {variable_name_symtable.pop(); - direct_variable_symtable.pop();} - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid configuration name defined in configuration declaration."); yyerrok;} -| CONFIGURATION error - optional_global_var_declarations - resource_declaration_list - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid configuration name defined in configuration declaration."); yyerrok;} -| CONFIGURATION configuration_name - optional_global_var_declarations - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no resource(s) defined in configuration declaration."); yynerrs++;} -| CONFIGURATION configuration_name - optional_global_var_declarations - error - optional_access_declarations - optional_instance_specific_initializations - END_CONFIGURATION - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid resource(s) defined in configuration declaration."); yyerrok;} -/*| CONFIGURATION configuration_name - optional_global_var_declarations - single_resource_declaration - {variable_name_symtable.pop(); - direct_variable_symtable.pop();} - optional_access_declarations - optional_instance_specific_initializations - END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed configuration declaration."); yyerrok;}*/ -| CONFIGURATION configuration_name - optional_global_var_declarations - resource_declaration_list - optional_access_declarations - optional_instance_specific_initializations - END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed configuration declaration."); yyerrok;} -| CONFIGURATION error END_CONFIGURATION - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in configuration declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - -// helper symbol for -// - configuration_declaration -// - resource_declaration -// -optional_global_var_declarations: - // empty - {$$ = NULL;} -| global_var_declarations -; - - -// helper symbol for configuration_declaration // -optional_access_declarations: - // empty - {$$ = NULL;} -//| access_declarations -; - -// helper symbol for configuration_declaration // -optional_instance_specific_initializations: - // empty - {$$ = NULL;} -| instance_specific_initializations -; - -// helper symbol for configuration_declaration // -resource_declaration_list: - resource_declaration - {$$ = new resource_declaration_list_c(locloc(@$)); $$->add_element($1);} -| resource_declaration_list resource_declaration - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| resource_declaration_list error - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected token after resource declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -resource_declaration: - RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} resource_name ON resource_type_name - optional_global_var_declarations - single_resource_declaration - END_RESOURCE - {$$ = new resource_declaration_c($3, $5, $6, $7, locloc(@$)); - variable_name_symtable.pop(); - direct_variable_symtable.pop(); - variable_name_symtable.insert($3, prev_declared_resource_name_token); - } -/* ERROR_CHECK_BEGIN */ -| RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} ON resource_type_name - optional_global_var_declarations - single_resource_declaration - END_RESOURCE - {$$ = NULL; print_err_msg(locl(@1), locf(@3), "no resource name defined in resource declaration."); yynerrs++;} -/*| RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} resource_name ON resource_type_name - optional_global_var_declarations - single_resource_declaration - END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@5), "unclosed resource declaration."); yyerrok;}*/ -| RESOURCE error END_RESOURCE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in resource declaration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -single_resource_declaration: - task_configuration_list program_configuration_list - {$$ = new single_resource_declaration_c($1, $2, locloc(@$));} -; - - -// helper symbol for single_resource_declaration // -task_configuration_list: - // empty - {$$ = new task_configuration_list_c(locloc(@$));} -| task_configuration_list task_configuration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| task_configuration_list task_configuration error - {$$ = $1; print_err_msg(locl(@1), locf(@2), "';' missing at the end of task configuration in resource declaration."); yyerrok;} -| task_configuration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after task configuration in resource declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -// helper symbol for single_resource_declaration // -program_configuration_list: - program_configuration ';' - {$$ = new program_configuration_list_c(locloc(@$)); $$->add_element($1);} -| program_configuration_list program_configuration ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| program_configuration error - {$$ = new program_configuration_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at the end of program configuration in resource declaration."); yyerrok;} -| program_configuration_list program_configuration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at the end of program configuration in resource declaration."); yyerrok;} -| program_configuration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid program configuration in resource declaration."); yyerrok;} -| program_configuration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after program configuration in resource declaration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -resource_name: identifier; - -/* -access_declarations: - VAR_ACCESS access_declaration_list END_VAR - {$$ = NULL;} -// ERROR_CHECK_BEGIN // -| VAR_ACCESS END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in access variable(s) declaration."); yynerrs++;} -| VAR_ACCESS error access_declaration_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_ACCESS' in access variable(s) declaration."); yyerrok;} -| VAR_ACCESS access_declaration_list error END_VAR - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed access variable(s) declaration."); yyerrok;} -| VAR_ACCESS error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in access variable(s) declaration."); yyerrok;} -// ERROR_CHECK_END // -; - -// helper symbol for access_declarations // -access_declaration_list: - access_declaration ';' -| access_declaration_list access_declaration ';' -// ERROR_CHECK_BEGIN // -| error ';' - {$$ = // create a new list //; - print_err_msg(locf(@1), locl(@1), "invalid access variable declaration."); yyerrok;} -| access_declaration error - {$$ = // create a new list //; - print_err_msg(locl(@1), locf(@2), "';' missing at the end of access variable declaration."); yyerrok;} -| access_declaration_list access_declaration error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at the end of access variable declaration."); yyerrok;} -| access_declaration_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid access variable declaration."); yyerrok;} -| access_declaration_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after access variable declaration."); yynerrs++;} -// ERROR_CHECK_END // -; - - -access_declaration: - access_name ':' access_path ':' non_generic_type_name -| access_name ':' access_path ':' non_generic_type_name direction -; - - -access_path: - prev_declared_direct_variable -| prev_declared_resource_name '.' prev_declared_direct_variable -| any_fb_name_list symbolic_variable -| prev_declared_resource_name '.' any_fb_name_list symbolic_variable -| prev_declared_program_name '.' any_fb_name_list symbolic_variable -| prev_declared_resource_name '.' prev_declared_program_name '.' any_fb_name_list symbolic_variable -; -*/ - -// helper symbol for -// - access_path -// - instance_specific_init -// -/* NOTE: The fb_name_list refers to funtion block variables - * that have been declared in a scope outside the one we are - * currently parsing, so we must accept them to be any_identifier! - * - * Beware that other locations of this syntax parser also require - * a fb_name_list. In those locations the function blocks are being declared, - * so only currently un-used identifiers (i.e. identifier) may be accepted. - * - * In order to distinguish the two, here we use any_fb_name_list, while - * in the the locations we simply use fb_name_list! - */ -any_fb_name_list: - // empty - {$$ = new any_fb_name_list_c(locloc(@$));} -//| fb_name_list fb_name '.' -| any_fb_name_list any_identifier '.' - {$$ = $1; $$->add_element($2);} -; - - - -global_var_reference: -// [resource_name '.'] global_var_name ['.' structure_element_name] // - prev_declared_global_var_name - {$$ = new global_var_reference_c(NULL, $1, NULL, locloc(@$));} -| prev_declared_global_var_name '.' structure_element_name - {$$ = new global_var_reference_c(NULL, $1, $3, locloc(@$));} -| prev_declared_resource_name '.' prev_declared_global_var_name - {$$ = new global_var_reference_c($1, $3, NULL, locloc(@$));} -| prev_declared_resource_name '.' prev_declared_global_var_name '.' structure_element_name - {$$ = new global_var_reference_c($1, $3, $5, locloc(@$));} -; - - -//access_name: identifier; - - -program_output_reference: -/* NOTE: - * program_output_reference is merely used within data_source. - * data_source is merely used within task_initialization - * task_initialization appears in a configuration declaration - * _before_ the programs are declared, so we cannot use - * prev_declared_program_name, as what might seem correct at first. - * - * The semantic checker must later check whether the identifier - * used really refers to a program declared after the task - * initialization! - */ -// prev_declared_program_name '.' symbolic_variable - program_name '.' symbolic_variable - {$$ = new program_output_reference_c($1, $3, locloc(@$));} -; - -program_name: identifier; - -/* -direction: - READ_WRITE - {$$ = NULL;} -| READ_ONLY - {$$ = NULL;} -; -*/ - -task_configuration: - TASK task_name task_initialization - {$$ = new task_configuration_c($2, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| TASK task_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no task name defined in task declaration."); yynerrs++;} -| TASK error task_initialization - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid task name defined in task declaration."); yyerrok;} -| TASK task_name error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no task initialization defined in task declaration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid task initialization in task declaration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* NOTE: The specification does not mention the namespace to which task names - * should belong to. Unlike resource and program names, for the moment we - * let the task names belong to their own private namespace, as they do not - * produce any conflicts in the syntax parser. - * If in the future our interpretation of the spec. turns out to be incorrect, - * the definition of task_name may have to be changed! - */ -task_name: any_identifier; - - -task_initialization: -// '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' // - '(' {cmd_goto_task_init_state();} task_initialization_single task_initialization_interval task_initialization_priority ')' - {$$ = new task_initialization_c($3, $4, $5, locloc(@$));} -; - - -task_initialization_single: -// [SINGLE ASSIGN data_source ','] - /* empty */ - {$$ = NULL;} -| SINGLE ASSIGN {cmd_pop_state();} data_source ',' {cmd_goto_task_init_state();} - {$$ = $4;} -/* ERROR_CHECK_BEGIN */ -| SINGLE {cmd_pop_state();} data_source ',' {cmd_goto_task_init_state();} - {$$ = NULL; print_err_msg(locl(@1), locf(@3), "':=' missing after 'SINGLE' in task initialization."); yynerrs++;} -| SINGLE ASSIGN {cmd_pop_state();} ',' {cmd_goto_task_init_state();} - {$$ = NULL; print_err_msg(locl(@2), locf(@4), "no data source defined in 'SINGLE' statement of task initialization."); yynerrs++;} -| SINGLE ASSIGN {cmd_pop_state();} error ',' {cmd_goto_task_init_state();} - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid data source defined in 'SINGLE' statement of task initialization."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -task_initialization_interval: -// [INTERVAL ASSIGN data_source ','] - /* empty */ - {$$ = NULL;} -| INTERVAL ASSIGN {cmd_pop_state();} data_source ',' {cmd_goto_task_init_state();} - {$$ = $4;} -/* ERROR_CHECK_BEGIN */ -| INTERVAL {cmd_pop_state();} data_source ',' {cmd_goto_task_init_state();} - {$$ = NULL; print_err_msg(locl(@1), locf(@3), "':=' missing after 'INTERVAL' in task initialization.");} -| INTERVAL ASSIGN {cmd_pop_state();} ',' {cmd_goto_task_init_state();} - {$$ = NULL; print_err_msg(locl(@2), locf(@4), "no data source defined in 'INTERVAL' statement of task initialization."); yynerrs++;} -| INTERVAL ASSIGN {cmd_pop_state();} error ',' {cmd_goto_task_init_state();} - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid data source defined in 'INTERVAL' statement of task initialization."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -task_initialization_priority: -// PRIORITY ASSIGN integer - PRIORITY ASSIGN {cmd_pop_state();} integer - {$$ = $4;} -/* ERROR_CHECK_BEGIN */ -| PRIORITY {cmd_pop_state();} integer - {$$ = NULL; print_err_msg(locl(@1), locf(@3), "':=' missing after 'PRIORITY' in task initialization."); yynerrs++;} -| PRIORITY ASSIGN {cmd_pop_state();} error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@4), "no priority number defined in 'PRIORITY' statement of task initialization.");} - else {print_err_msg(locf(@4), locl(@4), "invalid priority number in 'PRIORITY' statement of task initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -data_source: - constant -| global_var_reference -| program_output_reference -| prev_declared_direct_variable -; - -program_configuration: -// PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] // - PROGRAM program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = new program_configuration_c(NULL, $2, $3, $5, $6, locloc(@$)); - variable_name_symtable.insert($2, prev_declared_program_name_token); - } -| PROGRAM RETAIN program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = new program_configuration_c(new retain_option_c(locloc(@2)), $3, $4, $6, $7, locloc(@$)); - variable_name_symtable.insert($3, prev_declared_program_name_token); - } -| PROGRAM NON_RETAIN program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = new program_configuration_c(new non_retain_option_c(locloc(@2)), $3, $4, $6, $7, locloc(@$)); - variable_name_symtable.insert($3, prev_declared_program_name_token); - } -/* ERROR_CHECK_BEGIN */ -| PROGRAM program_name optional_task_name ':' identifier optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@5), locl(@5), "invalid program type name after ':' in program configuration."); yynerrs++;} -| PROGRAM RETAIN program_name optional_task_name ':' identifier optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@6), locl(@6), "invalid program type name after ':' in program configuration."); yynerrs++;} -| PROGRAM NON_RETAIN program_name optional_task_name ':' identifier optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@6), locl(@6), "invalid program type name after ':' in program configuration."); yynerrs++;} -| PROGRAM error program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'PROGRAM' in program configuration."); yyerrok;} -| PROGRAM RETAIN error program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'RETAIN' in retentive program configuration."); yyerrok;} -| PROGRAM NON_RETAIN error program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "unexpected token after 'NON_RETAIN' in non-retentive program configuration."); yyerrok;} -| PROGRAM optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no program name defined in program configuration."); yynerrs++;} -| PROGRAM RETAIN optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no program name defined in retentive program configuration."); yynerrs++;} -| PROGRAM NON_RETAIN optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no program name defined in non-retentive program configuration."); yynerrs++;} -| PROGRAM error optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid program name defined in program configuration."); yyerrok;} -| PROGRAM RETAIN error optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid program name defined in retentive program configuration."); yyerrok;} -| PROGRAM NON_RETAIN error optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid program name defined in non-retentive program configuration."); yyerrok;} -| PROGRAM program_name optional_task_name prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "':' missing after program name or optional task name in program configuration."); yynerrs++;} -| PROGRAM RETAIN program_name optional_task_name prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "':' missing after program name or optional task name in retentive program configuration."); yynerrs++;} -| PROGRAM NON_RETAIN program_name optional_task_name prev_declared_program_type_name optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "':' missing after program name or optional task name in non-retentive program configuration."); yynerrs++;} -| PROGRAM program_name optional_task_name ':' optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "no program type defined in program configuration."); yynerrs++;} -| PROGRAM RETAIN program_name optional_task_name ':' optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@5), locf(@6), "no program type defined in retentive program configuration."); yynerrs++;} -| PROGRAM NON_RETAIN program_name optional_task_name ':' optional_prog_conf_elements - {$$ = NULL; print_err_msg(locl(@5), locf(@6), "no program type defined in non-retentive program configuration."); yynerrs++;} -/* ERROR_CHECK_END */ -; - -// helper symbol for program_configuration // -optional_task_name: - // empty // - {$$ = NULL;} -| WITH task_name - {$$ = $2;} -/* ERROR_CHECK_BEGIN */ -| WITH error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no task name defined in optional task name of program configuration.");} - else {print_err_msg(locf(@2), locl(@2), "invalid task name in optional task name of program configuration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -// helper symbol for program_configuration // -optional_prog_conf_elements: - // empty // - {$$ = NULL;} -| '(' prog_conf_elements ')' - {$$ = $2;} -/* ERROR_CHECK_BEGIN */ -| '(' error ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid program configuration elements in program configuration."); yyerrok;} -| '(' prog_conf_elements error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing at the end of program configuration elements in program configuration."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -prog_conf_elements: - prog_conf_element - {$$ = new prog_conf_elements_c(locloc(@$)); $$->add_element($1);} -| prog_conf_elements ',' prog_conf_element - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| prog_conf_elements prog_conf_element - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in program configuration elements list."); yynerrs++;} -| prog_conf_elements ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for program configuration element in program configuration list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value for program configuration element in program configuration list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -prog_conf_element: - fb_task -| prog_cnxn -; - - -fb_task: - // fb_name WITH task_name -/* NOTE: The fb_name refers to funtion block variables - * that have been declared in a scope outside the one we are - * currently parsing, so we must accept them to be any_identifier! - */ - any_identifier WITH task_name - {$$ = new fb_task_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| any_identifier WITH error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no task name defined in function block configuration.");} - else {print_err_msg(locf(@3), locl(@3), "invalid task name in function block configuration."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -/* NOTE: - * The semantics of configuring a program are rather confusing, so here is - * my (Mario) understanding on the issue... - * - * A function/program may have as its input variables a simple variable - * (BYTE, WORD, etc...), an array (ARRAY [1 .. 3] OF BYTE, ...) , or a structure. - * Nevertheless, when calling this function from within a st or il language statement - * it is not possible to allocate a value to a single element of the array or structure - * typed input variable, as the accepted syntax is simply '(' variable_name ':=' variable ')' - * Notice how the variable_name does not include things such as 'a.elem1' or 'a[1]'! - * - * Nevertheless, when configuring a program from within a configuration, - * it becomes possible to allocate values to individual elements of the - * array or structured type input variable, as the syntax is now - * '(' symbolic_variable ':=' data_sink|prog_data_source ')' - * Notice how the symbolic_variable _does_ include things such as 'a.elem1' or 'a[1]'! - * - * Conclusion: Unlike other locations in the syntax where SENDTO appears, - * here it is not valid to replace symbolic_variable with any_identifier! - * Nevertheless, it is also not correct to leave symbolic_variable as it is, - * as we have defined it to only include previously declared variables, - * which is not the case in this situation. Here symbolic_variable is refering - * to variables that were defined within the scope of the program that is being - * called, and _not_ within the scope of the configuration that is calling the - * program, so the variables in question are not declared in the current scope! - * - * We therefore need to define a new symbolic_variable, that accepts any_identifier - * instead of previosuly declared variable names, to be used in the definition of - * prog_cnxn! - */ -prog_cnxn: - any_symbolic_variable ASSIGN prog_data_source - {$$ = new prog_cnxn_assign_c($1, $3, locloc(@$));} -| any_symbolic_variable SENDTO data_sink - {$$ = new prog_cnxn_sendto_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| any_symbolic_variable constant - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing between parameter and value in program configuration element."); yynerrs++;} -| any_symbolic_variable enumerated_value - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing between parameter and value in program configuration element."); yynerrs++;} -| any_symbolic_variable data_sink - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' or '=>' missing between parameter and variable in program configuration element."); yynerrs++;} -| any_symbolic_variable ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value or variable defined in program configuration assignment element.");} - else {print_err_msg(locf(@3), locl(@3), "invalid value or variable in program configuration assignment element."); yyclearin;} - yyerrok; - } -| any_symbolic_variable SENDTO error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no variable defined in program configuration sendto element.");} - else {print_err_msg(locf(@3), locl(@3), "invalid variable in program configuration sendto element."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -prog_data_source: - constant -| enumerated_value -| global_var_reference -| prev_declared_direct_variable -; - -data_sink: - global_var_reference -| prev_declared_direct_variable -; - -instance_specific_initializations: - VAR_CONFIG instance_specific_init_list END_VAR - {$$ = new instance_specific_initializations_c($2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| VAR_CONFIG END_VAR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no variable declared in configuration variable(s) initialization."); yynerrs++;} -| VAR_CONFIG error instance_specific_init_list END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unexpected token after 'VAR_CONFIG' in configuration variable(s) initialization."); yyerrok;} -| VAR_CONFIG instance_specific_init_list error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed configuration variable(s) initialization."); yyerrok;} -| VAR_CONFIG error END_VAR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in configuration variable(s) initialization."); yyerrok;} -/* ERROR_CHECK_END */ -; - -// helper symbol for instance_specific_initializations // -instance_specific_init_list: - instance_specific_init ';' - {$$ = new instance_specific_init_list_c(locloc(@$)); $$->add_element($1);} -| instance_specific_init_list instance_specific_init ';' - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| error ';' - {$$ = new instance_specific_init_list_c(locloc(@$)); print_err_msg(locf(@1), locl(@1), "invalid configuration variable initialization."); yyerrok;} -| instance_specific_init error - {$$ = new instance_specific_init_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at the end of configuration variable initialization."); yyerrok;} -| instance_specific_init_list instance_specific_init error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at the end of configuration variable initialization."); yyerrok;} -| instance_specific_init_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid configuration variable initialization."); yyerrok;} -| instance_specific_init_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after configuration variable initialization."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -instance_specific_init: -// -// resource_name '.' program_name '.' {fb_name '.'} -// ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' function_block_type_name ':=' structure_initialization)) -// -// prev_declared_resource_name '.' prev_declared_program_name '.' any_fb_name_list variable_name ':' located_var_spec_init -/* NOTE: variable_name has been changed to any_identifier (and not simply identifier) because the - * variables being referenced have been declared outside the scope currently being parsed! - */ -/* NOTE: program_name has not been changed to prev_declared_program_name because the - * programs being referenced have been declared outside the scope currently being parsed! - * The programs are only kept inside the scope of the resource in which they are defined. - */ - prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier ':' located_var_spec_init - {$$ = new instance_specific_init_c($1, $3, $5, $6, NULL, $8, locloc(@$));} -| prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier location ':' located_var_spec_init - {$$ = new instance_specific_init_c($1, $3, $5, $6, $7, $9, locloc(@$));} -| prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier ':' fb_initialization - {$5->add_element($6); $$ = new instance_specific_init_c($1, $3, $5, NULL, NULL, $8, locloc(@$));} -; - - -/* helper symbol for instance_specific_init */ -fb_initialization: - function_block_type_name ASSIGN structure_initialization - {$$ = new fb_initialization_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| function_block_type_name structure_initialization - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':=' missing between function block name and initialization in function block initialization."); yynerrs++;} -| function_block_type_name ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no initial value defined in function block initialization.");} - else {print_err_msg(locf(@3), locl(@3), "invalid initial value in function block initialization."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/***********************************/ -/* B 2.1 Instructions and Operands */ -/***********************************/ -/* helper symbol for many IL instructions, etc... */ -/* eat up any extra EOL tokens... */ - -eol_list: - EOL -| eol_list EOL -; - - - -instruction_list: - il_instruction - {$$ = new instruction_list_c(locloc(@$)); $$->add_element($1);} -| any_pragma eol_list - {$$ = new instruction_list_c(locloc(@$)); $$->add_element($1);} -| instruction_list il_instruction - {$$ = $1; $$->add_element($2);} -| instruction_list any_pragma - {$$ = $1; $$->add_element($2);} -; - - - -il_instruction: - il_incomplete_instruction eol_list - {$$ = new il_instruction_c(NULL, $1, locloc(@$));} -| label ':' il_incomplete_instruction eol_list - {$$ = new il_instruction_c($1, $3, locloc(@$));} -| label ':' eol_list - {$$ = new il_instruction_c($1, NULL, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| error eol_list - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid IL instruction."); yyerrok;} -| il_incomplete_instruction error - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "EOL missing at the end of IL instruction."); yyerrok;} -| error ':' il_incomplete_instruction eol_list - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid label in IL instruction."); yyerrok;} -| label il_incomplete_instruction eol_list - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing after label in IL instruction."); yynerrs++;} -| label ':' error eol_list - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid IL instruction."); yyerrok;} -| label ':' il_incomplete_instruction error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "EOL missing at the end of IL instruction."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for il_instruction */ -il_incomplete_instruction: - il_simple_operation -| il_expression -| il_jump_operation -| il_fb_call -| il_formal_funct_call -| il_return_operator -; - - -label: identifier; - - - -il_simple_operation: -// (il_simple_operator [il_operand]) | (function_name [il_operand_list]) - il_simple_operator - {$$ = new il_simple_operation_c($1, NULL, locloc(@$));} -/* - * Note: Bison is getting confused with the following rule, - * i.e. it is finding conflicts where there seemingly are really none. - * The rule was therefore replaced by the equivalent following - * two rules. - */ -/* -| il_simple_operator il_operand - {$$ = new il_simple_operation_c($1, $2, locloc(@$));} -*/ -| il_simple_operator_noclash il_operand - {$$ = new il_simple_operation_c($1, $2, locloc(@$));} -| il_simple_operator_clash il_operand - {$$ = new il_simple_operation_c($1, $2, locloc(@$));} -/* NOTE: the line - * | il_simple_operator - * already contains the 'NOT' operator, as well as all the - * expression operators ('MOD', 'AND', etc...), all of which - * may also be a function name! This means that these operators/functions, - * without any operands, could be reduced to either an operator or a - * function call. - * - * I (Mario) have chosen to reduce it to an operator. - * In order to do this, we must remove from the syntax that defines - * function calls all the functions whose names clash with the IL operators. - * - * The line - * | function_name - * has been replaced with the lines - * | function_name_no_clashes - * in order to include all possible function names except - * those whose names coincide with operators !! - */ -| function_name_no_clashes - {$$ = new il_function_call_c($1, NULL, locloc(@$));} -/* NOTE: the line - * | il_simple_operator il_operand - * already contains the 'NOT', 'MOD', etc. operators, followed by a single il_operand. - * However, this same code (MOD x) may also be reduced to a function call to the MOD - * function. This means that (MOD, AND,...) could be interpret as a function name - * or as an IL operator! This would lead us to a reduce/reduce conflict! - * - * I (Mario) have chosen to reduce it to an operand, rather than a function call. - * In order to do this, we must remove from the syntax that defines - * function calls all the functions whose names clash with the IL operators. - * - * The line - * | function_name il_operand_list - * has been replaced with the line - * | function_name_no_clashes il_operand_list - * in order to include all possible function names except - * for the function names which clash with expression and simple operators. - * - * Note that: - * this alternative syntax does not cover the possibility of - * the function 'NOT', 'MOD', etc... being called with more than one il_operand, - * in which case it is always a function call, and not an IL instruction. - * We therefore need to include an extra rule where the - * function_name_expression_clashes and function_name_simpleop_clashes - * are followed by a il_operand_list with __two__ or more il_operands!! - */ -| function_name_no_clashes il_operand_list - {$$ = new il_function_call_c($1, $2, locloc(@$));} -| il_simple_operator_clash il_operand_list2 - {$$ = new il_function_call_c(il_operator_c_2_identifier_c($1), $2, locloc(@$));} -; - - - -il_expression: -// il_expr_operator '(' [il_operand] EOL {EOL} [simple_instr_list] ')' -/* - * Note: Bison is getting confused with the use of il_expr_operator, - * i.e. it is finding conflicts where there seemingly are really none. - * il_expr_operator was therefore replaced by the equivalent - * il_expr_operator_noclash | il_expr_operator_clash. - */ - il_expr_operator_noclash '(' eol_list ')' - {$$ = new il_expression_c($1, NULL, NULL, locloc(@$));} -| il_expr_operator_noclash '(' il_operand eol_list ')' - {$$ = new il_expression_c($1, $3, NULL, locloc(@$));} -| il_expr_operator_noclash '(' eol_list simple_instr_list ')' - {$$ = new il_expression_c($1, NULL, $4, locloc(@$));} -| il_expr_operator_noclash '(' il_operand eol_list simple_instr_list ')' - {$$ = new il_expression_c($1, $3, $5, locloc(@$));} -| il_expr_operator_clash '(' eol_list ')' - {$$ = new il_expression_c($1, NULL, NULL, locloc(@$));} -| il_expr_operator_clash '(' il_operand eol_list ')' - {$$ = new il_expression_c($1, $3, NULL, locloc(@$));} -| il_expr_operator_clash '(' il_operand eol_list simple_instr_list ')' - {$$ = new il_expression_c($1, $3, $5, locloc(@$));} -| il_expr_operator_clash_eol_list simple_instr_list ')' - {$$ = new il_expression_c($1, NULL, $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| il_expr_operator_noclash '(' eol_list error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing at the end of IL expression."); yyerrok;} -| il_expr_operator_noclash '(' il_operand eol_list error - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "')' missing at the end of IL expression."); yyerrok;} -| il_expr_operator_noclash '(' eol_list simple_instr_list error - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "')' missing at the end of IL expression."); yyerrok;} -| il_expr_operator_noclash '(' il_operand eol_list simple_instr_list error - {$$ = NULL; print_err_msg(locl(@5), locf(@6), "')' missing at the end of IL expression."); yyerrok;} -| il_expr_operator_clash '(' il_operand eol_list error - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "')' missing at the end of IL expression."); yyerrok;} -| il_expr_operator_clash '(' il_operand eol_list simple_instr_list error - {$$ = NULL; print_err_msg(locl(@5), locf(@6), "')' missing at the end of IL expression."); yyerrok;} -| il_expr_operator_clash_eol_list simple_instr_list error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing at the end of IL expression."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_jump_operation: - il_jump_operator label - {$$ = new il_jump_operation_c($1, $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| il_jump_operator error - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid label defined in IL jump operation."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_fb_call: -// il_call_operator fb_name ['(' (EOL {EOL} [il_param_list]) | [il_operand_list] ')'] - il_call_operator prev_declared_fb_name - {$$ = new il_fb_call_c($1, $2, NULL, NULL, locloc(@$));} -| il_call_operator prev_declared_fb_name '(' ')' - {$$ = new il_fb_call_c($1, $2, NULL, NULL, locloc(@$));} -| il_call_operator prev_declared_fb_name '(' eol_list ')' - {$$ = new il_fb_call_c($1, $2, NULL, NULL, locloc(@$));} -| il_call_operator prev_declared_fb_name '(' il_operand_list ')' - {$$ = new il_fb_call_c($1, $2, $4, NULL, locloc(@$));} -| il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' - {$$ = new il_fb_call_c($1, $2, NULL, $5, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| il_call_operator error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no function block name defined in IL function block call.");} - else {print_err_msg(locf(@2), locl(@2), "invalid function block name in IL function block call."); yyclearin;} - yyerrok; - } -| il_call_operator '(' ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block name defined in IL function block call."); yynerrs++;} -| il_call_operator '(' eol_list ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block name defined in IL function block call."); yynerrs++;} -| il_call_operator '(' il_operand_list ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block name defined in IL function block call."); yynerrs++;} -| il_call_operator '(' eol_list il_param_list ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block name defined in IL function block call."); yynerrs++;} -| il_call_operator error '(' ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid function block name defined in IL function block call."); yyerrok;} -| il_call_operator error '(' eol_list ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid function block name defined in IL function block call."); yyerrok;} -| il_call_operator error '(' il_operand_list ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid function block name defined in IL function block call."); yyerrok;} -| il_call_operator error '(' eol_list il_param_list ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid function block name defined in IL function block call."); yyerrok;} -| il_call_operator prev_declared_fb_name ')' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'(' missing after function block name defined in IL function block call."); yynerrs++;} -| il_call_operator prev_declared_fb_name il_operand_list ')' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "'(' missing after function block name defined in IL function block call."); yynerrs++;} -| il_call_operator prev_declared_fb_name '(' error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing at the end of IL function block call."); yyerrok;} -| il_call_operator prev_declared_fb_name '(' eol_list error - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "')' missing at the end of IL function block call."); yyerrok;} -| il_call_operator prev_declared_fb_name '(' il_operand_list error - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "')' missing at the end of IL function block call."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: Please read note above the definition of function_name_without_clashes */ -il_formal_funct_call: -// function_name '(' EOL {EOL} [il_param_list] ')' -/* function_name '(' eol_list ')' */ -/* NOTE: il_formal_funct_call is only used in the definition of - * - il_incomplete_instruction - * - il_simple_instruction - * In both of the above, il_expression also - * shows up as another option. This means that the functions whose - * names clash with expressions, followed by '(' eol_list ')', are - * already included. We must therefore leave them out in this - * definition in order to remove reduce/reduce conflicts. - * - * In summary: 'MOD' '(' eol_list ')', and all other functions whose - * names clash with expressions may be interpreted by the syntax by - * two different routes. I (Mario) chose to interpret them - * as operators, rather than as function calls! - * (AND MOD OR XOR ADD DIV EQ GT GE LT LE MUL NE SUB) - */ - function_name_no_clashes '(' eol_list ')' - {$$ = new il_formal_funct_call_c($1, NULL, locloc(@$));} -| function_name_simpleop_clashes '(' eol_list ')' - {$$ = new il_formal_funct_call_c($1, NULL, locloc(@$));} -/* | function_name '(' eol_list il_param_list ')' */ -/* For the above syntax, we no longer have two ways of interpreting the - * same syntax. The above is always a function call! - * However, some of the functions that we may be calling - * may have the same name as an IL operator. This means that - * flex will be parsing them and handing them over to bison as - * IL operator tokens, and not as function name tokens. - * (when parsing ST, flex no longer recognizes IL operators, - * so will always return the correct function name, unless that - * name also coincides with an operator used in ST -> XOR, OR, MOD, AND, NOT) - * - * We must therefore interpret the IL operators as function names! - */ -| function_name_no_clashes '(' eol_list il_param_list ')' - {$$ = new il_formal_funct_call_c($1, $4, locloc(@$));} -| function_name_simpleop_clashes '(' eol_list il_param_list ')' - {$$ = new il_formal_funct_call_c($1, $4, locloc(@$));} -/* The following line should read: - * - * | function_name_expression_clashes '(' eol_list il_param_list ')' - * - * but the function_name_expression_clashes had to be first reduced to - * an intermediary symbol in order to remove a reduce/reduce conflict. - * In essence, the syntax requires more than one look ahead token - * in order to be parsed. We resolve this by reducing a collection of - * symbols into a temporary symbol (il_expr_operator_clash_eol_list), that - * will later be replaced by the correct symbol. The correct symbol will - * now be determined by a single look ahead token, as all the common - * symbols have been reduced to the temporary symbol - * il_expr_operator_clash_eol_list ! - * - * Unfortunately, this work around results in the wrong symbol - * being created for the abstract syntax tree. - * We need to figure out which symbol was created, destroy it, - * and create the correct symbol for our case. - * This is a lot of work, so I put it in a function - * at the end of this file... il_operator_c_2_identifier_c() - */ -| il_expr_operator_clash_eol_list il_param_list ')' - {$$ = new il_formal_funct_call_c(il_operator_c_2_identifier_c($1), $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| function_name_no_clashes '(' eol_list error ')' - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid parameter list defined in IL formal function call."); yyerrok;} -| function_name_simpleop_clashes '(' eol_list error ')' - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid parameter list defined in IL formal function call."); yyerrok;} -| il_expr_operator_clash_eol_list error ')' - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid parameter list defined in IL formal function call."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_expr_operator_clash_eol_list: - il_expr_operator_clash '(' eol_list - {$$ = $1;} -/* ERROR_CHECK_BEGIN */ -| il_expr_operator_clash '(' error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "EOL missing after '(' in IL instruction."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_operand: - variable -| enumerated_value -| constant -; - - -il_operand_list: - il_operand - {$$ = new il_operand_list_c(locloc(@$)); $$->add_element($1);} -| il_operand_list2 -; - - -/* List with 2 or more il_operands */ -il_operand_list2: - il_operand ',' il_operand - {$$ = new il_operand_list_c(locloc(@$)); $$->add_element($1); $$->add_element($3);} -| il_operand_list2 ',' il_operand - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| il_operand_list2 il_operand - {$$ = $1; print_err_msg(locl(@1), locf(@2), "',' missing in IL operand list."); yynerrs++;} -| il_operand ',' error - {$$ = new il_operand_list_c(locloc(@$)); - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no operand defined in IL operand list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid operand name in IL operand list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -simple_instr_list: - il_simple_instruction - {$$ = new simple_instr_list_c(locloc(@$)); $$->add_element($1);} -| simple_instr_list il_simple_instruction - {$$ = $1; $$->add_element($2);} -; - - -il_simple_instruction: - il_simple_operation eol_list -| il_expression eol_list -| il_formal_funct_call eol_list -/* ERROR_CHECK_BEGIN */ -| il_expression error - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "EOL missing after expression IL instruction."); yyerrok;} -| il_formal_funct_call error - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "EOL missing after formal function call IL instruction."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* NOTE: the correct definition of il_param_list is - * il_param_list ::= {il_param_instruction} il_param_last_instruction - * - * where {...} denotes zero or many il_param_instruction's. - * - * We could do this by defining the following: - * il_param_list: il_param_instruction_list il_param_last_instruction; - * il_param_instruction_list : ** empty ** | il_param_instruction_list il_param_instruction; - * - * Unfortunately, the above leads to reduce/reduce conflicts. - * The chosen alternative (as follows) does not have any conflicts! - * il_param_list: il_param_last_instruction | il_param_instruction_list il_param_last_instruction; - * il_param_instruction_list : il_param_instruction_list | il_param_instruction_list il_param_instruction; - */ -il_param_list: - il_param_instruction_list il_param_last_instruction - {$$ = $1; $$->add_element($2);} -| il_param_last_instruction - {$$ = new il_param_list_c(locloc(@$)); $$->add_element($1);} -/* ERROR_CHECK_BEGIN */ -| il_param_instruction_list error - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid parameter assignment in parameter assignment list."); yyerrok;} -| il_param_last_instruction il_param_last_instruction - {$$ = new il_param_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "',' missing at the end of parameter assignment in parameter assignment list."); yynerrs++;} -| il_param_instruction_list il_param_last_instruction il_param_last_instruction - {$$ = $1; print_err_msg(locl(@2), locf(@3), "',' missing at the end of parameter assignment in parameter assignment list."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -/* Helper symbol for il_param_list */ -il_param_instruction_list: - il_param_instruction - {$$ = new il_param_list_c(locloc(@$)); $$->add_element($1);} -| il_param_instruction_list il_param_instruction - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| il_param_last_instruction il_param_instruction - {$$ = new il_param_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "',' missing at the end of parameter assignment in parameter assignment list."); yynerrs++;} -| il_param_instruction_list il_param_last_instruction il_param_instruction - {$$ = $1; print_err_msg(locl(@2), locf(@3), "',' missing at the end of parameter assignment in parameter assignment list."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -il_param_instruction: - il_param_assignment ',' eol_list -| il_param_out_assignment ',' eol_list -/* ERROR_CHECK_BEGIN */ -| il_param_assignment ',' error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "EOL missing at the end of parameter assignment in parameter assignment list."); yyerrok;} -| il_param_out_assignment ',' error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "EOL missing at the end of parameter out assignment in parameter assignment list."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_param_last_instruction: - il_param_assignment eol_list -| il_param_out_assignment eol_list -/* ERROR_CHECK_BEGIN */ -| il_param_assignment error - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "EOL missing at the end of last parameter assignment in parameter assignment list."); yyerrok;} -| il_param_out_assignment error - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "EOL missing at the end of last parameter out assignment in parameter assignment list."); yyerrok;} -/* ERROR_CHECK_END */ - -; - - -il_param_assignment: - il_assign_operator il_operand - {$$ = new il_param_assignment_c($1, $2, NULL, locloc(@$));} -| il_assign_operator '(' eol_list simple_instr_list ')' - {$$ = new il_param_assignment_c($1, NULL, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| error il_operand - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid operator in parameter assignment."); yyerrok;} -| error '(' eol_list simple_instr_list ')' - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid operator in parameter assignment."); yyerrok;} -| il_assign_operator error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no operand defined in parameter assignment.");} - else {print_err_msg(locf(@2), locl(@2), "invalid operand in parameter assignment."); yyclearin;} - yyerrok; - } -| il_assign_operator '(' eol_list ')' - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no instruction list defined in parameter assignment."); yynerrs++;} -| il_assign_operator '(' eol_list error ')' - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid instruction list defined in parameter assignment."); yyerrok;} -| il_assign_operator '(' eol_list simple_instr_list error - {$$ = NULL; print_err_msg(locl(@4), locf(@5), "')' missing at the end of instruction list defined in parameter assignment."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_param_out_assignment: - il_assign_out_operator variable - {$$ = new il_param_out_assignment_c($1, $2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| il_assign_out_operator error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no variable defined in IL operand list.");} - else {print_err_msg(locf(@2), locl(@2), "invalid variable in IL operand list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - -/*******************/ -/* B 2.2 Operators */ -/*******************/ -sendto_identifier: sendto_identifier_token {$$ = new identifier_c($1, locloc(@$));}; - - -/* NOTE: - * The spec includes the operator 'EQ ' - * Note that EQ is followed by a space. - * I am considering this a typo, and defining the operator - * as 'EQ' - * (Mario) - */ -LD_operator: LD {$$ = new LD_operator_c(locloc(@$));}; -LDN_operator: LDN {$$ = new LDN_operator_c(locloc(@$));}; -ST_operator: ST {$$ = new ST_operator_c(locloc(@$));}; -STN_operator: STN {$$ = new STN_operator_c(locloc(@$));}; -NOT_operator: NOT {$$ = new NOT_operator_c(locloc(@$));}; -S_operator: S {$$ = new S_operator_c(locloc(@$));}; -R_operator: R {$$ = new R_operator_c(locloc(@$));}; -S1_operator: S1 {$$ = new S1_operator_c(locloc(@$));}; -R1_operator: R1 {$$ = new R1_operator_c(locloc(@$));}; -CLK_operator: CLK {$$ = new CLK_operator_c(locloc(@$));}; -CU_operator: CU {$$ = new CU_operator_c(locloc(@$));}; -CD_operator: CD {$$ = new CD_operator_c(locloc(@$));}; -PV_operator: PV {$$ = new PV_operator_c(locloc(@$));}; -IN_operator: IN {$$ = new IN_operator_c(locloc(@$));}; -PT_operator: PT {$$ = new PT_operator_c(locloc(@$));}; -AND_operator: AND {$$ = new AND_operator_c(locloc(@$));}; -AND2_operator: AND2 {$$ = new AND_operator_c(locloc(@$));}; /* '&' in the source code! */ -OR_operator: OR {$$ = new OR_operator_c(locloc(@$));}; -XOR_operator: XOR {$$ = new XOR_operator_c(locloc(@$));}; -ANDN_operator: ANDN {$$ = new ANDN_operator_c(locloc(@$));}; -ANDN2_operator: ANDN2 {$$ = new ANDN_operator_c(locloc(@$));}; /* '&N' in the source code! */ -ORN_operator: ORN {$$ = new ORN_operator_c(locloc(@$));}; -XORN_operator: XORN {$$ = new XORN_operator_c(locloc(@$));}; -ADD_operator: ADD {$$ = new ADD_operator_c(locloc(@$));}; -SUB_operator: SUB {$$ = new SUB_operator_c(locloc(@$));}; -MUL_operator: MUL {$$ = new MUL_operator_c(locloc(@$));}; -DIV_operator: DIV {$$ = new DIV_operator_c(locloc(@$));}; -MOD_operator: MOD {$$ = new MOD_operator_c(locloc(@$));}; -GT_operator: GT {$$ = new GT_operator_c(locloc(@$));}; -GE_operator: GE {$$ = new GE_operator_c(locloc(@$));}; -EQ_operator: EQ {$$ = new EQ_operator_c(locloc(@$));}; -LT_operator: LT {$$ = new LT_operator_c(locloc(@$));}; -LE_operator: LE {$$ = new LE_operator_c(locloc(@$));}; -NE_operator: NE {$$ = new NE_operator_c(locloc(@$));}; -CAL_operator: CAL {$$ = new CAL_operator_c(locloc(@$));}; -CALC_operator: CALC {$$ = new CALC_operator_c(locloc(@$));}; -CALCN_operator: CALCN {$$ = new CALCN_operator_c(locloc(@$));}; -RET_operator: RET {$$ = new RET_operator_c(locloc(@$));}; -RETC_operator: RETC {$$ = new RETC_operator_c(locloc(@$));}; -RETCN_operator: RETCN {$$ = new RETCN_operator_c(locloc(@$));}; -JMP_operator: JMP {$$ = new JMP_operator_c(locloc(@$));}; -JMPC_operator: JMPC {$$ = new JMPC_operator_c(locloc(@$));}; -JMPCN_operator: JMPCN {$$ = new JMPCN_operator_c(locloc(@$));}; - - -il_simple_operator: - il_simple_operator_clash -| il_simple_operator_noclash -; - - -il_simple_operator_noclash: - LD_operator -| LDN_operator -| ST_operator -| STN_operator -| S_operator -| R_operator -| S1_operator -| R1_operator -| CLK_operator -| CU_operator -| CD_operator -| PV_operator -| IN_operator -| PT_operator -| il_expr_operator_noclash -; - - -il_simple_operator_clash: - il_simple_operator_clash1 -| il_simple_operator_clash2 -; - -il_simple_operator_clash1: - NOT_operator -; - -il_simple_operator_clash2: - il_expr_operator_clash -; - - -/* -il_expr_operator: - il_expr_operator_noclash -| il_expr_operator_clash -; -*/ - -il_expr_operator_clash: - AND_operator -| OR_operator -| XOR_operator -| ADD_operator -| SUB_operator -| MUL_operator -| DIV_operator -| MOD_operator -| GT_operator -| GE_operator -| EQ_operator -| LT_operator -| LE_operator -| NE_operator -; - - -il_expr_operator_noclash: - ANDN_operator -| ANDN2_operator /* string '&N' in source code! */ -| AND2_operator /* string '&' in source code! */ -| ORN_operator -| XORN_operator -; - - - - -il_assign_operator: -/* variable_name ASSIGN */ - any_identifier ASSIGN - {$$ = new il_assign_operator_c($1, locloc(@$));} -| en_identifier ASSIGN - {$$ = new il_assign_operator_c($1, locloc(@$));} -| S1_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| R1_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| CLK_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| CU_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| CD_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| PV_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| IN_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -| PT_operator ASSIGN - {$$ = new il_assign_operator_c(il_operator_c_2_identifier_c($1), locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| error ASSIGN - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid parameter defined in parameter assignment."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_assign_out_operator: -/* variable_name SENDTO */ -/* any_identifier SENDTO */ - sendto_identifier SENDTO - {$$ = new il_assign_out_operator_c(NULL, $1, locloc(@$));} -/* The following is not required, as the sendto_identifier_token returned by flex will - * also include the 'ENO' identifier. - * The resulting abstract syntax tree is identical with or without this following rule, - * as both the eno_identifier and the sendto_identifier are stored as - * an identifier_c !! - * - * To understand why we must even explicitly consider the use of ENO here, - * please read the comment above the definition of 'variable' in section B1.4 for details. - */ -/* -| eno_identifier SENDTO - {$$ = new il_assign_out_operator_c(NULL, $1, locloc(@$));} -*/ -/*| NOT variable_name SENDTO */ -| NOT sendto_identifier SENDTO - {$$ = new il_assign_out_operator_c(new not_paramassign_c(locloc(@1)), $2, locloc(@$));} -/* The following is not required, as the sendto_identifier_token returned by flex will - * also include the 'ENO' identifier. - * The resulting abstract syntax tree is identical with or without this following rule, - * as both the eno_identifier and the sendto_identifier are stored as - * an identifier_c !! - * - * To understand why we must even explicitly consider the use of ENO here, - * please read the comment above the definition of 'variable' in section B1.4 for details. - * - * NOTE: Removing the following rule also removes a shift/reduce conflict from the parser. - * This conflict is not really an error/ambiguity in the syntax, but rather - * due to the fact that more than a single look-ahead token would be required - * to correctly parse the syntax, something that bison does not support. - * - * The shift/reduce conflict arises because bison does not know whether - * to parse the 'NOT ENO' in the following code - * LD 1 - * funct_name ( - * NOT ENO => bool_var, - * EN := TRUE - * ) - * as either a il_param_assignment (wrong!) or an il_param_out_assignment.(correct). - * The '=>' delimiter (known as SEND_TO in this iec.y file) is a dead giveaway that - * it should be parsed as an il_param_out_assignment, but still, bison gets confused! - * Bison considers the possibility of reducing the 'NOT ENO' as an NOT_operator with - * the 'ENO' operand - * (NOT_operator -> il_simple_operator -> il_simple_operation -> il_simple_instruction -> - * -> simple_instr_list -> il_param_assignment) - * instead of reducing it to an il_param_out_operator. - * ( il_param_out_operator -> il_param_out_assignment) - * - * Note that the shift/reduce conflict only manifests itself in the il_formal_funct_call, - * where both the il_param_out_assignment and il_param_assignment are used! - * - * il_param_out_assignment --+--> il_param_instruction -> il_param_instruction_list --+ - * | | - * il_param_assignment --+ | - * | - * il_formal_funct_call <- il_param_list <-+ - * - */ -/* -| NOT eno_identifier SENDTO - {$$ = new il_assign_out_operator_c(new not_paramassign_c(locloc(@1)), $2, locloc(@$));} -*/ -/* ERROR_CHECK_BEGIN */ -| error SENDTO - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid parameter defined in parameter out assignment."); yyerrok;} -| NOT SENDTO - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no parameter defined in parameter out assignment."); yynerrs++;} -| NOT error SENDTO - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid parameter defined in parameter out assignment."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -il_call_operator: - CAL_operator -| CALC_operator -| CALCN_operator -; - - -il_return_operator: - RET_operator -| RETC_operator -| RETCN_operator -; - - -il_jump_operator: - JMP_operator -| JMPC_operator -| JMPCN_operator -; - - -/***********************/ -/* B 3.1 - Expressions */ -/***********************/ -expression: - xor_expression -| expression OR xor_expression - {$$ = new or_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| expression OR error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after 'OR' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after 'OR' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -xor_expression: - and_expression -| xor_expression XOR and_expression - {$$ = new xor_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| xor_expression XOR error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after 'XOR' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after 'XOR' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -and_expression: - comparison -| and_expression '&' comparison - {$$ = new and_expression_c($1, $3, locloc(@$));} -| and_expression AND comparison - {$$ = new and_expression_c($1, $3, locloc(@$));} -/* NOTE: The lexical parser never returns the token '&'. - * The '&' string is interpreted by the lexcial parser as the token - * AND2! - * This means that the first rule with '&' is actually not required, - * but we leave it in nevertheless just in case we later decide - * to remove the AND2 token... - */ -| and_expression AND2 comparison - {$$ = new and_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| and_expression '&' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '&' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '&' in ST expression."); yyclearin;} - yyerrok; - } -| and_expression AND error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after 'AND' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after 'AND' in ST expression."); yyclearin;} - yyerrok; - } -| and_expression AND2 error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '&' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '&' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -comparison: - equ_expression -| comparison '=' equ_expression - {$$ = new equ_expression_c($1, $3, locloc(@$));} -| comparison OPER_NE equ_expression - {$$ = new notequ_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| comparison '=' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '=' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '=' in ST expression."); yyclearin;} - yyerrok; - } -| comparison OPER_NE error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '<>' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '<>' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -equ_expression: - add_expression -| equ_expression '<' add_expression - {$$ = new lt_expression_c($1, $3, locloc(@$));} -| equ_expression '>' add_expression - {$$ = new gt_expression_c($1, $3, locloc(@$));} -| equ_expression OPER_LE add_expression - {$$ = new le_expression_c($1, $3, locloc(@$));} -| equ_expression OPER_GE add_expression - {$$ = new ge_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| equ_expression '<' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '<' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '<' in ST expression."); yyclearin;} - yyerrok; - } -| equ_expression '>' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '>' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '>' in ST expression."); yyclearin;} - yyerrok; - } -| equ_expression OPER_LE error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '<=' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '<=' in ST expression."); yyclearin;} - yyerrok; - } -| equ_expression OPER_GE error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '>=' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '>=' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* Not required... -comparison_operator: '<' | '>' | '>=' '<=' -*/ - -add_expression: - term -| add_expression '+' term - {$$ = new add_expression_c($1, $3, locloc(@$));} -| add_expression '-' term - {$$ = new sub_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| add_expression '+' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '+' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '+' in ST expression."); yyclearin;} - yyerrok; - } -| add_expression '-' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '-' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '-' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* Not required... -add_operator: '+' | '-' -*/ - -term: - power_expression -| term '*' power_expression - {$$ = new mul_expression_c($1, $3, locloc(@$));} -| term '/' power_expression - {$$ = new div_expression_c($1, $3, locloc(@$));} -| term MOD power_expression - {$$ = new mod_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| term '*' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '*' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '*' in ST expression."); yyclearin;} - yyerrok; - } -| term '/' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '/' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '/' in ST expression."); yyclearin;} - yyerrok; - } -| term MOD error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after 'MOD' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after 'MOD' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* Not required... -multiply_operator: '*' | '/' | 'MOD' -*/ - -power_expression: - unary_expression -| power_expression OPER_EXP unary_expression - {$$ = new power_expression_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| power_expression OPER_EXP error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after '**' in ST expression.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after '**' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -unary_expression: - non_negative_primary_expression -| '-' non_negative_primary_expression - {$$ = new neg_expression_c($2, locloc(@$));} -| NOT primary_expression - {$$ = new not_expression_c($2, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| '-' error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no expression defined after '-' in ST expression.");} - else {print_err_msg(locf(@2), locl(@2), "invalid expression after '-' in ST expression."); yyclearin;} - yyerrok; - } -| NOT error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@1), locf(@2), "no expression defined after 'NOT' in ST expression.");} - else {print_err_msg(locf(@2), locl(@2), "invalid expression after 'NOT' in ST expression."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* Not required... -unary_operator: '-' | 'NOT' -*/ - - -/* NOTE: using constant as a possible symbol for primary_expression - * leads to a reduce/reduce conflict. - * - * The text '-9' may be parsed as either a - * expression<-primary_expression<-constant<-signed_integer - * (i.e. the constant 9 negative) - * OR - * expression<-unary_expression<-constant<-integer - * (i.e. the constant 9, preceded by a unary negation) - * - * To remove the conflict, we only allow constants without - * a preceding '-' to be used in primary_expression - * (i.e. as a parameter to the unary negation operator) - */ -/* NOTE: We use enumerated_value_without_identifier instead of enumerated_value - * in order to remove a reduce/reduce conflict between reducing an - * identifier to a variable or an enumerated_value. - * - * This change follows the IEC specification. The specification seems to - * imply (by introducing syntax that allows to unambiguosly reference an - * enumerated value - enum_type#enum_value) that in case the same identifier is used - * for a variable and an enumerated value, then the variable shall be - * considered. - */ -non_negative_primary_expression: - non_negative_constant -//| enumerated_value_without_identifier -| enumerated_value -| variable -| '(' expression ')' - {$$ = $2;} -| function_invocation -/* ERROR_CHECK_BEGIN */ -| '(' expression error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing at the end of expression in ST expression."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -primary_expression: - constant -//| enumerated_value_without_identifier -| enumerated_value -| variable -| '(' expression ')' - {$$ = $2;} -| function_invocation -/* ERROR_CHECK_BEGIN */ -| '(' expression error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing at the end of expression in ST expression."); yyerrok;} -/* ERROR_CHECK_END */ -; - - - -/* intermediate helper symbol for primary_expression */ -/* NOTE: function_name includes the standard function name 'NOT' ! - * This introduces a reduce/reduce conflict, as NOT(var) - * may be parsed as either a function_invocation, or a - * unary_expression. - * - * I (Mario) have opted to remove the possible reduction - * to function invocation, which means replacing the rule - * function_name '(' param_assignment_list ')' - * with - * function_name_no_NOT_clashes '(' param_assignment_list ')' - * - * Notice how the new rule does not include the situation where - * the function NOT is called with more than one parameter, which - * the original rule does include! Callinf the NOT function with more - * than one argument is probably a semantic error anyway, so it - * doesn't make much sense to take it into account. - * - * Nevertheless, if we were to to it entirely correctly, - * leaving the semantic checks for the next compiler stage, - * this syntax parser would need to include such a possibility. - * - * We will leave this out for now. No need to complicate the syntax - * more than the specification does by contradicting itself, and - * letting names clash! - */ -function_invocation: -/* function_name '(' [param_assignment_list] ')' */ - function_name_no_NOT_clashes '(' param_assignment_formal_list ')' - {$$ = new function_invocation_c($1, $3, NULL, locloc(@$));} -| function_name_no_NOT_clashes '(' param_assignment_nonformal_list ')' - {$$ = new function_invocation_c($1, NULL, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| function_name_no_NOT_clashes param_assignment_formal_list ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function name in ST expression."); yynerrs++;} -| function_name_no_NOT_clashes '(' ')' - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "no parameter defined in function invocation of ST expression."); yynerrs++;} -| function_name_no_NOT_clashes '(' error ')' - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid parameter(s) defined in function invocation of ST expression."); yyerrok;} -| function_name_no_NOT_clashes '(' param_assignment_formal_list error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing at the end of function invocation in ST expression."); yyerrok;} -| function_name_no_NOT_clashes '(' param_assignment_nonformal_list error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing at the end of function invocation in ST expression."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/********************/ -/* B 3.2 Statements */ -/********************/ -statement_list: - statement ';' - {$$ = new statement_list_c(locloc(@$)); $$->add_element($1);} -| any_pragma - {$$ = new statement_list_c(locloc(@$)); $$->add_element($1);} -| statement_list statement ';' - {$$ = $1; $$->add_element($2);} -| statement_list any_pragma - {$$ = $1; $$->add_element($2);} -/* ERROR_CHECK_BEGIN */ -| statement error - {$$ = new statement_list_c(locloc(@$)); print_err_msg(locl(@1), locf(@2), "';' missing at the end of statement in ST statement."); yyerrok;} -| statement_list statement error - {$$ = $1; print_err_msg(locl(@2), locf(@3), "';' missing at the end of statement in ST statement."); yyerrok;} -| statement_list error ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "invalid statement in ST statement."); yyerrok;} -| statement_list ';' - {$$ = $1; print_err_msg(locf(@2), locl(@2), "unexpected ';' after statement in ST statement."); yynerrs++;} -/* ERROR_CHECK_END */ -; - - -statement: - assignment_statement -| subprogram_control_statement -| selection_statement -| iteration_statement -; - - -/*********************************/ -/* B 3.2.1 Assignment Statements */ -/*********************************/ -assignment_statement: - variable ASSIGN expression - {$$ = new assignment_statement_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| error ASSIGN expression - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid variable before ':=' in ST assignment statement."); yyerrok;} -| variable ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined after ':=' in ST assignment statement.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression after ':=' in ST assignment statement."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - - - -/*****************************************/ -/* B 3.2.2 Subprogram Control Statements */ -/*****************************************/ -subprogram_control_statement: - fb_invocation -| return_statement -; - -return_statement: - RETURN {$$ = new return_statement_c(locloc(@$));} -; - - - -fb_invocation: - prev_declared_fb_name '(' ')' - {$$ = new fb_invocation_c($1, NULL, NULL, locloc(@$)); } -| prev_declared_fb_name '(' param_assignment_formal_list ')' - {$$ = new fb_invocation_c($1, $3, NULL, locloc(@$));} -| prev_declared_fb_name '(' param_assignment_nonformal_list ')' - {$$ = new fb_invocation_c($1, NULL, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| prev_declared_fb_name ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function block name in ST statement."); yynerrs++;} -| prev_declared_fb_name param_assignment_formal_list ')' - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "'(' missing after function block name in ST statement."); yynerrs++;} -| prev_declared_fb_name '(' error ')' - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid parameter list in function block invocation in ST statement."); yyerrok;} -| prev_declared_fb_name '(' error - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing after parameter list of function block invocation in ST statement."); yyerrok;} -| prev_declared_fb_name '(' param_assignment_formal_list error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing after parameter list of function block invocation in ST statement."); yyerrok;} -| prev_declared_fb_name '(' param_assignment_nonformal_list error - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "')' missing after parameter list of function block invocation in ST statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for - * - fb_invocation - * - function_invocation - */ -param_assignment_formal_list: - param_assignment_formal - {$$ = new param_assignment_list_c(locloc(@$)); $$->add_element($1);} -| param_assignment_formal_list ',' param_assignment_formal - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| param_assignment_formal_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no parameter assignment defined in ST parameter assignment list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid parameter assignment in ST parameter assignment list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - -/* helper symbol for - * - fb_invocation - * - function_invocation - */ -param_assignment_nonformal_list: - param_assignment_nonformal - {$$ = new param_assignment_list_c(locloc(@$)); $$->add_element($1);} -| param_assignment_nonformal_list ',' param_assignment_nonformal - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| param_assignment_nonformal_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no parameter assignment defined in ST parameter assignment list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid parameter assignment in ST parameter assignment list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -/* NOTE: According to the IEC 61131-3 standard, there are two possible - * syntaxes for calling function blocks within ST. - * The formal method has the form: - * fb ( invar := x, inoutvar := var1, outvar => var2); - * The non-formal method has the form: - * fb (x, var1, var2); - * In the text of IEC 61131-3 (where the semantics are defined), - * it is obvious that mixing the two syntaxes is considered incorrect. - * The following should therefore be incorrect: - * fb ( invar := x, var1, var2); - * However, according to the syntax definition, as defined in IEC 61131-3, - * mixing the formal and non-formal methods of invocation is allowed. - * We have two alternatives: - * (a) implement the syntax here in iec.y according to the standard, - * and leave it to the semantic analyser stage to find this error - * (b) or implement the syntax in iec.y correctly, not allowing - * the mixing of formal and non-formal invocation syntaxes. - * Considering that this is a syntax issue, and not semantic issue, - * I (Mario) have decided to go with alternative (a). - * In other words, in iec.y we do not follow the syntax as defined in - * Annex B of the IEC 61131-3 standard, but rather implement - * the syntax also taking into account the textual part of the standard too. - */ -/* -param_assignment: - variable_name ASSIGN expression -*/ -param_assignment_nonformal: - expression -; - - -param_assignment_formal: - any_identifier ASSIGN expression - {$$ = new input_variable_param_assignment_c($1, $3, locloc(@$));} -| en_identifier ASSIGN expression - {$$ = new input_variable_param_assignment_c($1, $3, locloc(@$));} -/*| variable_name SENDTO variable */ -/*| any_identifier SENDTO variable */ -| sendto_identifier SENDTO variable - {$$ = new output_variable_param_assignment_c(NULL, $1, $3, locloc(@$));} -/* The following is not required, as the sendto_identifier_token returned by flex will - * also include the 'ENO' identifier. - * The resulting abstract syntax tree is identical with or without this following rule, - * as both the eno_identifier and the sendto_identifier are stored as - * an identifier_c !! - * - * To understand why we must even explicitly consider the use of ENO here, - * please read the comment above the definition of 'variable' in section B1.4 for details. - */ -/* -| eno_identifier SENDTO variable - {$$ = new output_variable_param_assignment_c(NULL, $1, $3, locloc(@$));} -*/ -/*| NOT variable_name SENDTO variable */ -/*| NOT any_identifier SENDTO variable*/ -| NOT sendto_identifier SENDTO variable - {$$ = new output_variable_param_assignment_c(new not_paramassign_c(locloc(@$)), $2, $4, locloc(@$));} -/* The following is not required, as the sendto_identifier_token returned by flex will - * also include the 'ENO' identifier. - * The resulting abstract syntax tree is identical with or without this following rule, - * as both the eno_identifier and the sendto_identifier are stored as - * an identifier_c !! - * - * To understand why we must even explicitly consider the use of ENO here, - * please read the comment above the definition of 'variable' in section B1.4 for details. - */ -/* -| NOT eno_identifier SENDTO variable - {$$ = new output_variable_param_assignment_c(new not_paramassign_c(locloc(@$)), $2, $4, locloc(@$));} -*/ -/* ERROR_CHECK_BEGIN */ -| any_identifier ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter assignment.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter assignment."); yyclearin;} - yyerrok; - } -| en_identifier ASSIGN error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter assignment.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter assignment."); yyclearin;} - yyerrok; - } -| sendto_identifier SENDTO error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter out assignment.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter out assignment."); yyclearin;} - yyerrok; - } -/* -| eno_identifier SENDTO error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter out assignment.");} - else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter out assignment."); yyclearin;} - yyerrok; - } -*/ -| NOT SENDTO variable - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no parameter name defined in ST formal parameter out negated assignment."); yynerrs++;} -| NOT error SENDTO variable - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid parameter name defined in ST formal parameter out negated assignment."); yyerrok;} -| NOT sendto_identifier SENDTO error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no expression defined in ST formal parameter out negated assignment.");} - else {print_err_msg(locf(@4), locl(@4), "invalid expression in ST formal parameter out negated assignment."); yyclearin;} - yyerrok; - } -/* -| NOT eno_identifier SENDTO error - {$$ = NULL; - if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no expression defined in ST formal parameter out negated assignment.");} - else {print_err_msg(locf(@4), locl(@4), "invalid expression in ST formal parameter out negated assignment."); yyclearin;} - yyerrok; - } -*/ -/* ERROR_CHECK_END */ -; - - - - - -/********************************/ -/* B 3.2.3 Selection Statements */ -/********************************/ -selection_statement: - if_statement -| case_statement -; - - -if_statement: - IF expression THEN statement_list elseif_statement_list END_IF - {$$ = new if_statement_c($2, $4, $5, NULL, locloc(@$));} -| IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF - {$$ = new if_statement_c($2, $4, $5, $7, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| IF THEN statement_list elseif_statement_list END_IF - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no test expression defined in ST 'IF' statement."); yynerrs++;} -| IF THEN statement_list elseif_statement_list ELSE statement_list END_IF - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no test expression defined in ST 'IF' statement."); yynerrs++;} -| IF error THEN statement_list elseif_statement_list END_IF - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid test expression defined for ST 'IF' statement."); yyerrok;} -| IF error THEN statement_list elseif_statement_list ELSE statement_list END_IF - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid test expression defined for ST 'IF' statement."); yyerrok;} -| IF expression error statement_list elseif_statement_list END_IF - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting 'THEN' after test expression in ST 'IF' statement."); yyerrok;} -| IF expression error statement_list elseif_statement_list ELSE statement_list END_IF - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting 'THEN' after test expression in ST 'IF' statement."); yyerrok;} -| IF expression THEN elseif_statement_list END_IF - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no statement defined after 'THEN' in ST 'IF' statement."); yynerrs++;} -| IF expression THEN elseif_statement_list ELSE statement_list END_IF - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no statement defined after 'THEN' in ST 'IF' statement."); yynerrs++;} -| IF expression THEN statement_list elseif_statement_list ELSE END_IF - {$$ = NULL; print_err_msg(locl(@6), locf(@7), "no statement defined after 'ELSE' in ST 'IF' statement."); yynerrs++;} -| IF expression THEN statement_list elseif_statement_list ELSE error END_IF - {$$ = NULL; print_err_msg(locf(@7), locl(@7), "invalid statement defined after 'ELSE' in ST 'IF' statement."); yynerrs++; yyerrok;} -| IF expression error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed 'IF' statement in ST."); yyerrok;} -| IF expression THEN statement_list elseif_statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "unclosed 'IF' statement in ST."); yynerrs++;} -| IF expression THEN statement_list elseif_statement_list ELSE statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "unclosed 'IF' statement in ST."); yynerrs++;} -| IF error END_IF - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in ST 'IF' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* helper symbol for if_statement */ -elseif_statement_list: - /* empty */ - {$$ = new elseif_statement_list_c(locloc(@$));} -| elseif_statement_list elseif_statement - {$$ = $1; $$->add_element($2);} -; - -/* helper symbol for elseif_statement_list */ -elseif_statement: - ELSIF expression THEN statement_list - {$$ = new elseif_statement_c($2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| ELSIF THEN statement_list - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no test expression defined for 'ELSEIF' statement in ST 'IF' statement."); yynerrs++;} -| ELSIF error THEN statement_list - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid test expression defined for 'ELSEIF' statement in ST 'IF' statement."); yyerrok;} -| ELSIF expression error statement_list - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting 'THEN' after test expression in 'ELSEIF' statement of ST 'IF' statement."); yyerrok;} -| ELSIF expression THEN error - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid statement list in 'ELSEIF' statement of ST 'IF' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -case_statement: - CASE expression OF case_element_list END_CASE - {$$ = new case_statement_c($2, $4, NULL, locloc(@$));} -| CASE expression OF case_element_list ELSE statement_list END_CASE - {$$ = new case_statement_c($2, $4, $6, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| CASE OF case_element_list END_CASE - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no test expression defined in ST 'CASE' statement."); yynerrs++;} -| CASE OF case_element_list ELSE statement_list END_CASE - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no test expression defined in ST 'CASE' statement."); yynerrs++;} -| CASE error OF case_element_list END_CASE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid test expression defined for ST 'CASE' statement."); yyerrok;} -| CASE error OF case_element_list ELSE statement_list END_CASE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid test expression defined for ST 'CASE' statement."); yyerrok;} -| CASE expression error case_element_list END_CASE - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting 'OF' after test expression in ST 'CASE' statement."); yyerrok;} -| CASE expression error case_element_list ELSE statement_list END_CASE - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting 'OF' after test expression in ST 'CASE' statement."); yyerrok;} -| CASE expression OF END_CASE - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no case element(s) defined after 'OF' in ST 'CASE' statement."); yynerrs++;} -| CASE expression OF ELSE statement_list END_CASE - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no case element(s) defined after 'OF' in ST 'CASE' statement."); yynerrs++;} -| CASE expression OF error END_CASE - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid case element(s) defined after 'OF' in ST 'CASE' statement."); yyerrok;} -| CASE expression OF error ELSE statement_list END_CASE - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid case element(s) defined after 'OF' in ST 'CASE' statement."); yyerrok;} -| CASE expression OF case_element_list ELSE END_CASE - {$$ = NULL; print_err_msg(locl(@5), locf(@6), "no statement defined after 'ELSE' in ST 'CASE' statement."); yynerrs++;} -| CASE expression OF case_element_list ELSE error END_CASE - {$$ = NULL; print_err_msg(locf(@6), locl(@6), "invalid statement defined after 'ELSE' in ST 'CASE' statement."); yyerrok;} -| CASE expression error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@2), "unclosed 'CASE' statement in ST."); yyerrok;} -| CASE expression OF case_element_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "unclosed 'CASE' statement in ST."); yynerrs++;} -| CASE expression OF case_element_list ELSE statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@3), "unclosed 'CASE' statement in ST."); yynerrs++;} -| CASE error END_CASE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in ST 'CASE' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -/* helper symbol for case_statement */ -case_element_list: - case_element - {$$ = new case_element_list_c(locloc(@$)); $$->add_element($1);} -| case_element_list case_element - {$$ = $1; $$->add_element($2);} -; - - -case_element: - case_list ':' statement_list - {$$ = new case_element_c($1, $3, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| case_list statement_list - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing after case list in ST 'CASE' statement."); yynerrs++;} -| case_list ':' error - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "invalid statement in case element of ST 'CASE' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -case_list: - case_list_element - {$$ = new case_list_c(locloc(@$)); $$->add_element($1);} -| case_list ',' case_list_element - {$$ = $1; $$->add_element($3);} -/* ERROR_CHECK_BEGIN */ -| case_list ',' error - {$$ = $1; - if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no case defined in case list of ST parameter assignment list.");} - else {print_err_msg(locf(@3), locl(@3), "invalid case in case list of ST parameter assignment list."); yyclearin;} - yyerrok; - } -/* ERROR_CHECK_END */ -; - - -case_list_element: - signed_integer -| subrange -| enumerated_value -; - - - - - -/********************************/ -/* B 3.2.4 Iteration Statements */ -/********************************/ -iteration_statement: - for_statement -| while_statement -| repeat_statement -| exit_statement -; - - -for_statement: - FOR control_variable ASSIGN expression TO expression BY expression DO statement_list END_FOR - {$$ = new for_statement_c($2, $4, $6, $8, $10, locloc(@$));} -| FOR control_variable ASSIGN expression TO expression DO statement_list END_FOR - {$$ = new for_statement_c($2, $4, $6, NULL, $8, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| FOR ASSIGN expression TO expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no control variable defined in ST 'FOR' statement."); yynerrs++;} -| FOR ASSIGN expression TO expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no control variable defined in ST 'FOR' statement."); yynerrs++;} -| FOR error ASSIGN expression TO expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid control variable defined for ST 'FOR' statement."); yyerrok;} -| FOR error ASSIGN expression TO expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid control variable defined for ST 'FOR' statement."); yyerrok;} -| FOR control_variable expression TO expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "':=' missing between control variable and start expression in ST 'FOR' statement."); yynerrs++;} -| FOR control_variable expression TO expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locl(@2), locf(@3), "':=' missing between control variable and start expression in ST 'FOR' statement."); yynerrs++;} -| FOR control_variable error expression TO expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting ':=' between control variable and start expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable error expression TO expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting ':=' between control variable and start expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN TO expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no start expression defined in ST 'FOR' statement."); yynerrs++;} -| FOR control_variable ASSIGN TO expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no start expression defined in ST 'FOR' statement."); yynerrs++;} -| FOR control_variable ASSIGN error TO expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid start expression defined in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN error TO expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid start expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression error expression BY expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@5), locl(@5), "expecting 'TO' between start expression and end expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression error expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@5), locl(@5), "expecting 'TO' between start expression and end expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression error expression DO statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@7), locl(@7), "expecting 'BY' between end expression and step expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression BY expression error statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@9), locl(@9), "expecting 'DO' after step expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression error statement_list END_FOR - {$$ = NULL; print_err_msg(locf(@7), locl(@7), "expecting 'DO' after end expression in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression BY expression DO END_FOR - {$$ = NULL; print_err_msg(locl(@9), locf(@10), "no statement(s) defined after 'DO' in ST 'FOR' statement."); yynerrs++;} -| FOR control_variable ASSIGN expression TO expression DO END_FOR - {$$ = NULL; print_err_msg(locl(@7), locf(@8), "no statement(s) defined after 'DO' in ST 'FOR' statement."); yynerrs++;} -| FOR control_variable ASSIGN expression TO expression BY expression DO error END_FOR - {$$ = NULL; print_err_msg(locf(@10), locl(@10), "invalid statement(s) defined after 'DO' in ST 'FOR' statement."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression DO error END_FOR - {$$ = NULL; print_err_msg(locf(@8), locl(@8), "invalid statement(s) defined after 'DO' in ST 'FOR' statement."); yyerrok;} -| FOR control_variable error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'FOR' statement in ST."); yyerrok;} -| FOR control_variable ASSIGN expression error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'FOR' statement in ST."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression DO statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'FOR' statement in ST."); yynerrs++;} -| FOR control_variable ASSIGN expression TO expression BY expression error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'FOR' statement in ST."); yyerrok;} -| FOR control_variable ASSIGN expression TO expression BY expression DO statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'FOR' statement in ST."); yynerrs++;} -| FOR error END_FOR - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in ST 'FOR' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - -/* The spec has the syntax - * control_variable: identifier; - * but then defines the semantics of control_variable - * (Section 3.3.2.4) as being of an integer type - * (e.g., SINT, INT, or DINT). - * - * Obviously this presuposes that the control_variable - * must have been declared in some VAR .. END_VAR - * We must therefore change the syntax to read - * control_variable: prev_declared_variable_name; - * - * If we don't, then the correct use of any previosuly declared - * variable would result in an incorrect syntax error -*/ -control_variable: - prev_declared_variable_name - {$$ = new symbolic_variable_c($1,locloc(@$));}; -// control_variable: identifier {$$ = $1;}; - -/* Integrated directly into for_statement */ -/* -for_list: - expression TO expression [BY expression] -; -*/ - - -while_statement: - WHILE expression DO statement_list END_WHILE - {$$ = new while_statement_c($2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| WHILE DO statement_list END_WHILE - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no test expression defined in ST 'WHILE' statement."); yynerrs++;} -| WHILE error DO statement_list END_WHILE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid test expression defined for ST 'WHILE' statement."); yyerrok;} -| WHILE expression error statement_list END_WHILE - {$$ = NULL; print_err_msg(locf(@3), locl(@3), "expecting 'DO' after test expression in ST 'WHILE' statement."); yyerrok;} -| WHILE expression DO END_WHILE - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no statement(s) defined after 'DO' in ST 'WHILE' statement."); yynerrs++;} -| WHILE expression DO error END_WHILE - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid statement(s) defined after 'DO' in ST 'WHILE' statement."); yyerrok;} -| WHILE expression error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'WHILE' statement in ST."); yyerrok;} -| WHILE expression DO statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'WHILE' statement in ST."); yynerrs++;} -| WHILE error END_WHILE - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in ST 'WHILE' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -repeat_statement: - REPEAT statement_list UNTIL expression END_REPEAT - {$$ = new repeat_statement_c($2, $4, locloc(@$));} -/* ERROR_CHECK_BEGIN */ -| REPEAT UNTIL expression END_REPEAT - {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no statement(s) defined after 'REPEAT' in ST 'REPEAT' statement."); yynerrs++;} -| REPEAT error UNTIL expression END_REPEAT - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "invalid statement(s) defined after 'REPEAT' for ST 'REPEAT' statement."); yyerrok;} -| REPEAT statement_list UNTIL END_REPEAT - {$$ = NULL; print_err_msg(locl(@3), locf(@4), "no test expression defined after 'UNTIL' in ST 'REPEAT' statement.");} -| REPEAT statement_list UNTIL error END_REPEAT - {$$ = NULL; print_err_msg(locf(@4), locl(@4), "invalid test expression defined after 'UNTIL' in ST 'REPEAT' statement."); yyerrok;} -| REPEAT statement_list END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'REPEAT' statement in ST."); yynerrs++;} -| REPEAT statement_list UNTIL expression error END_OF_INPUT - {$$ = NULL; print_err_msg(locf(@1), locl(@1), "unclosed 'REPEAT' statement in ST."); yyerrok;} -| REPEAT error END_REPEAT - {$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in ST 'REPEAT' statement."); yyerrok;} -/* ERROR_CHECK_END */ -; - - -exit_statement: - EXIT {$$ = new exit_statement_c(locloc(@$));} -; - - - - - -%% - -#include /* required for printf() */ -#include -#include "../util/symtable.hh" - -/* variables defined in code generated by flex... */ -extern FILE *yyin; -extern int yylineno; -extern tracking_t* current_tracking; - - - - -/*************************************************************************************************/ -/* NOTE: These variables are really parameters we would like the stage2__ function to pass */ -/* to the yyparse() function. However, the yyparse() function is created automatically */ -/* by bison, so we cannot add parameters to this function. The only other */ -/* option is to use global variables! yuck! */ -/*************************************************************************************************/ - -/* A global flag used to tell the parser if overloaded funtions should be allowed. - * The IEC 61131-3 standard allows overloaded funtions in the standard library, - * but disallows them in user code... - * - * In essence, a parameter we would like to pass to the yyparse() function but - * have to do it using a global variable, as the yyparse() prototype is fixed by bison. - */ -bool allow_function_overloading = false; - -/* A global flag used to tell the parser whether to include the full variable location - * when printing out error messages... - */ -bool full_token_loc; - -/* A pointer to the root of the parsing tree that will be generated - * by bison. - */ -symbol_c *tree_root; - - - -/* The following function is called automatically by bison whenever it comes across - * an error. Unfortunately it calls this function before executing the code that handles - * the error itself, so we cannot print out the correct line numbers of the error location - * over here. - * Our solution is to store the current error message in a global variable, and have all - * error action handlers call the function print_err_msg() after setting the location - * (line number) variable correctly. - */ -const char *current_error_msg; -void yyerror (const char *error_msg) { - current_error_msg = error_msg; -/* fprintf(stderr, "error %d: %s\n", yynerrs // global variable //, error_msg); */ -/* print_include_stack(); */ -} - - -/* ERROR_CHECK_BEGIN */ -bool is_current_syntax_token() { - switch (yychar) { - case ';': - case ',': - case ')': - case ']': - case '+': - case '*': - case '-': - case '/': - case '<': - case '>': - case '=': - case '&': - case OR: - case XOR: - case AND: - case AND2: - case OPER_NE: - case OPER_LE: - case OPER_GE: - case MOD: - case OPER_EXP: - case NOT: - return true; - default: - return false; - } -} -/* ERROR_CHECK_END */ - - -void print_err_msg(int first_line, - int first_column, - const char *first_filename, - long int first_order, - int last_line, - int last_column, - const char *last_filename, - long int last_order, - const char *additional_error_msg) { - - const char *unknown_file = ""; - if (first_filename == NULL) first_filename = unknown_file; - if ( last_filename == NULL) last_filename = unknown_file; - - if (full_token_loc) { - if (first_filename == last_filename) - fprintf(stderr, "%s:%d-%d..%d-%d: error : %s\n", first_filename, first_line, first_column, last_line, last_column, additional_error_msg); - else - fprintf(stderr, "%s:%d-%d..%s:%d-%d: error : %s\n", first_filename, first_line, first_column, last_filename, last_line, last_column, additional_error_msg); - } else { - fprintf(stderr, "%s:%d: error : %s\n", first_filename, first_line, additional_error_msg); - } - //fprintf(stderr, "error %d: %s\n", yynerrs /* a global variable */, additional_error_msg); - print_include_stack(); - //fprintf(stderr, "%s(%d-%d): %s\n", current_filename, first_line, last_line, current_error_msg); -} - - - -/* convert between an il_operator to a function name */ -/* This a kludge! - * It is required because our language requires more than one - * look ahead token, and bison only works with one! - */ -#define op_2_str(op, str) {\ - op ## _operator_c *ptr = dynamic_cast(il_operator); \ - if (ptr != NULL) name = str; \ -} - -/* NOTE: this code is very ugly and un-eficient, but I (Mario) have many - * more things to worry about right now, so just let it be... - */ -symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator) { - const char *name = NULL; - identifier_c *res; - - op_2_str(NOT, "NOT"); - - op_2_str(AND, "AND"); - op_2_str(OR, "OR"); - op_2_str(XOR, "XOR"); - op_2_str(ADD, "ADD"); - op_2_str(SUB, "SUB"); - op_2_str(MUL, "MUL"); - op_2_str(DIV, "DIV"); - op_2_str(MOD, "MOD"); - op_2_str(GT, "GT"); - op_2_str(GE, "GE"); - op_2_str(EQ, "EQ"); - op_2_str(LT, "LT"); - op_2_str(LE, "LE"); - op_2_str(NE, "NE"); - - op_2_str(LD, "LD"); - op_2_str(LDN, "LDN"); - op_2_str(ST, "ST"); - op_2_str(STN, "STN"); - - op_2_str(S, "S"); - op_2_str(R, "R"); - op_2_str(S1, "S1"); - op_2_str(R1, "R1"); - - op_2_str(CLK, "CLK"); - op_2_str(CU, "CU"); - op_2_str(CD, "CD"); - op_2_str(PV, "PV"); - op_2_str(IN, "IN"); - op_2_str(PT, "PT"); - - op_2_str(ANDN, "ANDN"); - op_2_str(ORN, "ORN"); - op_2_str(XORN, "XORN"); - - op_2_str(ADD, "ADD"); - op_2_str(SUB, "SUB"); - op_2_str(MUL, "MUL"); - op_2_str(DIV, "DIV"); - - op_2_str(GT, "GT"); - op_2_str(GE, "GE"); - op_2_str(EQ, "EQ"); - op_2_str(LT, "LT"); - op_2_str(LE, "LE"); - op_2_str(NE, "NE"); - - op_2_str(CAL, "CAL"); - op_2_str(CALC, "CALC"); - op_2_str(CALCN, "CALCN"); - op_2_str(RET, "RET"); - op_2_str(RETC, "RETC"); - op_2_str(RETCN, "RETCN"); - op_2_str(JMP, "JMP"); - op_2_str(JMPC, "JMPC"); - op_2_str(JMPCN, "JMPCN"); - - if (name == NULL) - ERROR; - - res = new identifier_c(strdup(name), - il_operator->first_line, - il_operator->first_column, - il_operator->first_file, - il_operator->first_order, - il_operator->last_line, - il_operator->last_column, - il_operator->last_file, - il_operator->last_order - ); - free(il_operator); - return res; -} - - -#include "standard_function_names.c" - -const char *standard_function_block_names[] = { -// 2.5.2.3.1 Bistable elements -// Table 34 - Standard bistable function blocks -"SR","RS", -// 2.5.2.3.2 Edge detection -// Table 35 - Standard edge detection function blocks -"R_TRIG","F_TRIG", -// 2.5.2.3.3 Counters -// Table 36 - Standard counter function blocks -"CTU","CTU_DINT","CTU_LINT","CTU_UDINT","CTU_ULINT", -"CTD","CTD_DINT","CTD_LINT","CTD_UDINT","CTD_ULINT", -"CTUD","CTUD_DINT","CTUD_LINT","CTUD_ULINT", -// 2.5.2.3.4 Timers -// Table 37 - Standard timer function blocks -"TP","TON","TOF", -/* end of array marker! Do not remove! */ -NULL -}; - - -#define LIBFILE "ieclib.txt" -#define DEF_LIBFILENAME LIBDIRECTORY "/" LIBFILE - -extern const char *INCLUDE_DIRECTORIES[]; - - - -int stage2__(const char *filename, - const char *includedir, /* Include directory, where included files will be searched for... */ - symbol_c **tree_root_ref, - bool full_token_loc_ /* error messages specify full token location */ - ) { - - 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); - free(errmsg); - return -1; - } - - if (includedir != NULL) { - INCLUDE_DIRECTORIES[0] = includedir; - } - if ((libfilename = strdup3(INCLUDE_DIRECTORIES[0], "/", LIBFILE)) == NULL) { - fprintf (stderr, "Out of memory. Bailing out!\n"); - return -1; - } - - if((lib_file = fopen(libfilename, "r")) == NULL) { - char *errmsg = strdup2("Error opening library file ", libfilename); - perror(errmsg); - free(errmsg); - } - - if (lib_file == NULL) { - /* we give up... */ - free(libfilename); - fclose(in_file); - return -1; - } - - /* first parse the standard library file... */ - /* - #if YYDEBUG - yydebug = 1; - #endif - */ - yyin = lib_file; - allow_function_overloading = true; - full_token_loc = full_token_loc_; - current_filename = libfilename; - current_tracking = GetNewTracking(yyin); - if (yyparse() != 0) - ERROR; - - if (yynerrs > 0) { - fprintf (stderr, "\nFound %d error(s) in %s. Bailing out!\n", yynerrs /* global variable */, libfilename); - ERROR; - } - free(libfilename); - fclose(lib_file); - - /* if by any chance the library is not complete, we - * now add the missing reserved keywords to the list!!! - */ - for(int i = 0; standard_function_block_names[i] != NULL; i++) - if (library_element_symtable.find_value(standard_function_block_names[i]) == - library_element_symtable.end_value()) - library_element_symtable.insert(standard_function_block_names[i], standard_function_block_name_token); - - - /* now parse the input file... */ - #if YYDEBUG - yydebug = 1; - #endif - yyin = in_file; - allow_function_overloading = false; - full_token_loc = full_token_loc_; - current_filename = filename; - current_tracking = GetNewTracking(yyin); - {int res; - if ((res = yyparse()) != 0) { - fprintf (stderr, "\nParsing failed because of too many consecutive syntax errors. Bailing out!\n"); - exit(EXIT_FAILURE); - } - } - - if (yynerrs > 0) { - fprintf (stderr, "\nFound %d error(s). Bailing out!\n", yynerrs /* global variable */); - exit(EXIT_FAILURE); - } - - if (tree_root_ref != NULL) - *tree_root_ref = tree_root; - - fclose(in_file); - return 0; -} - - -