etisserant@0: /*
etisserant@0:  * (c) 2003 Mario de Sousa
etisserant@0:  *
etisserant@0:  * Offered to the public under the terms of the GNU General Public License
etisserant@0:  * as published by the Free Software Foundation; either version 2 of the
etisserant@0:  * License, or (at your option) any later version.
etisserant@0:  *
etisserant@0:  * This program is distributed in the hope that it will be useful, but
etisserant@0:  * WITHOUT ANY WARRANTY; without even the implied warranty of
etisserant@0:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
etisserant@0:  * Public License for more details.
etisserant@0:  *
etisserant@0:  * This code is made available on the understanding that it will not be
etisserant@0:  * used in safety-critical situations without a full and competent review.
etisserant@0:  */
etisserant@0: 
etisserant@0: /*
etisserant@0:  * An IEC 61131-3 IL and ST compiler.
etisserant@0:  *
etisserant@0:  * Based on the
etisserant@0:  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
etisserant@0:  *
etisserant@0:  */
etisserant@0: 
etisserant@0: /*
etisserant@0:  * Stage 2
etisserant@0:  * =======
etisserant@0:  *
etisserant@0:  *  This file contains the syntax definition of the textual
etisserant@0:  *  languages IL and ST. The syntax parser, comprising the
etisserant@0:  *  2nd stage of the overall compiler, is generated by runing
etisserant@0:  *  bison on this file.
etisserant@0:  */
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /**********************************************************************/
etisserant@0: /**********************************************************************/
etisserant@0: /**********************************************************************/
etisserant@0: /**********************************************************************/
etisserant@0: /*******                                                        *******/
etisserant@0: /*******   The following syntax does not have any conflicts.    *******/
etisserant@0: /*******                                                        *******/
etisserant@0: /*******   P L E A S E    K E E P    I T    T H A T    W A Y !  *******/
etisserant@0: /*******   ===================================================  *******/
etisserant@0: /*******                                                        *******/
etisserant@0: /**********************************************************************/
etisserant@0: /**********************************************************************/
etisserant@0: /**********************************************************************/
etisserant@0: /**********************************************************************/
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: %{
etisserant@0: #include <string.h>	/* required for strdup()  */
etisserant@0: 
etisserant@0: 
etisserant@0: /* declare the token parser generated by flex... */
etisserant@0: int yylex(void);
etisserant@0: 
etisserant@0: /* declare the error handler defined at the end of this file */
etisserant@0: void yyerror (const char *error_msg);
etisserant@0: 
etisserant@0: /* produce a more verbose parsing error message */
etisserant@0: #define YYERROR_VERBOSE
etisserant@0: 
etisserant@0: /* Include debuging code.
etisserant@0:  * Printing of debug info must then be activated by setting
etisserant@0:  * the variable yydebug to 1.
etisserant@0:  */
mario@20: #define YYDEBUG 1
etisserant@0: 
etisserant@0: 
etisserant@0: /* file with declaration of absyntax classes... */
etisserant@0: #include "../absyntax/absyntax.hh"
etisserant@0: 
etisserant@0: /* file with declaration of token constants. Generated by bison! */
mario@15: // #include "iec.y.hh"
mario@15: 
mario@15: #include "stage1_2_priv.hh"
etisserant@0: 
etisserant@0: 
etisserant@0: /* an ugly hack!!
etisserant@0:  * We will probably not need it when we decide
etisserant@0:  *  to cut down the abstract syntax down to size.
etisserant@0:  *  We keep it as it is until we get to write
etisserant@0:  *  stages 3 and 4 of the compiler. Who knows,
etisserant@0:  *  we might just find out that we really do need
etisserant@0:  *  the abstract syntax tree to stay as it is
etisserant@0:  *  afterall!
etisserant@0:  */
etisserant@0: /* for each element <elem> in list_c * <list>
etisserant@0:  * execute the code <code>
etisserant@0:  */
etisserant@0: #define FOR_EACH_ELEMENT(elem, list, code) {		\
etisserant@0:   symbol_c *elem;					\
etisserant@0:   for(int i = 0; i < list->n; i++) {			\
etisserant@0:     elem = list->elements[i];				\
etisserant@0:     code;						\
etisserant@0:   }							\
etisserant@0: }
etisserant@0: 
etisserant@0: 
etisserant@0: /* A macro for printing out internal parser errors... */
etisserant@0: #define ERROR error_exit(__FILE__,__LINE__)
etisserant@0: /* function defined in main.cc */
etisserant@0: extern void error_exit(const char *file_name, int line_no);
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*************************/
etisserant@0: /* global variables...   */
etisserant@0: /*************************/
mario@15: /* NOTE: For some strange reason bison ver 2.3 is including these declarations
mario@15:  *       in the iec.y.hh file, which is in turn included by flex.
mario@15:  *       We cannot therefore define any variables over here, but merely declare 
mario@15:  *       their existance (otherwise we get errors when linking the code, since we
mario@15:  *       would get a new variable defined each time iec.y.hh is included!).
mario@15:  *       Even though the variables are declared 'extern' over here, they will in
mario@15:  *       fact be defined towards the end of this same file (i.e. in the prologue)
mario@15:  */
etisserant@0: 
etisserant@0: /* A global flag used to tell the parser if overloaded funtions should be allowed.
etisserant@0:  * The IEC 61131-3 standard allows overloaded funtions in the standard library,
etisserant@0:  * but disallows them in user code...
etisserant@0:  */
mario@15: extern bool allow_function_overloading;
mario@15: 
mario@15: /* A pointer to the root of the parsing tree that will be generated 
mario@15:  * by bison.
mario@15:  */
mario@15: extern symbol_c *tree_root;
mario@15: 
etisserant@0: 
etisserant@0: 
etisserant@0: /************************/
etisserant@0: /* forward declarations */
etisserant@0: /************************/
etisserant@0: /* The functions declared here are defined at the end of this file... */
etisserant@0: 
etisserant@0: /* Convert an il_operator_c into an identifier_c */
etisserant@0: symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator);
etisserant@0: 
etisserant@0: /* print an error message */
etisserant@0: void print_err_msg(const char *filename, int lineno, const char *additional_error_msg);
etisserant@0: 
etisserant@0: %}
etisserant@0: 
etisserant@0: 
etisserant@0: 
mario@15: 
mario@20: // %glr-parser
mario@13: // %expect-rr 1
mario@13: 
mario@13: 
mario@13: 
mario@13: 
etisserant@0: %union {
etisserant@0:     symbol_c 	*leaf;
etisserant@0:     list_c	*list;
etisserant@0:     char 	*ID;	/* token value */
etisserant@0:     struct {
etisserant@0:       symbol_c	*first;
etisserant@0:       symbol_c	*second;
lbessard@3:       symbol_c	*third;
lbessard@3:       symbol_c	*fourth;
lbessard@3:     } tmp_symbol; /* used as a temorary reference to symbols by:
lbessard@3:                                      il_simple_operator_clash_il_operand
lbessard@3:                                      transaction_tmp
lbessard@3:                                      action_tmp
lbessard@3:                              */
etisserant@0: }
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*****************************/
etisserant@0: /* Prelimenary constructs... */
etisserant@0: /*****************************/
etisserant@0: /* A bogus token that, in principle, flex MUST NEVER generate */
etisserant@0: /* USE 1:
etisserant@0:  * ======
etisserant@0:  * This token is currently also being used as the default
etisserant@0:  * initialisation value of the token_id member in
etisserant@0:  * the symbol_c base class.
etisserant@0:  *
etisserant@0:  * USE 2
etisserant@0:  * =====
etisserant@0:  * This token may also be used in the future to remove
etisserant@0:  * mysterious reduce/reduce conflicts due to the fact
etisserant@0:  * that our grammar may not be LALR(1) but merely LR(1).
etisserant@0:  * This means that bison cannot handle it without some
etisserant@0:  * caoxing from ourselves. We will then need this token
etisserant@0:  * to do the coaxing...
etisserant@0:  */
etisserant@0: %token BOGUS_TOKEN_ID
etisserant@0: 
etisserant@0: 
mario@15: 
mario@15: %{
mario@15: /* The interface through which bison and flex interact. */
mario@15: /* May only be included after the definition of BOGUS_TOKEN_ID */
mario@15: #include "stage1_2_priv.hh"
mario@15: %}
mario@15: 
mario@15: 
mario@15: %type <leaf> start
mario@15: 
mario@15: %type <leaf>	any_identifier
mario@15: 
mario@15: %token <ID>	prev_declared_variable_name_token
mario@15: %token <ID>	prev_declared_fb_name_token
mario@15: %type <leaf>	prev_declared_variable_name
mario@15: %type <leaf>	prev_declared_fb_name
mario@15: 
mario@15: %token  <ID>	prev_declared_simple_type_name_token
mario@15: %token  <ID>	prev_declared_subrange_type_name_token
mario@15: %token  <ID>	prev_declared_enumerated_type_name_token
mario@15: %token  <ID>	prev_declared_array_type_name_token
mario@15: %token  <ID>	prev_declared_structure_type_name_token
mario@15: %token  <ID>	prev_declared_string_type_name_token
mario@15: 
mario@15: %type  <leaf>	prev_declared_simple_type_name
mario@15: %type  <leaf>	prev_declared_subrange_type_name
mario@15: %type  <leaf>	prev_declared_enumerated_type_name
mario@15: %type  <leaf>	prev_declared_array_type_name
mario@15: %type  <leaf>	prev_declared_structure_type_name
mario@15: %type  <leaf>	prev_declared_string_type_name
mario@15: 
mario@15: %token <ID>	prev_declared_derived_function_name_token
mario@15: %token <ID>	prev_declared_derived_function_block_name_token
mario@15: %token <ID>	prev_declared_program_type_name_token
mario@15: %type  <leaf>	prev_declared_derived_function_name
mario@15: %type  <leaf>	prev_declared_derived_function_block_name
mario@15: %type  <leaf>	prev_declared_program_type_name
mario@15: 
mario@15: 
mario@15: 
mario@15: 
etisserant@0: /* The pragmas... */
etisserant@0: %token <ID>	pragma_token
etisserant@0: %type <leaf>	pragma
etisserant@0: 
etisserant@0: 
etisserant@0: /* Where do these tokens belong ?? */
etisserant@0: /* TODO: get the syntax parser to handle these tokens... */
etisserant@0: %token	EN
etisserant@0: %token	ENO
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /***************************/
etisserant@0: /* B 0 - Programming Model */
etisserant@0: /***************************/
etisserant@0: %type <list>	library
etisserant@0: %type <leaf>	library_element_declaration
etisserant@0: 
etisserant@0: 
etisserant@0: /*******************************************/
etisserant@0: /* B 1.1 - Letters, digits and identifiers */
etisserant@0: /*******************************************/
etisserant@0: /* Done totally within flex...
etisserant@0:   letter
etisserant@0:   digit
etisserant@0:   octal_digit
etisserant@0:   hex_digit
etisserant@0: */
etisserant@0: %token <ID>	identifier_token
etisserant@0: %type  <leaf>	identifier
etisserant@0: 
etisserant@0: 
etisserant@0: /*********************/
etisserant@0: /* B 1.2 - Constants */
etisserant@0: /*********************/
etisserant@0: %type <leaf>	constant
etisserant@0: /* a helper symbol for expression */
etisserant@0: %type  <leaf> non_negative_constant
etisserant@0: 
etisserant@0: 
etisserant@0: /******************************/
etisserant@0: /* B 1.2.1 - Numeric Literals */
etisserant@0: /******************************/
etisserant@0: /* Done totally within flex...
etisserant@0:   bit
etisserant@0: */
etisserant@0: %type  <leaf> numeric_literal
etisserant@0: /* helper symbol for non_negative_constant */
etisserant@0: %type  <leaf> non_negative_numeric_literal
etisserant@0: %type  <leaf> integer_literal
etisserant@0: %type  <leaf> signed_integer
etisserant@0: /* a helper symbol for non_negative_constant */
etisserant@0: %type  <leaf> non_negative_signed_integer
etisserant@0: %token <ID>   integer_token
etisserant@0: %type  <leaf> integer
etisserant@0: %token <ID>   binary_integer_token
etisserant@0: %type  <leaf> binary_integer
etisserant@0: %token <ID>   octal_integer_token
etisserant@0: %type  <leaf> octal_integer
etisserant@0: %token <ID>   hex_integer_token
etisserant@0: %type  <leaf> hex_integer
etisserant@0: %token <ID>   real_token
etisserant@0: %type  <leaf> real
etisserant@0: %type  <leaf> signed_real
etisserant@0: /* helper symbol for non_negative_real_literal */
etisserant@0: %type  <leaf> non_negative_signed_real
etisserant@0: %type  <leaf> real_literal
etisserant@0: /* helper symbol for non_negative_numeric_literal */
etisserant@0: %type  <leaf> non_negative_real_literal
etisserant@0: // %type  <leaf> exponent
etisserant@0: %type  <leaf> bit_string_literal
etisserant@0: %type  <leaf> boolean_literal
etisserant@0: 
etisserant@0: %token FALSE
etisserant@0: %token TRUE
etisserant@0: 
etisserant@0: 
etisserant@0: /*******************************/
etisserant@0: /* B 1.2.2 - Character Strings */
etisserant@0: /*******************************/
etisserant@0: %token <ID>   single_byte_character_string_token
etisserant@0: %token <ID>   double_byte_character_string_token
etisserant@0: 
etisserant@0: %type  <leaf> character_string
etisserant@0: %type  <leaf> single_byte_character_string
etisserant@0: %type  <leaf> double_byte_character_string
etisserant@0: 
etisserant@0: 
etisserant@0: /***************************/
etisserant@0: /* B 1.2.3 - Time Literals */
etisserant@0: /***************************/
etisserant@0: %type  <leaf> time_literal
etisserant@0: 
etisserant@0: 
etisserant@0: /************************/
etisserant@0: /* B 1.2.3.1 - Duration */
etisserant@0: /************************/
etisserant@0: %type  <leaf>	duration
etisserant@0: %type  <leaf>	interval
etisserant@0: %type  <leaf>	days
etisserant@0: %type  <leaf>	fixed_point
etisserant@0: %type  <leaf>	hours
etisserant@0: %type  <leaf>	minutes
etisserant@0: %type  <leaf>	seconds
etisserant@0: %type  <leaf>	milliseconds
etisserant@0: 
etisserant@0: %type  <leaf>	integer_d
etisserant@0: %type  <leaf>	integer_h
etisserant@0: %type  <leaf>	integer_m
etisserant@0: %type  <leaf>	integer_s
etisserant@0: %type  <leaf>	integer_ms
etisserant@0: %type  <leaf>	fixed_point_d
etisserant@0: %type  <leaf>	fixed_point_h
etisserant@0: %type  <leaf>	fixed_point_m
etisserant@0: %type  <leaf>	fixed_point_s
etisserant@0: %type  <leaf>	fixed_point_ms
etisserant@0: 
etisserant@0: %token <ID>	fixed_point_token
etisserant@0: %token <ID>	fixed_point_d_token
etisserant@0: %token <ID>	integer_d_token
etisserant@0: %token <ID>	fixed_point_h_token
etisserant@0: %token <ID>	integer_h_token
etisserant@0: %token <ID>	fixed_point_m_token
etisserant@0: %token <ID>	integer_m_token
etisserant@0: %token <ID>	fixed_point_s_token
etisserant@0: %token <ID>	integer_s_token
etisserant@0: %token <ID>	fixed_point_ms_token
etisserant@0: %token <ID>	integer_ms_token
etisserant@0: 
etisserant@0: %token TIME
etisserant@0: %token T_SHARP
etisserant@0: 
etisserant@0: 
etisserant@0: /************************************/
etisserant@0: /* B 1.2.3.2 - Time of day and Date */
etisserant@0: /************************************/
etisserant@0: %type  <leaf>	time_of_day
etisserant@0: %type  <leaf>	daytime
etisserant@0: %type  <leaf>	day_hour
etisserant@0: %type  <leaf>	day_minute
etisserant@0: %type  <leaf>	day_second
etisserant@0: %type  <leaf>	date
etisserant@0: %type  <leaf>	date_literal
etisserant@0: %type  <leaf>	year
etisserant@0: %type  <leaf>	month
etisserant@0: %type  <leaf>	day
etisserant@0: %type  <leaf>	date_and_time
etisserant@0: 
etisserant@0: %token TIME_OF_DAY
etisserant@0: %token DATE
etisserant@0: %token D_SHARP
etisserant@0: %token DATE_AND_TIME
etisserant@0: 
etisserant@0: 
etisserant@0: /**********************/
etisserant@0: /* B 1.3 - Data Types */
etisserant@0: /**********************/
etisserant@0: /* Strangely, the following symbol does seem to be required! */
etisserant@0: // %type  <leaf> data_type_name
etisserant@0: %type  <leaf> non_generic_type_name
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************************/
etisserant@0: /* B 1.3.1 - Elementary Data Types */
etisserant@0: /***********************************/
etisserant@0: /* NOTES:
etisserant@0:  *
etisserant@0:  *    - To make the definition of bit_string_literal more
etisserant@0:  *      concise, it is useful to use an extra non-terminal
etisserant@0:  *      symbol (i.e. a grouping or construct) that groups the
etisserant@0:  *      following elements (BYTE, WORD, DWORD, LWORD).
etisserant@0:  *      Note that the definition of bit_string_type_name
etisserant@0:  *      (according to the spec) includes the above elements
etisserant@0:  *      and an extra BOOL.
etisserant@0:  *      We could use an extra construct with the first four
etisserant@0:  *      elements to be used solely in the definition of
etisserant@0:  *      bit_string_literal, but with the objective of not
etisserant@0:  *      having to replicate the actions (if we ever need
etisserant@0:  *      to change them, they would need to be changed in both
etisserant@0:  *      bit_string_type_name and the extra grouping), we
etisserant@0:  *      have re-defined bit_string_type_name as only including
etisserant@0:  *      the first four elements.
etisserant@0:  *      In order to have our parser implement the specification
etisserant@0:  *      correctly we have augmented every occurence of
etisserant@0:  *      bit_string_type_name in other rules with the BOOL
etisserant@0:  *      token. Since bit_string_type_name only appears in
etisserant@0:  *      the rule for elementary_type_name, this does not
etisserant@0:  *      seem to be a big concession to make!
etisserant@0:  *
etisserant@0:  *    - We have added a helper symbol to concentrate the
etisserant@0:  *      instantiation of STRING and WSTRING into a single
etisserant@0:  *      location (elementary_string_type_name).
etisserant@0:  *      These two elements show up in several other rules,
etisserant@0:  *      but we want to create the equivalent abstract syntax
etisserant@0:  *      in a single location of this file, in order to make
etisserant@0:  *      possible future changes easier to edit...
etisserant@0:  */
etisserant@0: %type  <leaf>	elementary_type_name
etisserant@0: %type  <leaf>	numeric_type_name
etisserant@0: %type  <leaf>	integer_type_name
etisserant@0: %type  <leaf>	signed_integer_type_name
etisserant@0: %type  <leaf>	unsigned_integer_type_name
etisserant@0: %type  <leaf>	real_type_name
etisserant@0: %type  <leaf>	date_type_name
etisserant@0: %type  <leaf>	bit_string_type_name
etisserant@0: /* helper symbol to concentrate the instantiation
etisserant@0:  * of STRING and WSTRING into a single location
etisserant@0:  */
etisserant@0: %type  <leaf>	elementary_string_type_name
etisserant@0: 
etisserant@0: %token BYTE
etisserant@0: %token WORD
etisserant@0: %token DWORD
etisserant@0: %token LWORD
etisserant@0: 
etisserant@0: %token LREAL
etisserant@0: %token REAL
etisserant@0: 
etisserant@0: %token SINT
etisserant@0: %token INT
etisserant@0: %token DINT
etisserant@0: %token LINT
etisserant@0: 
etisserant@0: %token USINT
etisserant@0: %token UINT
etisserant@0: %token UDINT
etisserant@0: %token ULINT
etisserant@0: 
etisserant@0: %token WSTRING
etisserant@0: %token STRING
etisserant@0: %token BOOL
etisserant@0: 
mario@15: // %token TIME
mario@15: // %token DATE
mario@15: // %token DATE_AND_TIME
etisserant@0: %token DT
mario@15: // %token TIME_OF_DAY
etisserant@0: %token TOD
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 1.3.2 - Generic data types */
etisserant@0: /********************************/
etisserant@0: /* Strangely, the following symbol does seem to be required! */
etisserant@0: // %type  <leaf>	generic_type_name
etisserant@0: 
etisserant@0: /* The following tokens do not seem to be used either
etisserant@0:  * but we declare them so they become reserved words...
etisserant@0:  */
etisserant@0: %token ANY
etisserant@0: %token ANY_DERIVED
etisserant@0: %token ANY_ELEMENTARY
etisserant@0: %token ANY_MAGNITUDE
etisserant@0: %token ANY_NUM
etisserant@0: %token ANY_REAL
etisserant@0: %token ANY_INT
etisserant@0: %token ANY_BIT
etisserant@0: %token ANY_STRING
etisserant@0: %token ANY_DATE
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 1.3.3 - Derived data types */
etisserant@0: /********************************/
etisserant@0: %type  <leaf>	derived_type_name
etisserant@0: %type  <leaf>	single_element_type_name
etisserant@0: // %type  <leaf>	simple_type_name
etisserant@0: // %type  <leaf>	subrange_type_name
etisserant@0: // %type  <leaf>	enumerated_type_name
etisserant@0: // %type  <leaf>	array_type_name
etisserant@0: // %type  <leaf>	structure_type_name
etisserant@0: 
etisserant@0: %type  <leaf>	data_type_declaration
etisserant@0: /* helper symbol for data_type_declaration */
etisserant@0: %type  <list>	type_declaration_list
etisserant@0: %type  <leaf>	type_declaration
etisserant@0: %type  <leaf>	single_element_type_declaration
etisserant@0: 
etisserant@0: %type  <leaf>	simple_type_declaration
etisserant@0: %type  <leaf>	simple_spec_init
etisserant@0: %type  <leaf>	simple_specification
etisserant@0: 
etisserant@0: %type  <leaf>	subrange_type_declaration
etisserant@0: %type  <leaf>	subrange_spec_init
etisserant@0: %type  <leaf>	subrange_specification
etisserant@0: %type  <leaf>	subrange
etisserant@0: 
etisserant@0: %type  <leaf>	enumerated_type_declaration
etisserant@0: %type  <leaf>	enumerated_spec_init
etisserant@0: %type  <leaf>	enumerated_specification
etisserant@0: /* helper symbol for enumerated_value */
etisserant@0: %type  <list>	enumerated_value_list
etisserant@0: %type  <leaf>	enumerated_value
mario@13: %type  <leaf>	enumerated_value_without_identifier
etisserant@0: 
etisserant@0: %type  <leaf>	array_type_declaration
etisserant@0: %type  <leaf>	array_spec_init
etisserant@0: %type  <leaf>	array_specification
etisserant@0: /* helper symbol for array_specification */
etisserant@0: %type  <list>	array_subrange_list
etisserant@0: %type  <leaf>	array_initialization
etisserant@0: /* helper symbol for array_initialization */
etisserant@0: %type  <list>	array_initial_elements_list
etisserant@0: %type  <leaf>	array_initial_elements
etisserant@0: %type  <leaf>	array_initial_element
etisserant@0: 
etisserant@0: %type  <leaf>	structure_type_declaration
etisserant@0: %type  <leaf>	structure_specification
etisserant@0: %type  <leaf>	initialized_structure
etisserant@0: %type  <leaf>	structure_declaration
etisserant@0: /* helper symbol for structure_declaration */
etisserant@0: %type  <list>	structure_element_declaration_list
etisserant@0: %type  <leaf>	structure_element_declaration
etisserant@0: %type  <leaf>	structure_element_name
etisserant@0: %type  <leaf>	structure_initialization
etisserant@0: /* helper symbol for structure_initialization */
etisserant@0: %type  <list>	structure_element_initialization_list
etisserant@0: %type  <leaf>	structure_element_initialization
etisserant@0: 
etisserant@0: //%type  <leaf>	string_type_name
etisserant@0: %type  <leaf>	string_type_declaration
etisserant@0: /* helper symbol for string_type_declaration */
etisserant@0: %type  <leaf>	string_type_declaration_size
etisserant@0: /* helper symbol for string_type_declaration */
etisserant@0: %type  <leaf>	string_type_declaration_init
etisserant@0: 
etisserant@0: %token ASSIGN
etisserant@0: %token DOTDOT  /* ".." */
etisserant@0: %token TYPE
etisserant@0: %token END_TYPE
etisserant@0: %token ARRAY
etisserant@0: %token OF
etisserant@0: %token STRUCT
etisserant@0: %token END_STRUCT
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*********************/
etisserant@0: /* B 1.4 - Variables */
etisserant@0: /*********************/
etisserant@0: %type  <leaf>	variable
etisserant@0: %type  <leaf>	symbolic_variable
etisserant@0: /* helper symbol for prog_cnxn */
etisserant@0: %type  <leaf>	any_symbolic_variable
etisserant@0: %type  <leaf>	variable_name
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************************/
etisserant@0: /* B.1.4.1   Directly Represented Variables */
etisserant@0: /********************************************/
etisserant@0: /* Done totally within flex...
etisserant@0:  location_prefix
etisserant@0:  size_prefix
etisserant@0: */
etisserant@0: %token <ID>	direct_variable_token
etisserant@0: %type  <leaf>	direct_variable
etisserant@0: 
etisserant@0: 
etisserant@0: /*************************************/
etisserant@0: /* B.1.4.2   Multi-element Variables */
etisserant@0: /*************************************/
etisserant@0: %type  <leaf>	multi_element_variable
etisserant@0: /* helper symbol for any_symbolic_variable */
etisserant@0: %type  <leaf>	any_multi_element_variable
etisserant@0: %type  <leaf>	array_variable
etisserant@0: /* helper symbol for any_symbolic_variable */
etisserant@0: %type  <leaf>	any_array_variable
etisserant@0: %type  <leaf>	subscripted_variable
etisserant@0: /* helper symbol for any_symbolic_variable */
etisserant@0: %type  <leaf>	any_subscripted_variable
etisserant@0: %type  <list>	subscript_list
etisserant@0: %type  <leaf>	subscript
etisserant@0: %type  <leaf>	structured_variable
etisserant@0: /* helper symbol for any_symbolic_variable */
etisserant@0: %type  <leaf>	any_structured_variable
etisserant@0: %type  <leaf>	record_variable
etisserant@0: /* helper symbol for any_symbolic_variable */
etisserant@0: %type  <leaf>	any_record_variable
etisserant@0: %type  <leaf>	field_selector
etisserant@0: 
etisserant@0: 
etisserant@0: /******************************************/
etisserant@0: /* B 1.4.3 - Declaration & Initialisation */
etisserant@0: /******************************************/
etisserant@0: %type  <leaf>	input_declarations
etisserant@0: /* helper symbol for input_declarations */
etisserant@0: %type  <list>	input_declaration_list
etisserant@0: %type  <leaf>	input_declaration
etisserant@0: %type  <leaf>	edge_declaration
etisserant@0: %type  <leaf>	var_init_decl
etisserant@0: %type  <leaf>	var1_init_decl
etisserant@0: %type  <list>	var1_list
etisserant@0: %type  <leaf>	array_var_init_decl
etisserant@0: %type  <leaf>	structured_var_init_decl
etisserant@0: %type  <leaf>	fb_name_decl
etisserant@0: /* helper symbol for fb_name_decl */
etisserant@0: %type  <list>	fb_name_list_with_colon
etisserant@0: /* helper symbol for fb_name_list_with_colon */
etisserant@0: %type  <list>	var1_list_with_colon
etisserant@0: // %type  <list>	fb_name_list
etisserant@0: // %type  <leaf>	fb_name
etisserant@0: %type  <leaf>	output_declarations
etisserant@0: %type  <leaf>	input_output_declarations
etisserant@0: /* helper symbol for input_output_declarations */
etisserant@0: %type  <list>	var_declaration_list
etisserant@0: %type  <leaf>	var_declaration
etisserant@0: %type  <leaf>	temp_var_decl
etisserant@0: %type  <leaf>	var1_declaration
etisserant@0: %type  <leaf>	array_var_declaration
etisserant@0: %type  <leaf>	structured_var_declaration
etisserant@0: %type  <leaf>	var_declarations
etisserant@0: %type  <leaf>	retentive_var_declarations
etisserant@0: %type  <leaf>	located_var_declarations
etisserant@0: /* helper symbol for located_var_declarations */
etisserant@0: %type  <list>	located_var_decl_list
etisserant@0: %type  <leaf>	located_var_decl
etisserant@0: %type  <leaf>	external_var_declarations
etisserant@0: /* helper symbol for external_var_declarations */
etisserant@0: %type  <list>	external_declaration_list
etisserant@0: %type  <leaf>	external_declaration
etisserant@0: %type  <leaf>	global_var_name
etisserant@0: %type  <leaf>	global_var_declarations
etisserant@0: /* helper symbol for global_var_declarations */
etisserant@0: %type  <list>	global_var_decl_list
etisserant@0: %type  <leaf>	global_var_decl
etisserant@0: %type  <leaf>	global_var_spec
etisserant@0: %type  <leaf>	located_var_spec_init
etisserant@0: %type  <leaf>	location
etisserant@0: %type  <list>	global_var_list
etisserant@0: %type  <leaf>	string_var_declaration
etisserant@0: %type  <leaf>	single_byte_string_var_declaration
etisserant@0: %type  <leaf>	single_byte_string_spec
etisserant@0: %type  <leaf>	double_byte_string_var_declaration
etisserant@0: %type  <leaf>	double_byte_string_spec
etisserant@0: %type  <leaf>	incompl_located_var_declarations
etisserant@0: /* helper symbol for incompl_located_var_declarations */
etisserant@0: %type  <list>	incompl_located_var_decl_list
etisserant@0: %type  <leaf>	incompl_located_var_decl
etisserant@0: %type  <leaf>	incompl_location
etisserant@0: %type  <leaf>	var_spec
etisserant@0: /* helper symbol for var_spec */
etisserant@0: %type  <leaf>	string_spec
etisserant@0: /* intermediate helper symbol for:
etisserant@0:  *  - non_retentive_var_decls
etisserant@0:  *  - output_declarations
etisserant@0:  */
etisserant@0: %type  <list>	var_init_decl_list
etisserant@0: 
etisserant@0: %token  <ID>	incompl_location_token
etisserant@0: 
etisserant@0: %token VAR_INPUT
etisserant@0: %token VAR_OUTPUT
etisserant@0: %token VAR_IN_OUT
etisserant@0: %token VAR_EXTERNAL
etisserant@0: %token VAR_GLOBAL
etisserant@0: %token END_VAR
etisserant@0: %token RETAIN
etisserant@0: %token NON_RETAIN
etisserant@0: %token R_EDGE
etisserant@0: %token F_EDGE
etisserant@0: %token AT
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************/
etisserant@0: /* B 1.5.1 - Functions */
etisserant@0: /***********************/
etisserant@0: //%type  <leaf>	function_name
etisserant@0: /* helper symbol for IL language */
etisserant@0: %type  <leaf>	function_name_no_clashes
etisserant@0: %type  <leaf>	function_name_simpleop_clashes
etisserant@0: //%type  <leaf>	function_name_expression_clashes
etisserant@0: /* helper symbols for ST language */
etisserant@0: //%type  <leaf>	function_name_NOT_clashes
etisserant@0: %type  <leaf>	function_name_no_NOT_clashes
etisserant@0: 
etisserant@0: //%type  <leaf>	standard_function_name
etisserant@0: /* helper symbols for IL language */
etisserant@0: %type  <leaf>	standard_function_name_no_clashes
etisserant@0: %type  <leaf>	standard_function_name_simpleop_clashes
etisserant@0: %type  <leaf>	standard_function_name_expression_clashes
etisserant@0: /* helper symbols for ST language */
etisserant@0: %type  <leaf>	standard_function_name_NOT_clashes
etisserant@0: %type  <leaf>	standard_function_name_no_NOT_clashes
etisserant@0: 
etisserant@0: %type  <leaf>	derived_function_name
etisserant@0: %type  <leaf>	function_declaration
etisserant@0: /* helper symbol for function_declaration */
etisserant@0: %type  <leaf>	function_name_declaration
etisserant@0: %type  <leaf>	io_var_declarations
etisserant@0: %type  <leaf>	function_var_decls
etisserant@0: %type  <leaf>	function_body
etisserant@0: %type  <leaf>	var2_init_decl
etisserant@0: /* intermediate helper symbol for function_declaration */
etisserant@0: %type  <list>	io_OR_function_var_declarations_list
etisserant@0: /* intermediate helper symbol for function_var_decls */
etisserant@0: %type  <list>	var2_init_decl_list
etisserant@0: 
etisserant@0: %token <ID>	standard_function_name_token
etisserant@0: 
etisserant@0: %token FUNCTION
etisserant@0: %token END_FUNCTION
etisserant@0: %token CONSTANT
etisserant@0: 
etisserant@0: 
etisserant@0: /*****************************/
etisserant@0: /* B 1.5.2 - Function Blocks */
etisserant@0: /*****************************/
etisserant@0: %type  <leaf>	function_block_type_name
etisserant@0: %type  <leaf>	standard_function_block_name
etisserant@0: %type  <leaf>	derived_function_block_name
etisserant@0: %type  <leaf>	function_block_declaration
etisserant@0: %type  <leaf>	other_var_declarations
etisserant@0: %type  <leaf>	temp_var_decls
etisserant@0: %type  <leaf>	non_retentive_var_decls
etisserant@0: %type  <leaf>	function_block_body
etisserant@0: /* intermediate helper symbol for function_declaration */
etisserant@0: %type  <list>	io_OR_other_var_declarations_list
etisserant@0: /* intermediate helper symbol for temp_var_decls */
etisserant@0: %type  <list>	temp_var_decls_list
etisserant@0: 
etisserant@0: %token <ID>	standard_function_block_name_token
etisserant@0: 
etisserant@0: %token FUNCTION_BLOCK
etisserant@0: %token END_FUNCTION_BLOCK
etisserant@0: %token VAR_TEMP
mario@15: // %token END_VAR
etisserant@0: %token VAR
mario@15: // %token NON_RETAIN
mario@15: // %token END_VAR
etisserant@0: 
etisserant@0: 
etisserant@0: /**********************/
etisserant@0: /* B 1.5.3 - Programs */
etisserant@0: /**********************/
etisserant@0: %type  <leaf>	program_type_name
etisserant@0: %type  <leaf>	program_declaration
etisserant@0: /* helper symbol for program_declaration */
etisserant@0: %type  <list>	program_var_declarations_list
etisserant@0: 
etisserant@0: %token PROGRAM
etisserant@0: %token END_PROGRAM
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************************/
etisserant@0: /* B 1.6 Sequential Function Chart elements */
etisserant@0: /********************************************/
etisserant@1: 
etisserant@0: %type  <list>	sequential_function_chart
etisserant@1: %type  <list>	sfc_network
etisserant@0: %type  <leaf>	initial_step
etisserant@0: %type  <leaf>	step
etisserant@1: %type  <list>	action_association_list
etisserant@0: %type  <leaf>	step_name
etisserant@0: %type  <leaf>	action_association
etisserant@1: /* helper symbol for action_association */
etisserant@0: %type  <list>	indicator_name_list
etisserant@0: %type  <leaf>	action_name
etisserant@0: %type  <leaf>	action_qualifier
etisserant@1: %type  <leaf>	qualifier
etisserant@0: %type  <leaf>	timed_qualifier
etisserant@0: %type  <leaf>	action_time
etisserant@0: %type  <leaf>	indicator_name
etisserant@0: %type  <leaf>	transition
etisserant@0: %type  <leaf>	steps
etisserant@0: %type  <list>	step_name_list
lbessard@3: %type  <tmp_symbol> transition_header
lbessard@3: %type  <leaf>	transition_condition_il
lbessard@3: %type  <leaf>	transition_condition_st
lbessard@3: %type  <tmp_symbol> action_header
etisserant@0: %type  <leaf>	action
etisserant@1: %type  <leaf>	transition_name
etisserant@1: 
etisserant@0: 
mario@15: // %token ASSIGN
etisserant@0: %token ACTION
etisserant@0: %token END_ACTION
etisserant@0: 
etisserant@0: %token TRANSITION
etisserant@0: %token END_TRANSITION
etisserant@0: %token FROM
etisserant@0: %token TO
etisserant@0: %token PRIORITY
etisserant@0: 
etisserant@0: %token INITIAL_STEP
etisserant@0: %token STEP
etisserant@0: %token END_STEP
etisserant@0: 
etisserant@0: %token L
etisserant@0: %token D
etisserant@0: %token SD
etisserant@0: %token DS
etisserant@0: %token SL
etisserant@0: 
etisserant@0: %token N
etisserant@0: %token P
etisserant@0: /* NOTE: the following two clash with the R and S IL operators.
etisserant@0:  * It will have to be handled when we include parsing of SFC...
etisserant@0:  */
etisserant@0: /*
etisserant@0: %token R
etisserant@0: %token S
etisserant@0: */
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 1.7 Configuration elements */
etisserant@0: /********************************/
etisserant@0: %type  <leaf>	configuration_name
etisserant@0: %type  <leaf>	resource_type_name
etisserant@0: %type  <leaf>	configuration_declaration
etisserant@0: // helper symbol for
etisserant@0: //  - configuration_declaration
etisserant@0: //  - resource_declaration
etisserant@0: //
etisserant@0: %type  <leaf>	optional_global_var_declarations
etisserant@0: // helper symbol for configuration_declaration
etisserant@0: %type  <leaf>	optional_access_declarations
etisserant@0: // helper symbol for configuration_declaration
etisserant@0: %type  <leaf>	optional_instance_specific_initializations
etisserant@0: // helper symbol for configuration_declaration
etisserant@0: %type  <list>	resource_declaration_list
etisserant@0: %type  <leaf>	resource_declaration
etisserant@0: %type  <leaf>	single_resource_declaration
etisserant@0: // helper symbol for single_resource_declaration
etisserant@0: %type  <list>	task_configuration_list
etisserant@0: // helper symbol for single_resource_declaration
etisserant@0: %type  <list>	program_configuration_list
etisserant@0: %type  <leaf>	resource_name
etisserant@0: // %type  <leaf>	access_declarations
etisserant@0: // helper symbol for access_declarations
etisserant@0: // %type  <leaf>	access_declaration_list
etisserant@0: // %type  <leaf>	access_declaration
etisserant@0: // %type  <leaf>	access_path
etisserant@0: // helper symbol for access_path
etisserant@0: %type  <list>	any_fb_name_list
etisserant@0: %type  <leaf>	global_var_reference
etisserant@0: // %type  <leaf>	access_name
etisserant@0: %type  <leaf>	program_output_reference
etisserant@0: %type  <leaf>	program_name
etisserant@0: // %type  <leaf>	direction
etisserant@0: %type  <leaf>	task_configuration
etisserant@0: %type  <leaf>	task_name
etisserant@0: %type  <leaf>	task_initialization
etisserant@0: %type  <leaf>	data_source
etisserant@0: %type  <leaf>	program_configuration
etisserant@0: // helper symbol for program_configuration
etisserant@0: %type  <leaf>	optional_task_name
etisserant@0: // helper symbol for program_configuration
etisserant@0: %type  <leaf>	optional_prog_conf_elements
etisserant@0: %type  <list>	prog_conf_elements
etisserant@0: %type  <leaf>	prog_conf_element
etisserant@0: %type  <leaf>	fb_task
etisserant@0: %type  <leaf>	prog_cnxn
etisserant@0: %type  <leaf>	prog_data_source
etisserant@0: %type  <leaf>	data_sink
etisserant@0: %type  <leaf>	instance_specific_initializations
etisserant@0: // helper symbol for instance_specific_initializations
etisserant@0: %type  <list>	instance_specific_init_list
etisserant@0: %type  <leaf>	instance_specific_init
etisserant@0: // helper symbol for instance_specific_init
etisserant@0: %type  <leaf>	fb_initialization
etisserant@0: 
etisserant@0: %type  <leaf>	prev_declared_global_var_name
etisserant@0: %token  <ID>	prev_declared_global_var_name_token
etisserant@0: 
etisserant@0: %type  <leaf>	prev_declared_program_name
etisserant@0: %token  <ID>	prev_declared_program_name_token
etisserant@0: 
etisserant@0: %type  <leaf>	prev_declared_resource_name
etisserant@0: %token  <ID>	prev_declared_resource_name_token
etisserant@0: 
etisserant@0: %token  <ID>	prev_declared_configuration_name_token
etisserant@0: 
etisserant@0: // %type  <leaf>	prev_declared_task_name
etisserant@0: // %token  <ID>	prev_declared_task_name_token
etisserant@0: 
etisserant@0: %token CONFIGURATION
etisserant@0: %token END_CONFIGURATION
etisserant@0: %token TASK
etisserant@0: %token RESOURCE
etisserant@0: %token ON
etisserant@0: %token END_RESOURCE
etisserant@0: %token VAR_CONFIG
etisserant@0: %token VAR_ACCESS
mario@15: // %token END_VAR
etisserant@0: %token WITH
mario@15: // %token PROGRAM
mario@15: // %token RETAIN
mario@15: // %token NON_RETAIN
mario@15: // %token PRIORITY
etisserant@0: %token SINGLE
etisserant@0: %token INTERVAL
etisserant@0: %token READ_WRITE
etisserant@0: %token READ_ONLY
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************************/
etisserant@0: /* B 2.1 Instructions and Operands */
etisserant@0: /***********************************/
etisserant@0: %type  <list>	instruction_list
etisserant@0: %type  <leaf>	il_instruction
etisserant@0: %type  <leaf>	il_incomplete_instruction
etisserant@0: %type  <leaf>	label
etisserant@0: %type  <leaf>	il_simple_operation
etisserant@0: // helper symbol for il_simple_operation
lbessard@3: %type <tmp_symbol> il_simple_operator_clash_il_operand
etisserant@0: %type  <leaf>	il_expression
etisserant@0: %type  <leaf>	il_jump_operation
etisserant@0: %type  <leaf>	il_fb_call
etisserant@0: %type  <leaf>	il_formal_funct_call
etisserant@0: // helper symbol for il_formal_funct_call
etisserant@0: %type  <leaf> il_expr_operator_clash_eol_list
etisserant@0: %type  <leaf>	il_operand
etisserant@0: %type  <list>	il_operand_list
etisserant@0: %type  <list>	simple_instr_list
etisserant@0: %type  <leaf>	il_simple_instruction
etisserant@0: %type  <list>	il_param_list
etisserant@0: %type  <list>	il_param_instruction_list
etisserant@0: %type  <leaf>	il_param_instruction
etisserant@0: %type  <leaf>	il_param_last_instruction
etisserant@0: %type  <leaf>	il_param_assignment
etisserant@0: %type  <leaf>	il_param_out_assignment
etisserant@0: 
etisserant@0: %token EOL
etisserant@0: 
etisserant@0: 
etisserant@0: /*******************/
etisserant@0: /* B 2.2 Operators */
etisserant@0: /*******************/
etisserant@0: %token <ID>	sendto_identifier_token
etisserant@0: %type  <leaf>	sendto_identifier
etisserant@0: 
etisserant@0: %type  <leaf>	LD_operator
etisserant@0: %type  <leaf>	LDN_operator
etisserant@0: %type  <leaf>	ST_operator
etisserant@0: %type  <leaf>	STN_operator
etisserant@0: %type  <leaf>	NOT_operator
etisserant@0: %type  <leaf>	S_operator
etisserant@0: %type  <leaf>	R_operator
etisserant@0: %type  <leaf>	S1_operator
etisserant@0: %type  <leaf>	R1_operator
etisserant@0: %type  <leaf>	CLK_operator
etisserant@0: %type  <leaf>	CU_operator
etisserant@0: %type  <leaf>	CD_operator
etisserant@0: %type  <leaf>	PV_operator
etisserant@0: %type  <leaf>	IN_operator
etisserant@0: %type  <leaf>	PT_operator
etisserant@0: %type  <leaf>	AND_operator
etisserant@0: %type  <leaf>	AND2_operator
etisserant@0: %type  <leaf>	OR_operator
etisserant@0: %type  <leaf>	XOR_operator
etisserant@0: %type  <leaf>	ANDN_operator
etisserant@0: %type  <leaf>	ANDN2_operator
etisserant@0: %type  <leaf>	ORN_operator
etisserant@0: %type  <leaf>	XORN_operator
etisserant@0: %type  <leaf>	ADD_operator
etisserant@0: %type  <leaf>	SUB_operator
etisserant@0: %type  <leaf>	MUL_operator
etisserant@0: %type  <leaf>	DIV_operator
etisserant@0: %type  <leaf>	MOD_operator
etisserant@0: %type  <leaf>	GT_operator
etisserant@0: %type  <leaf>	GE_operator
etisserant@0: %type  <leaf>	EQ_operator
etisserant@0: %type  <leaf>	LT_operator
etisserant@0: %type  <leaf>	LE_operator
etisserant@0: %type  <leaf>	NE_operator
etisserant@0: %type  <leaf>	CAL_operator
etisserant@0: %type  <leaf>	CALC_operator
etisserant@0: %type  <leaf>	CALCN_operator
etisserant@0: %type  <leaf>	RET_operator
etisserant@0: %type  <leaf>	RETC_operator
etisserant@0: %type  <leaf>	RETCN_operator
etisserant@0: %type  <leaf>	JMP_operator
etisserant@0: %type  <leaf>	JMPC_operator
etisserant@0: %type  <leaf>	JMPCN_operator
etisserant@0: 
etisserant@0: %type  <leaf>	il_simple_operator
etisserant@0: %type  <leaf>	il_simple_operator_clash
etisserant@0: %type  <leaf>	il_simple_operator_clash1
etisserant@0: %type  <leaf>	il_simple_operator_clash2
etisserant@0: %type  <leaf>	il_simple_operator_noclash
etisserant@0: 
etisserant@0: //%type  <leaf>	il_expr_operator
etisserant@0: %type  <leaf>	il_expr_operator_clash
etisserant@0: %type  <leaf>	il_expr_operator_noclash
etisserant@0: 
etisserant@0: %type  <leaf>	il_assign_operator
etisserant@0: %type  <leaf>	il_assign_out_operator
etisserant@0: %type  <leaf>	il_call_operator
etisserant@0: %type  <leaf>	il_return_operator
etisserant@0: %type  <leaf>	il_jump_operator
etisserant@0: 
etisserant@0: 
etisserant@0: %token LD
etisserant@0: %token LDN
etisserant@0: %token ST
etisserant@0: %token STN
etisserant@0: %token NOT
etisserant@0: %token S
etisserant@0: %token R
etisserant@0: %token S1
etisserant@0: %token R1
etisserant@0: %token CLK
etisserant@0: %token CU
etisserant@0: %token CD
etisserant@0: %token PV
etisserant@0: %token IN
etisserant@0: %token PT
etisserant@0: %token AND
etisserant@0: %token AND2  /* character '&' in the source code*/
etisserant@0: %token OR
etisserant@0: %token XOR
etisserant@0: %token ANDN
etisserant@0: %token ANDN2 /* characters '&N' in the source code */
etisserant@0: %token ORN
etisserant@0: %token XORN
etisserant@0: %token ADD
etisserant@0: %token SUB
etisserant@0: %token MUL
etisserant@0: %token DIV
etisserant@0: %token MOD
etisserant@0: %token GT
etisserant@0: %token GE
etisserant@0: %token EQ
etisserant@0: %token LT
etisserant@0: %token LE
etisserant@0: %token NE
etisserant@0: %token CAL
etisserant@0: %token CALC
etisserant@0: %token CALCN
etisserant@0: %token RET
etisserant@0: %token RETC
etisserant@0: %token RETCN
etisserant@0: %token JMP
etisserant@0: %token JMPC
etisserant@0: %token JMPCN
etisserant@0: 
etisserant@0: %token SENDTO   /* "=>" */
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************/
etisserant@0: /* B 3.1 - Expressions */
etisserant@0: /***********************/
etisserant@0: /* NOTE:
etisserant@0:  *
etisserant@0:  *    - unary_operator, multiply_operator,
etisserant@0:  *      add_operator and comparison_operator
etisserant@0:  *      are not required. Their values are integrated
etisserant@0:  *      directly into other rules...
etisserant@0:  */
etisserant@0: %type  <leaf>	expression
etisserant@0: %type  <leaf>	xor_expression
etisserant@0: %type  <leaf>	and_expression
etisserant@0: %type  <leaf>	comparison
etisserant@0: %type  <leaf>	equ_expression
etisserant@0: // %type  <leaf>	comparison_operator
etisserant@0: %type  <leaf>	add_expression
etisserant@0: // %type  <leaf>	add_operator
etisserant@0: %type  <leaf>	term
etisserant@0: // %type  <leaf>	multiply_operator
etisserant@0: %type  <leaf>	power_expression
etisserant@0: %type  <leaf>	unary_expression
etisserant@0: // %type  <leaf>	unary_operator
etisserant@0: %type  <leaf>	primary_expression
etisserant@0: /* intermediate helper symbol for primary_expression */
etisserant@0: %type  <leaf>	function_invocation
etisserant@0: 
mario@15: // %token AND
mario@15: // %token XOR
mario@15: // %token OR
mario@15: // %token MOD
mario@15: // %token NOT
etisserant@0: %token OPER_NE
etisserant@0: %token OPER_GE
etisserant@0: %token OPER_LE
etisserant@0: %token OPER_EXP
etisserant@0: 
etisserant@0: 
etisserant@0: /********************/
etisserant@0: /* B 3.2 Statements */
etisserant@0: /********************/
etisserant@0: %type <list> statement_list
etisserant@0: %type <leaf> statement
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*********************************/
etisserant@0: /* B 3.2.1 Assignment Statements */
etisserant@0: /*********************************/
etisserant@0: %type <leaf> assignment_statement
mario@15: // %token ASSIGN   /* ":=" */
etisserant@0: 
etisserant@0: 
etisserant@0: /*****************************************/
etisserant@0: /* B 3.2.2 Subprogram Control Statements */
etisserant@0: /*****************************************/
etisserant@0: %type <leaf>	subprogram_control_statement
etisserant@0: %type <leaf>	return_statement
etisserant@0: %type <leaf>	fb_invocation
etisserant@0: %type <leaf>	param_assignment
etisserant@0: /* helper symbol for fb_invocation */
etisserant@0: %type <list> param_assignment_list
etisserant@0: 
mario@15: // %token ASSIGN
mario@15: // %token SENDTO   /* "=>" */
etisserant@0: %token RETURN
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 3.2.3 Selection Statements */
etisserant@0: /********************************/
etisserant@0: %type <leaf>	selection_statement
etisserant@0: %type <leaf>	if_statement
etisserant@0: %type <leaf>	case_statement
etisserant@0: %type <leaf>	case_element
etisserant@0: %type <list>	case_list
etisserant@0: %type <leaf>	case_list_element
etisserant@0: /* helper symbol for if_statement */
etisserant@0: %type <list>	elseif_statement_list
etisserant@0: /* helper symbol for elseif_statement_list */
etisserant@0: %type <leaf>	elseif_statement
etisserant@0: /* helper symbol for case_statement */
etisserant@0: %type <list>	case_element_list
etisserant@0: 
etisserant@0: %token IF
etisserant@0: %token THEN
etisserant@0: %token ELSIF
etisserant@0: %token ELSE
etisserant@0: %token END_IF
etisserant@0: 
etisserant@0: %token CASE
mario@15: // %token OF
mario@15: // %token ELSE
etisserant@0: %token END_CASE
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 3.2.4 Iteration Statements */
etisserant@0: /********************************/
etisserant@0: %type <leaf>	iteration_statement
etisserant@0: %type <leaf>	for_statement
etisserant@0: %type <leaf>	control_variable
etisserant@0: %type <leaf>	while_statement
etisserant@0: %type <leaf>	repeat_statement
etisserant@0: %type <leaf>	exit_statement
etisserant@0: /* Integrated directly into for_statement */
etisserant@0: // %type <leaf>	for_list
etisserant@0: 
etisserant@0: %token FOR
mario@15: // %token ASSIGN
mario@15: // %token TO
etisserant@0: %token BY
etisserant@0: %token DO
etisserant@0: %token END_FOR
etisserant@0: 
etisserant@0: %token WHILE
mario@15: // %token DO
etisserant@0: %token END_WHILE
etisserant@0: 
etisserant@0: %token REPEAT
etisserant@0: %token UNTIL
etisserant@0: %token END_REPEAT
etisserant@0: 
etisserant@0: %token EXIT
etisserant@0: 
etisserant@0: %%
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: /********************************************************/
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*****************************/
etisserant@0: /* Prelimenary constructs... */
etisserant@0: /*****************************/
etisserant@0: start:
etisserant@0:   library	{$$ = $1;}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* the pragmas... */
etisserant@0: pragma:
etisserant@0:   pragma_token	{$$ = new pragma_c($1);}
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE:
etisserant@0:  *       short version:
etisserant@0:  *       identifier is used for previously undeclared identifiers
etisserant@0:  *       any_identifier is used when any identifier, previously
etisserant@0:  *       declared or not, is required in the syntax.
etisserant@0:  *
etisserant@0:  *       long version:
etisserant@0:  *       When flex comes across an identifier, it first
etisserant@0:  *       searches through the currently declared variables,
etisserant@0:  *       functions, types, etc... to determine if it has
etisserant@0:  *       been previously declared.
etisserant@0:  *       Only if the identifier has not yet been declared
etisserant@0:  *       will it return an identifier_token (later turned into
etisserant@0:  *       an identifier symbol by the bison generated syntax parser).
etisserant@0:  *
etisserant@0:  *       Some constructs in the syntax, such as when calling
etisserant@0:  *       a function 'F(var1 := 1; var2 := 2);', will accept _any_
etisserant@0:  *       identifier in 'var1', even if it has been previously
etisserant@0:  *       declared in the current scope, since var1 belongs to
etisserant@0:  *       another scope (the variables declared in function F).
etisserant@0:  *
etisserant@0:  *       For the above reason, we need to define the symbol
etisserant@0:  *       any_identifier. All the symbols that may become an
etisserant@0:  *       any_identifier are expected to be stored in the
etisserant@0:  *       abstract syntax as a identifier_c
etisserant@0:  */
etisserant@0: /* NOTE:
etisserant@0:  *  Type names, function names, function block type names and
etisserant@0:  *  program type names are considerd keywords once they are defined,
etisserant@0:  *  so may no longer be used for variable names!
etisserant@0:  *  BUT the spec is confusing on this issue, as it is not clear when
etisserant@0:  *  a function name should be considered as defined. If it is to be
etisserant@0:  *  considered defined only from the location from where it is declared
etisserant@0:  *  and onwards, it means that before it is declared its name may be
etisserant@0:  *  used for variable names!
etisserant@0:  *  This means that we must allow names previously used for functions
etisserant@0:  *  (et. al.) to also constitue an any_identifier!
etisserant@0:  */
etisserant@0: any_identifier:
etisserant@0:   identifier
etisserant@0: | prev_declared_fb_name
etisserant@0: | prev_declared_variable_name
etisserant@0: /**/
etisserant@0: | prev_declared_enumerated_type_name
etisserant@0: | prev_declared_simple_type_name
etisserant@0: | prev_declared_subrange_type_name
etisserant@0: | prev_declared_array_type_name
etisserant@0: | prev_declared_structure_type_name
etisserant@0: | prev_declared_string_type_name
etisserant@0: | prev_declared_derived_function_name
etisserant@0: | prev_declared_derived_function_block_name
etisserant@0: | prev_declared_program_type_name
etisserant@0: /**/
etisserant@0: | prev_declared_resource_name
etisserant@0: | prev_declared_program_name
etisserant@0: | prev_declared_global_var_name
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: prev_declared_variable_name: prev_declared_variable_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_fb_name: prev_declared_fb_name_token {$$ = new identifier_c($1);};
etisserant@0: 
etisserant@0: prev_declared_simple_type_name: prev_declared_simple_type_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_subrange_type_name: prev_declared_subrange_type_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_array_type_name: prev_declared_array_type_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_structure_type_name: prev_declared_structure_type_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_string_type_name: prev_declared_string_type_name_token {$$ = new identifier_c($1);};
etisserant@0: 
etisserant@0: prev_declared_derived_function_name: prev_declared_derived_function_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_program_type_name: prev_declared_program_type_name_token {$$ = new identifier_c($1);};
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /***************************/
etisserant@0: /* B 0 - Programming Model */
etisserant@0: /***************************/
etisserant@0: library:
etisserant@0:   /* empty */
etisserant@0: 	{if (tree_root == NULL)
etisserant@0: 	  tree_root = new library_c();
etisserant@0: 	 $$ = (list_c *)tree_root;
etisserant@0: 	}
etisserant@0: | library library_element_declaration
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | library error
etisserant@0: 	{$$ = NULL;
etisserant@0: 	 print_err_msg(current_filename, @2.last_line, "unknown error.");
etisserant@0: 	 /* yychar */
etisserant@0: 	 yyerrok;
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: library_element_declaration:
etisserant@0:   data_type_declaration
etisserant@0: | function_declaration
etisserant@0: | function_block_declaration
etisserant@0: | program_declaration
etisserant@0: | configuration_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*******************************************/
etisserant@0: /* B 1.1 - Letters, digits and identifiers */
etisserant@0: /*******************************************/
etisserant@0: /* NOTE: the spec defines identifier as:
etisserant@0:  *         identifier ::= (letter|('_' (letter|digit))) {['_'] (letter|digit)}
etisserant@0:  *       In essence, any sequence of letters or digits, starting with a letter
etisserant@0:  *       or '_'.
etisserant@0:  *
etisserant@0:  *       On section 2.1.3 (pg 26) , the spec states
etisserant@0:  *       "The keywords listed in annex C shall not be used for any other purpose,
etisserant@0:  *         e.g., variable names or extensions as defined in 1.5.1."
etisserant@0:  *       (NOTE: the spec itself does not follow this rule, as it defines standard
etisserant@0:  *       functions with names identidal to keywords, e.g. 'MOD', 'NOT' !!. This is
etisserant@0:  *       another issue altogether, and is worked around somewhere else...)
etisserant@0:  *
etisserant@0:  *       This means that we must re-define indentifier so as to exclude
etisserant@0:  *       any keywords defined in annex C.
etisserant@0:  *
etisserant@0:  *       Note also that the list includes
etisserant@0:  *          - Data type names
etisserant@0:  *          - Function names
etisserant@0:  *          - Function Block names
etisserant@0:  *       This means that any named used for a function name, data type name
etisserant@0:  *       or function block name, essentially becomes a keyword, and may therefore
etisserant@0:  *       no longer be re-used for any other use! (see NOTE 2)
etisserant@0:  *
etisserant@0:  *       In our case, excluding the keywords is achieved in the lexical parser,
etisserant@0:  *       by two mechanisms:
etisserant@0:  *         (1) giving higher priority to the keywords (tokens) than to identifiers,
etisserant@0:  *             so when the lexical parser finds a keyword it will be parsed as a
etisserant@0:  *             token before being parsed as an identifier.
etisserant@0:  *         (2) when an identifier is found that is not a keyword, the lexical parser
etisserant@0:  *             then looks in the global symbol table, and will not return an identifier
etisserant@0:  *             if the name has been previously used as a data type name, function name,
etisserant@0:  *             or function block name! (In these cases it will return a
etisserant@0:  *             prev_declared_function_name_token, etc...).
etisserant@0:  *
etisserant@0:  *       Unfortunately, the language (especially IL) uses tokens that are
etisserant@0:  *       not defined as keywords in the spec (e.g. 'IN', 'R1', 'S1', 'PT', etc...)!
etisserant@0:  *       This means that it is valid to name a function 'IN', a variable 'PT', etc...
etisserant@0:  *       BUT, the lexical parser will interpret these names as tokens (keywords).
etisserant@0:  *       To allow these names to be used as function names, variable names, etc...,
etisserant@0:  *       I (Mario) have augmented the definition of identifier to also include the tokens
etisserant@0:  *       that are not explicitly defined as keywords in the spec!!
etisserant@0:  *
etisserant@0:  *
etisserant@0:  *
etisserant@0:  *
etisserant@0:  * NOTE 2:
etisserant@0:  *         I (Mario) find it strange that the writers of the spec really want
etisserant@0:  *         names previously used for function names, data type names or function
etisserant@0:  *         block names, to become full fledged keywords. I understand that they
etisserant@0:  *         do not want these names being used as variable names, but how about
etisserant@0:  *         enumeration values? How about structure element names?
etisserant@0:  *         If we interpret the spec literally, these would not be accepted,
etisserant@0:  *         which would probably burden the programmer quite a bit, in making sure
etisserant@0:  *         all these name don't clash!
etisserant@0:  *
etisserant@0:  *
etisserant@0:  *
etisserant@0:  * NOTE 3: The keywords, as specified in Annex C are...
etisserant@0:  *
etisserant@0:  *          - Data type names
etisserant@0:  *          - Function names
etisserant@0:  *          - Function Block names
etisserant@0:  *          - ACTION...END_ACTION
etisserant@0:  *          - ARRAY...OF
etisserant@0:  *          - AT
etisserant@0:  *          - CASE...OF...ELSE...END_CASE
etisserant@0:  *          - CONFIGURATION...END_CONFIGURATION
etisserant@0:  *          - CONSTANT
etisserant@0:  *          - EN, ENO
etisserant@0:  *          - EXIT
etisserant@0:  *          - FALSE
etisserant@0:  *          - F_EDGE
etisserant@0:  *          - FOR...TO...BY...DO...END_FOR
etisserant@0:  *          - FUNCTION...END_FUNCTION
etisserant@0:  *          - FUNCTION_BLOCK...END_FUNCTION_BLOCK
etisserant@0:  *          - IF...THEN...ELSIF...ELSE...END_IF
etisserant@0:  *          - INITIAL_STEP...END_STEP
etisserant@0:  *          - NOT, MOD, AND, XOR, OR
etisserant@0:  *          - PROGRAM...WITH...
etisserant@0:  *          - PROGRAM...END_PROGRAM
etisserant@0:  *          - R_EDGE
etisserant@0:  *          - READ_ONLY, READ_WRITE
etisserant@0:  *          - REPEAT...UNTIL...END_REPEAT
etisserant@0:  *          - RESOURCE...ON...END_RESOURCE
etisserant@0:  *          - RETAIN, NON_RETAIN
etisserant@0:  *          - RETURN
etisserant@0:  *          - STEP...END_STEP
etisserant@0:  *          - STRUCT...END_STRUCT
etisserant@0:  *          - TASK
etisserant@0:  *          - TRANSITION...FROM...TO...END_TRANSITION
etisserant@0:  *          - TRUE
etisserant@0:  *          - TYPE...END_TYPE
etisserant@0:  *          - VAR...END_VAR
etisserant@0:  *          - VAR_INPUT...END_VAR
etisserant@0:  *          - VAR_OUTPUT...END_VAR
etisserant@0:  *          - VAR_IN_OUT...END_VAR
etisserant@0:  *          - VAR_TEMP...END_VAR
etisserant@0:  *          - VAR_EXTERNAL...END_VAR
etisserant@0:  *          - VAR_ACCESS...END_VAR
etisserant@0:  *          - VAR_CONFIG...END_VAR
etisserant@0:  *          - VAR_GLOBAL...END_VAR
etisserant@0:  *          - WHILE...DO...END_WHILE
etisserant@0:  *          - WITH
etisserant@0:  */
etisserant@0: 
etisserant@0: identifier:
etisserant@0:   identifier_token	{$$ = new identifier_c($1);}
etisserant@0: /*  Make sure that all tokens (names) not defined as keywords are included here...
etisserant@0:  * I (Mario) have already done this, but if any changes are made to this file,
etisserant@0:  * this list MUST be kept consistent!!
etisserant@0:  */
etisserant@0: /**/
etisserant@0: | PRIORITY		{$$ = new identifier_c(strdup("PRIORITY"));}
etisserant@0: | SINGLE		{$$ = new identifier_c(strdup("SINGLE"));}
etisserant@0: | INTERVAL		{$$ = new identifier_c(strdup("INTERVAL"));}
etisserant@0: /**/
etisserant@0: | LD_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | LDN_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | ST_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | STN_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | S_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | R_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | S1_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | R1_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | CLK_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | CU_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | CD_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | PV_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | IN_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | PT_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | ANDN_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: /* NOTE: ANDN2_operator corresponds to the string '&N' in the source code!
etisserant@0:  *       This is __not__ a valid name, so it is omitted from this list!!
etisserant@0:  *| ANDN2_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0:  */
etisserant@0: /* NOTE: 'AND' is a keyword, so should not appear on this list... */
etisserant@0: | ORN_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | XORN_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | ADD_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | SUB_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | MUL_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | DIV_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | GT_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | GE_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | EQ_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | LT_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | LE_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | NE_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | CAL_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | CALC_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | CALCN_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | RET_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | RETC_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | RETCN_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | JMP_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | JMPC_operator		{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | JMPCN_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /*********************/
etisserant@0: /* B 1.2 - Constants */
etisserant@0: /*********************/
etisserant@0: constant:
etisserant@0:   numeric_literal
etisserant@0: | character_string
etisserant@0: | time_literal
etisserant@0: | bit_string_literal
etisserant@0: | boolean_literal
etisserant@0: /* NOTE: in order to remove reduce/reduce conflicts,
etisserant@0:  * unsigned_integer, signed_integer, binary_integer, octal_integer
etisserant@0:  * and hex_integer have been integrated directly into
etisserant@0:  * the constants construct, instead of belonging to
etisserant@0:  * either the bit_string_literal or integer_literal
etisserant@0:  * construct.
etisserant@0:  */
etisserant@0: /* NOTE: unsigned_integer, although used in some
etisserant@0:  * rules, is not defined in the spec!
etisserant@0:  * We therefore replaced unsigned_integer as integer
etisserant@0:  */
etisserant@0: /*| integer {} */  /* i.e. an unsigned_integer */ /* NOTE: already included as a signed integer! */
etisserant@0: | signed_integer
etisserant@0: | binary_integer
etisserant@0: | octal_integer
etisserant@0: | hex_integer
etisserant@0: ;
etisserant@0: 
etisserant@0: /* a helper symbol for expression */
etisserant@0: /* A constant without any preceding '-', but may
etisserant@0:  * include a preceding '+' !
etisserant@0:  */
etisserant@0: non_negative_constant:
etisserant@0:   non_negative_numeric_literal
etisserant@0: | character_string
etisserant@0: | time_literal
etisserant@0: | bit_string_literal
etisserant@0: | boolean_literal
etisserant@0: | non_negative_signed_integer
etisserant@0: | binary_integer
etisserant@0: | octal_integer
etisserant@0: | hex_integer
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /******************************/
etisserant@0: /* B 1.2.1 - Numeric Literals */
etisserant@0: /******************************/
etisserant@0: /* NOTES:
etisserant@0:  *
etisserant@0:  *    - integer is parsed by flex, but signed_integer
etisserant@0:  *      is parsed by bison. Flex cannot parse a signed
etisserant@0:  *      integer correctly!  For example: '123+456'
etisserant@0:  *      would be parsed by flex as an {integer} {signed_integer}
etisserant@0:  *      instead of {integer} '+' {integer}
etisserant@0:  *
etisserant@0:  *    - Neither flex nor bison can parse a real_literal
etisserant@0:  *      completely (and correctly).
etisserant@0:  *      Note that we cannot use the definition of real in bison as
etisserant@0:  *      real: signed_integer '.' integer [exponent]
etisserant@0:  *      exponent: {'E'|'e'} ['+'|'-'] integer
etisserant@0:  *      because 123e45 would be parsed by flex as
etisserant@0:  *      integer (123) identifier (e45).
etisserant@0:  *      I.e., flex never hands over an 'e' directly to
etisserant@0:  *      bison, but rather interprets it as an identifier.
etisserant@0:  *      I guess we could jump through hoops and get it
etisserant@0:  *      working in bison, but the following alternative
etisserant@0:  *      seems more straight forward...
etisserant@0:  *
etisserant@0:  *      We therefore had to break up the definition of
etisserant@0:  *      real_literal in discrete parts:
etisserant@0:  *      real_literal: [real_type_name '#'] singned_real
etisserant@0:  *      signed_real: ['+'|'-'] real
etisserant@0:  *      Flex handles real, while bison handles signed_real
etisserant@0:  *      and real_literal.
etisserant@0:  *
etisserant@0:  *    - According to the spec, intger '.' integer
etisserant@0:  *      may be reduced to either a real or a fixed_point.
etisserant@0:  *      It is nevertheless possible to figure out from the
etisserant@0:  *      context which of the two rules should be used in
etisserant@0:  *      the reduction.
etisserant@0:  *      Unfortunately, due to the issue described above
etisserant@0:  *      regarding the exponent of a real, the syntax
etisserant@0:  *      integer '.' integer
etisserant@0:  *      must be parsed by flex as a single token (i.e.
etisserant@0:  *      fixed_point_token). This means we must add fixed_point
etisserant@0:  *      to the definition of real!
etisserant@0:  *
etisserant@0:  *    - The syntax also uses a construct
etisserant@0:  *        fixed_point: integer ['.' integer]
etisserant@0:  *      Notice that real is not defined based on fixed point,
etisserant@0:  *      but rather off integer thus:
etisserant@0:  *        real: integer '.' integer [exponent]
etisserant@0:  *      This means that a real may not be composed of a single
etisserant@0:  *      integer, unlike the construct fixed_point!
etisserant@0:  *      This also means that a
etisserant@0:  *        integer '.' integer
etisserant@0:  *      could be reduced to either a real or a fixed_point
etisserant@0:  *      construct. It is probably possible to decide by looking
etisserant@0:  *      at the context, BUT:
etisserant@0:  *       Unfortunatley, due to the reasons explained way above,
etisserant@0:  *      a real (with an exponent) has to be handled by flex as a
etisserant@0:  *      whole. This means that we cannot leave to bison (the syntax
etisserant@0:  *      parser) the decision of how to reduce an
etisserant@0:  *        integer '.' integer
etisserant@0:  *      (either to real or to fixed_point)
etisserant@0:  *      The decision on how to reduce it would need to be done by
etisserant@0:  *      ther lexical analyser (i.e. flex). But flex cannot do this
etisserant@0:  *      sort of thing.
etisserant@0:  *      The solution I (Mario) adopted is to have flex return
etisserant@0:  *      a real_token on (notice that exponent is no longer optional)
etisserant@0:  *        integer '.' integer exponent
etisserant@0:  *      and to return a fixed_point_token when it finds
etisserant@0:  *        integer '.' integer
etisserant@0:  *      We now redefine real and fixed_point to be
etisserant@0:  *        fixed_point: fixed_point_token | integer
etisserant@0:  *        real: real_token | fixed_point_token
etisserant@0:  */
etisserant@0: real:
etisserant@0:   real_token		{$$ = new real_c($1);}
etisserant@0: | fixed_point_token	{$$ = new real_c($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: integer:	integer_token		{$$ = new integer_c($1);};
etisserant@0: binary_integer:	binary_integer_token	{$$ = new binary_integer_c($1);};
etisserant@0: octal_integer:	octal_integer_token	{$$ = new octal_integer_c($1);};
etisserant@0: hex_integer:	hex_integer_token	{$$ = new hex_integer_c($1);};
etisserant@0: 
etisserant@0: numeric_literal:
etisserant@0:   integer_literal
etisserant@0: | real_literal
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for non_negative_constant */
etisserant@0: non_negative_numeric_literal:
etisserant@0:   integer_literal
etisserant@0: | non_negative_real_literal
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: integer_literal:
etisserant@0:   integer_type_name '#' signed_integer
etisserant@0: 	{$$ = new integer_literal_c($1, $3);}
etisserant@0: | integer_type_name '#' binary_integer
etisserant@0: 	{$$ = new integer_literal_c($1, $3);}
etisserant@0: | integer_type_name '#' octal_integer
etisserant@0: 	{$$ = new integer_literal_c($1, $3);}
etisserant@0: | integer_type_name '#' hex_integer
etisserant@0: 	{$$ = new integer_literal_c($1, $3);}
etisserant@0: /* NOTE: see note in the definition of constant for reason
etisserant@0:  * why signed_integer, binary_integer, octal_integer
etisserant@0:  * and hex_integer are missing here!
etisserant@0:  */
etisserant@0: ;
etisserant@0: 
etisserant@0: signed_integer:
etisserant@0:   integer
etisserant@0: | '+' integer   {$$ = $2;}
etisserant@0: | '-' integer	{$$ = new neg_expression_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* a helper symbol for non_negative_constant */
etisserant@0: /* A integer without any preceding '-', but may
etisserant@0:  * include a preceding '+' !
etisserant@0:  */
etisserant@0: non_negative_signed_integer:
etisserant@0:   integer
etisserant@0: | '+' integer   {$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: real_literal:
etisserant@0:   signed_real
etisserant@0: | real_type_name '#' signed_real
etisserant@0: 	{$$ = new real_literal_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for non_negative_numeric_literal */
etisserant@0: non_negative_real_literal:
etisserant@0:   non_negative_signed_real
etisserant@0: | real_type_name '#' signed_real
etisserant@0: 	{$$ = new real_literal_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: signed_real:
etisserant@0:   real
etisserant@0: | '+' real	{$$ = $2;}
etisserant@0: | '-' real	{$$ = new neg_expression_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for non_negative_real_literal */
etisserant@0: non_negative_signed_real:
etisserant@0:   real
etisserant@0: | '+' real	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: bit_string_literal:
etisserant@0:   bit_string_type_name '#' integer  /* i.e. unsigned_integer */
etisserant@0: 	{$$ = new bit_string_literal_c($1, $3);}
etisserant@0: | bit_string_type_name '#' binary_integer
etisserant@0: 	{$$ = new bit_string_literal_c($1, $3);}
etisserant@0: | bit_string_type_name '#' octal_integer
etisserant@0: 	{$$ = new bit_string_literal_c($1, $3);}
etisserant@0: | bit_string_type_name '#' hex_integer
etisserant@0: 	{$$ = new bit_string_literal_c($1, $3);}
etisserant@0: /* NOTE: see note in the definition of constant for reason
etisserant@0:  * why unsigned_integer, binary_integer, octal_integer
etisserant@0:  * and hex_integer are missing here!
etisserant@0:  */
etisserant@0: /* NOTE: see note under the B 1.2.1 section of token
etisserant@0:  * and grouping type definition for reason why the use of
etisserant@0:  * bit_string_type_name, although seemingly incorrect, is
etisserant@0:  * really correct here!
etisserant@0:  */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: boolean_literal:
etisserant@0:   TRUE	{$$ = new boolean_literal_c(new bool_type_name_c(),
etisserant@0:   				    new boolean_true_c());}
etisserant@0: | FALSE	{$$ = new boolean_literal_c(new bool_type_name_c(),
etisserant@0: 				    new boolean_false_c());}
etisserant@0: /*
etisserant@0: |	BOOL '#' '1' {}
etisserant@0: |	BOOL '#' '0' {}
etisserant@0: */
etisserant@0: /* NOTE: the rules
etisserant@0:  * BOOL '#' '1'
etisserant@0:  * and
etisserant@0:  * BOOL '#' '0'
etisserant@0:  * do not work as expected...
etisserant@0:  * Consider that we are using 'BOOL' and '#' as tokens
etisserant@0:  * that flex hands over to bison (yacc). Because flex would
etisserant@0:  * then parse the single '1' or '0' as an integer,
etisserant@0:  * the rule in bison would have to be
etisserant@0:  * BOOL '#' integer, followed by verifying of the
etisserant@0:  * integer has the correct value!
etisserant@0:  *
etisserant@0:  * We therefore have flex return TRUE whenever it
etisserant@0:  * comes across 'TRUE' or 'BOOL#1', and FALSE whenever
etisserant@0:  * it comes across 'FALSE' or 'BOOL#0'.
etisserant@0:  * Note that this means that flex will parse "BOOL#01"
etisserant@0:  * as FALSE followed by an integer ('1').
etisserant@0:  * Bison should detect this as an error, so we should
etisserant@0:  * be OK.
etisserant@0:  *
etisserant@0:  * Another option would be to change the rules to accept
etisserant@0:  * BOOL '#' integer
etisserant@0:  * but then check whether the integer has a correct
etisserant@0:  * value! At the moment I feel that the first option
etisserant@0:  * is more straight forward.
etisserant@0:  */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*******************************/
etisserant@0: /* B 1.2.2 - Character Strings */
etisserant@0: /*******************************/
etisserant@0: /* Transform the tokens given us by flex into leafs */
etisserant@0: single_byte_character_string:	single_byte_character_string_token
etisserant@0: 	{$$ = new single_byte_character_string_c($1);};
etisserant@0: 
etisserant@0: double_byte_character_string:	double_byte_character_string_token
etisserant@0: 	{$$ = new double_byte_character_string_c($1);};
etisserant@0: 
etisserant@0: 
etisserant@0: character_string:
etisserant@0:   single_byte_character_string
etisserant@0: | double_byte_character_string
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /***************************/
etisserant@0: /* B 1.2.3 - Time Literals */
etisserant@0: /***************************/
etisserant@0: time_literal:
etisserant@0:   time_of_day
etisserant@0: | date
etisserant@0: | date_and_time
etisserant@0: | duration
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /************************/
etisserant@0: /* B 1.2.3.1 - Duration */
etisserant@0: /************************/
etisserant@0: duration:
etisserant@0: /*  (T | TIME) '#' ['-'] interval */
etisserant@0: /* NOTE: since TIME is also a data type, it is a keyword
etisserant@0:  *       and may therefore be handled by a token.
etisserant@0:  *
etisserant@0:  *       Unfortunately T is not a data type, and therefore
etisserant@0:  *       not a keyword. This means that we may have variables named T!
etisserant@0:  *       Flex cannot return the token TIME when it comes across a single T!
etisserant@0:  *
etisserant@0:  *       We therefore have flex returning the token T_SHARP
etisserant@0:  *       when it comes across 'T#'
etisserant@0:  */
etisserant@0:   TIME '#' interval
etisserant@0: 	{$$ = new duration_c(NULL, $3);}
etisserant@0: | TIME '#' '-' interval
etisserant@0: 	{$$ = new duration_c(new neg_time_c(), $4);}
etisserant@0: | T_SHARP interval
etisserant@0: 	{$$ = new duration_c(NULL, $2);}
etisserant@0: | T_SHARP '-' interval
etisserant@0: 	{$$ = new duration_c(new neg_time_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: interval:
etisserant@0:   days
etisserant@0: | hours
etisserant@0: | minutes
etisserant@0: | seconds
etisserant@0: | milliseconds
etisserant@0: ;
etisserant@0: 
etisserant@0: integer_d:  integer_d_token  {$$ = new integer_c($1);};
etisserant@0: integer_h:  integer_h_token  {$$ = new integer_c($1);};
etisserant@0: integer_m:  integer_m_token  {$$ = new integer_c($1);};
etisserant@0: integer_s:  integer_s_token  {$$ = new integer_c($1);};
etisserant@0: integer_ms: integer_ms_token {$$ = new integer_c($1);};
etisserant@0: 
etisserant@0: fixed_point_d:
etisserant@0:   fixed_point_d_token
etisserant@0: 	{$$ = new fixed_point_c($1);}
etisserant@0: | integer_d
etisserant@0: ;
etisserant@0: 
etisserant@0: fixed_point_h:
etisserant@0:   fixed_point_h_token
etisserant@0: 	{$$ = new fixed_point_c($1);}
etisserant@0: | integer_h
etisserant@0: ;
etisserant@0: 
etisserant@0: fixed_point_m:
etisserant@0:   fixed_point_m_token
etisserant@0: 	{$$ = new fixed_point_c($1);}
etisserant@0: | integer_m
etisserant@0: ;
etisserant@0: 
etisserant@0: fixed_point_s:
etisserant@0:   fixed_point_s_token
etisserant@0: 	{$$ = new fixed_point_c($1);}
etisserant@0: | integer_s
etisserant@0: ;
etisserant@0: 
etisserant@0: fixed_point_ms:
etisserant@0:   fixed_point_ms_token
etisserant@0: 	{$$ = new fixed_point_c($1);}
etisserant@0: | integer_ms
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: fixed_point:
etisserant@0:   fixed_point_token
etisserant@0: 	{$$ = new fixed_point_c($1);}
etisserant@0: | integer
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: days:
etisserant@0: /*  fixed_point ('d') */
etisserant@0:   fixed_point_d
etisserant@0: 	{$$ = new days_c($1, NULL);}
etisserant@0: /*| integer ('d') ['_'] hours */
etisserant@0: | integer_d hours
etisserant@0: 	{$$ = new days_c($1, $2);}
etisserant@0: | integer_d '_' hours
etisserant@0: 	{$$ = new days_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: hours:
etisserant@0: /*  fixed_point ('h') */
etisserant@0:   fixed_point_h
etisserant@0: 	{$$ = new hours_c($1, NULL);}
etisserant@0: /*| integer ('h') ['_'] minutes */
etisserant@0: | integer_h minutes
etisserant@0: 	{$$ = new hours_c($1, $2);}
etisserant@0: | integer_h '_' minutes
etisserant@0: 	{$$ = new hours_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: minutes:
etisserant@0: /*  fixed_point ('m') */
etisserant@0:   fixed_point_m
etisserant@0: 	{$$ = new minutes_c($1, NULL);}
etisserant@0: /*| integer ('m') ['_'] seconds */
etisserant@0: | integer_m seconds
etisserant@0: 	{$$ = new minutes_c($1, $2);}
etisserant@0: | integer_m '_' seconds
etisserant@0: 	{$$ = new minutes_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: seconds:
etisserant@0: /*  fixed_point ('s') */
etisserant@0:   fixed_point_s
etisserant@0: 	{$$ = new seconds_c($1, NULL);}
etisserant@0: /*| integer ('s') ['_'] milliseconds */
etisserant@0: | integer_s milliseconds
etisserant@0: 	{$$ = new seconds_c($1, $2);}
etisserant@0: | integer_s '_' milliseconds
etisserant@0: 	{$$ = new seconds_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: milliseconds:
etisserant@0: /*  fixed_point ('ms') */
etisserant@0:   fixed_point_ms
etisserant@0: 	{$$ = new milliseconds_c($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /************************************/
etisserant@0: /* B 1.2.3.2 - Time of day and Date */
etisserant@0: /************************************/
etisserant@0: time_of_day:
etisserant@0:   TIME_OF_DAY '#' daytime
etisserant@0: 	{$$ = new time_of_day_c($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: daytime:
etisserant@0:   day_hour ':' day_minute ':' day_second
etisserant@0: 	{$$ = new daytime_c($1, $3, $5);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: day_hour: integer;
etisserant@0: day_minute: integer;
etisserant@0: day_second: fixed_point;
etisserant@0: 
etisserant@0: 
etisserant@0: date:
etisserant@0:   DATE '#' date_literal
etisserant@0: 	{$$ = new date_c($3);}
etisserant@0: | D_SHARP date_literal
etisserant@0: 	{$$ = new date_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: date_literal:
etisserant@0:   year '-' month '-' day
etisserant@0: 	{$$ = new date_literal_c($1, $3, $5);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: year: integer;
etisserant@0: month: integer;
etisserant@0: day: integer;
etisserant@0: 
etisserant@0: 
etisserant@0: date_and_time:
etisserant@0:   DATE_AND_TIME '#' date_literal '-' daytime
etisserant@0: 	{$$ = new date_and_time_c($3, $5);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /**********************/
etisserant@0: /* B 1.3 - Data Types */
etisserant@0: /**********************/
etisserant@0: /* Strangely, the following symbol does seem to be required! */
etisserant@0: /*
etisserant@0: data_type_name:
etisserant@0:   non_generic_type_name
etisserant@0: | generic_type_name
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: non_generic_type_name:
etisserant@0:   elementary_type_name
etisserant@0: | derived_type_name
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************************/
etisserant@0: /* B 1.3.1 - Elementary Data Types */
etisserant@0: /***********************************/
etisserant@0: elementary_type_name:
etisserant@0:   numeric_type_name
etisserant@0: | date_type_name
etisserant@0: | bit_string_type_name
etisserant@0: | elementary_string_type_name
etisserant@0: | TIME		{$$ = new time_type_name_c();}
etisserant@0: | BOOL		{$$ = new bool_type_name_c();}
etisserant@0: /* NOTE: see note under the B 1.2.1 section of token
etisserant@0:  * and grouping type definition for reason why BOOL
etisserant@0:  * was added to this definition.
etisserant@0:  */
etisserant@0: ;
etisserant@0: 
etisserant@0: numeric_type_name:
etisserant@0:   integer_type_name
etisserant@0: | real_type_name
etisserant@0: ;
etisserant@0: 
etisserant@0: integer_type_name:
etisserant@0:   signed_integer_type_name
etisserant@0: | unsigned_integer_type_name
etisserant@0: ;
etisserant@0: 
etisserant@0: signed_integer_type_name:
etisserant@0:   SINT	{$$ = new sint_type_name_c();}
etisserant@0: | INT	{$$ = new int_type_name_c();}
etisserant@0: | DINT	{$$ = new dint_type_name_c();}
etisserant@0: | LINT	{$$ = new lint_type_name_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: unsigned_integer_type_name:
etisserant@0:   USINT	{$$ = new usint_type_name_c();}
etisserant@0: | UINT	{$$ = new uint_type_name_c();}
etisserant@0: | UDINT	{$$ = new udint_type_name_c();}
etisserant@0: | ULINT	{$$ = new ulint_type_name_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: real_type_name:
etisserant@0:   REAL	{$$ = new real_type_name_c();}
etisserant@0: | LREAL	{$$ = new lreal_type_name_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: date_type_name:
etisserant@0:   DATE		{$$ = new date_type_name_c();}
etisserant@0: | TIME_OF_DAY	{$$ = new tod_type_name_c();}
etisserant@0: | TOD		{$$ = new tod_type_name_c();}
etisserant@0: | DATE_AND_TIME	{$$ = new dt_type_name_c();}
etisserant@0: | DT		{$$ = new dt_type_name_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: bit_string_type_name:
etisserant@0:   BYTE	{$$ = new byte_type_name_c();}
etisserant@0: | WORD	{$$ = new word_type_name_c();}
etisserant@0: | DWORD	{$$ = new dword_type_name_c();}
etisserant@0: | LWORD	{$$ = new lword_type_name_c();}
etisserant@0: /* NOTE: see note under the B 1.2.1 section of token
etisserant@0:  * and grouping type definition for reason why the BOOL
etisserant@0:  * was omitted from this definition.
etisserant@0:  */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* Helper symbol to concentrate the instantiation
etisserant@0:  * of STRING and WSTRING into a single location.
etisserant@0:  *
etisserant@0:  * These two elements show up in several other rules,
etisserant@0:  * but we want to create the equivalent abstract syntax
etisserant@0:  * in a single location of this file, in order to make
etisserant@0:  * possible future changes easier to edit...
etisserant@0:  */
etisserant@0: elementary_string_type_name:
etisserant@0:   STRING	{$$ = new string_type_name_c();}
etisserant@0: | WSTRING	{$$ = new wstring_type_name_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 1.3.2 - Generic data types */
etisserant@0: /********************************/
etisserant@0: /* Strangely, the following symbol does seem to be required! */
etisserant@0: /*
etisserant@0: generic_type_name:
etisserant@0:   ANY
etisserant@0: | ANY_DERIVED
etisserant@0: | ANY_ELEMENTARY
etisserant@0: | ANY_MAGNITUDE
etisserant@0: | ANY_NUM
etisserant@0: | ANY_REAL
etisserant@0: | ANY_INT
etisserant@0: | ANY_BIT
etisserant@0: | ANY_STRING
etisserant@0: | ANY_DATE
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 1.3.3 - Derived data types */
etisserant@0: /********************************/
etisserant@0: 
etisserant@0: derived_type_name:
etisserant@0:   single_element_type_name
etisserant@0: | prev_declared_array_type_name	{$$ = $1;}
etisserant@0: | prev_declared_structure_type_name	{$$ = $1;}
etisserant@0: | prev_declared_string_type_name	{$$ = $1;}
etisserant@0: ;
etisserant@0: 
etisserant@0: single_element_type_name:
etisserant@0:   prev_declared_simple_type_name		{$$ = $1;}
etisserant@0: /* Include the following if arrays of function blocks are to be allowed!
etisserant@0:  * Since the standard does not allow them,
etisserant@0:  * we leave it commented out for the time being...
etisserant@0:  */
etisserant@0: //| prev_declared_derived_function_block_name	{$$ = $1;}
etisserant@0: | prev_declared_subrange_type_name		{$$ = $1;}
etisserant@0: | prev_declared_enumerated_type_name		{$$ = $1;}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* NOTE: in order to remove a reduce/reduce conflict,
etisserant@0:  *       all occurences of simple_type_name, etc...
etisserant@0:  *       have been replaced with identifier!
etisserant@0:  */
etisserant@0: /*
etisserant@0: simple_type_name: identifier;
etisserant@0: subrange_type_name: identifier;
etisserant@0: enumerated_type_name: identifier;
etisserant@0: array_type_name: identifier;
etisserant@0: structure_type_name: identifier;
etisserant@0: */
etisserant@0: 
etisserant@0: data_type_declaration:
etisserant@0:   TYPE type_declaration_list END_TYPE
etisserant@0: 	{$$ = new data_type_declaration_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for data_type_declaration */
etisserant@0: type_declaration_list:
etisserant@0:   type_declaration ';'
etisserant@0: 	{$$ = new type_declaration_list_c(); $$->add_element($1);}
etisserant@0: | type_declaration_list type_declaration ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: type_declaration:
etisserant@0:   single_element_type_declaration
etisserant@0: | array_type_declaration
etisserant@0: | structure_type_declaration
etisserant@0: | string_type_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: single_element_type_declaration:
etisserant@0:   simple_type_declaration
etisserant@0: | subrange_type_declaration
etisserant@0: | enumerated_type_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: simple_type_declaration:
etisserant@0: /*  simple_type_name ':' simple_spec_init */
etisserant@0:   identifier ':' simple_spec_init
etisserant@0: 	{$$ = new simple_type_declaration_c($1, $3);
etisserant@0: 	 library_element_symtable.insert($1, prev_declared_simple_type_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: simple_spec_init:
etisserant@0:   simple_specification
etisserant@0:   /* The following line was changed so that we wouldn't
etisserant@0:    * have the first element of a simple_spec_init_c()
etisserant@0:    * pointing to another simple_spec_init_c!
etisserant@0:    */
etisserant@0: /*
etisserant@0: | simple_specification ASSIGN constant
etisserant@0: 	{$$ = new simple_spec_init_c($1, $3);}
etisserant@0: */
etisserant@0: | elementary_type_name ASSIGN constant
etisserant@0: 	{$$ = new simple_spec_init_c($1, $3);}
etisserant@0: | prev_declared_simple_type_name ASSIGN constant
etisserant@0: 	{$$ = new simple_spec_init_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* When converting to C/C++, we need to know whether
etisserant@0:  * the elementary_type_name is being used in a variable
etisserant@0:  * declaration or elsewhere (ex. declaration of a derived
etisserant@0:  * type), so the abstract syntax has the elementary_type_name
etisserant@0:  * wrapped inside a simple_spec_init_c.
etisserant@0:  * The exact same thing occurs with prev_declared_simple_type_name.
etisserant@0:  *
etisserant@0:  * This is why in the definition of simple_spec_init,
etisserant@0:  * simple_specification was brocken up into its
etisserant@0:  * constituent components...
etisserant@0:  */
etisserant@0: simple_specification:
etisserant@0: // elementary_type_name | simple_type_name
etisserant@0:   elementary_type_name
etisserant@0: 	{$$ = new simple_spec_init_c($1, NULL);}
etisserant@0: | prev_declared_simple_type_name
etisserant@0: 	{$$ = new simple_spec_init_c($1, NULL);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: subrange_type_declaration:
etisserant@0: /*  subrange_type_name ':' subrange_spec_init */
etisserant@0:   identifier ':' subrange_spec_init
etisserant@0: 	{$$ = new subrange_type_declaration_c($1, $3);
etisserant@0: 	 library_element_symtable.insert($1, prev_declared_subrange_type_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: subrange_spec_init:
etisserant@0:   subrange_specification
etisserant@0: 	{$$ = new subrange_spec_init_c($1, NULL);}
etisserant@0: | subrange_specification ASSIGN signed_integer
etisserant@0: 	{$$ = new subrange_spec_init_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: subrange_specification:
etisserant@0:   integer_type_name '(' subrange')'
etisserant@0: 	{$$ = new subrange_specification_c($1, $3);}
etisserant@0: | prev_declared_subrange_type_name	{$$ = $1;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: subrange:
etisserant@0:   signed_integer DOTDOT signed_integer
etisserant@0: 	{$$ = new subrange_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: enumerated_type_declaration:
etisserant@0: /*  enumerated_type_name ':' enumerated_spec_init */
etisserant@0:   identifier ':' enumerated_spec_init
etisserant@0: 	{$$ = new enumerated_type_declaration_c($1, $3);
etisserant@0: 	 library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: enumerated_spec_init:
etisserant@0:   enumerated_specification
etisserant@0: 	{$$ = new enumerated_spec_init_c($1, NULL);}
etisserant@0: | enumerated_specification ASSIGN enumerated_value
etisserant@0: 	{$$ = new enumerated_spec_init_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: enumerated_specification:
etisserant@0:   '(' enumerated_value_list ')'
etisserant@0: 	{$$ = $2;}
etisserant@0: | prev_declared_enumerated_type_name	{$$ = $1;}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for enumerated_specification */
etisserant@0: enumerated_value_list:
etisserant@0:   enumerated_value
etisserant@0: 	{$$ = new enumerated_value_list_c(); $$->add_element($1);}
etisserant@0: | enumerated_value_list ',' enumerated_value
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: enumerated_value:
etisserant@0:   identifier
etisserant@0: 	{$$ = $1;}
etisserant@0: | prev_declared_enumerated_type_name '#' any_identifier
etisserant@0: 	{$$ = new enumerated_value_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
mario@13: enumerated_value_without_identifier:
mario@13:   prev_declared_enumerated_type_name '#' any_identifier
mario@13: 	{$$ = new enumerated_value_c($1, $3);}
mario@13: ;
mario@13: 
etisserant@0: 
etisserant@0: array_type_declaration:
etisserant@0: /*  array_type_name ':' array_spec_init */
etisserant@0:   identifier ':' array_spec_init
etisserant@0: 	{$$ = new array_type_declaration_c($1, $3);
etisserant@0: 	 library_element_symtable.insert($1, prev_declared_array_type_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: array_spec_init:
etisserant@0:   array_specification
etisserant@0: 	{$$ = new array_spec_init_c($1, NULL);}
etisserant@0: | array_specification ASSIGN array_initialization
etisserant@0: 	{$$ = new array_spec_init_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: array_specification:
etisserant@0:   prev_declared_array_type_name
etisserant@0: 	{$$ = $1;}
etisserant@0: | ARRAY '[' array_subrange_list ']' OF non_generic_type_name
etisserant@0: 	{$$ = new array_specification_c($3, $6);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for array_specification */
etisserant@0: array_subrange_list:
etisserant@0:   subrange
etisserant@0: 	{$$ = new array_subrange_list_c(); $$->add_element($1);}
etisserant@0: | array_subrange_list ',' subrange
etisserant@0: 	{$$ = $1; $$->add_element($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: array_initialization:
etisserant@0:   '[' array_initial_elements_list ']'
etisserant@0: 	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for array_initialization */
etisserant@0: array_initial_elements_list:
etisserant@0:   array_initial_elements
etisserant@0: 	{$$ = new array_initial_elements_list_c(); $$->add_element($1);}
etisserant@0: | array_initial_elements_list ',' array_initial_elements
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: array_initial_elements:
etisserant@0:   array_initial_element
etisserant@0: | integer '(' ')'
etisserant@0: | integer '(' array_initial_element ')'
etisserant@0: 	{$$ = new array_initial_elements_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: array_initial_element:
etisserant@0:   constant
etisserant@0: | enumerated_value
etisserant@0: | structure_initialization
etisserant@0: | array_initialization
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: structure_type_declaration:
etisserant@0: /*  structure_type_name ':' structure_specification */
etisserant@0:   identifier ':' structure_specification
etisserant@0: 	{$$ = new structure_type_declaration_c($1, $3);
etisserant@0: 	 library_element_symtable.insert($1, prev_declared_structure_type_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: structure_specification:
etisserant@0:   structure_declaration
etisserant@0: | initialized_structure
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: initialized_structure:
etisserant@0:   prev_declared_structure_type_name
etisserant@0: 	{$$ = new initialized_structure_c($1, NULL);}
etisserant@0: | prev_declared_structure_type_name ASSIGN structure_initialization
etisserant@0: 	{$$ = new initialized_structure_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: structure_declaration:
etisserant@0:   STRUCT structure_element_declaration_list END_STRUCT
etisserant@0: 	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for structure_declaration */
etisserant@0: structure_element_declaration_list:
etisserant@0:   structure_element_declaration ';'
etisserant@0: 	{$$ = new structure_element_declaration_list_c(); $$->add_element($1);}
etisserant@0: | structure_element_declaration_list structure_element_declaration ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: structure_element_declaration:
etisserant@0:   structure_element_name ':' simple_spec_init
etisserant@0: 	{$$ = new structure_element_declaration_c($1, $3);}
etisserant@0: | structure_element_name ':' subrange_spec_init
etisserant@0: 	{$$ = new structure_element_declaration_c($1, $3);}
etisserant@0: | structure_element_name ':' enumerated_spec_init
etisserant@0: 	{$$ = new structure_element_declaration_c($1, $3);}
etisserant@0: | structure_element_name ':' array_spec_init
etisserant@0: 	{$$ = new structure_element_declaration_c($1, $3);}
etisserant@0: | structure_element_name ':' initialized_structure
etisserant@0: 	{$$ = new structure_element_declaration_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: structure_element_name: any_identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: structure_initialization:
etisserant@0:   '(' structure_element_initialization_list ')'
etisserant@0: 	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for structure_initialization */
etisserant@0: structure_element_initialization_list:
etisserant@0:   structure_element_initialization
etisserant@0: 	{$$ = new structure_element_initialization_list_c(); $$->add_element($1);}
etisserant@0: | structure_element_initialization_list ',' structure_element_initialization
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: structure_element_initialization:
etisserant@0:   structure_element_name ASSIGN constant
etisserant@0: 	{$$ = new structure_element_initialization_c($1, $3);}
etisserant@0: | structure_element_name ASSIGN enumerated_value
etisserant@0: 	{$$ = new structure_element_initialization_c($1, $3);}
etisserant@0: | structure_element_name ASSIGN array_initialization
etisserant@0: 	{$$ = new structure_element_initialization_c($1, $3);}
etisserant@0: | structure_element_name ASSIGN structure_initialization
etisserant@0: 	{$$ = new structure_element_initialization_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* NOTE: in order to remove a reduce/reduce conflict,
etisserant@0:  *       all occurences of string_type_name
etisserant@0:  *       have been replaced with identifier!
etisserant@0:  */
etisserant@0: /*
etisserant@0: string_type_name: identifier;
etisserant@0: */
etisserant@0: 
etisserant@0: string_type_declaration:
etisserant@0: /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
etisserant@0:   identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init
etisserant@0: 	{$$ = new string_type_declaration_c($1, $3, $4, $5);
etisserant@0: 	 library_element_symtable.insert($1, prev_declared_string_type_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for string_type_declaration */
etisserant@0: string_type_declaration_size:
etisserant@0:   '[' integer ']'
etisserant@0: 	{$$ = $2;}
etisserant@0: /* REMOVED !! */
etisserant@0: //|  /* empty */
etisserant@0: //	{$$ = NULL;}
etisserant@0: ;
etisserant@0: /* The syntax contains a reduce/reduce conflict.
etisserant@0:  * The optional '[' <size> ']'
etisserant@0:  * has been changed to become mandatory to remove the conflict.
etisserant@0:  *
etisserant@0:  * The conflict arises because
etisserant@0:  *  new_str_type : STRING := "hello!"
etisserant@0:  * may be reduced to a string_type_declaration OR
etisserant@0:  * a simple_type_declaration.
etisserant@0:  *
etisserant@0:  * Our change forces it to be reduced to a
etisserant@0:  * simple_type_declaration!
etisserant@0:  * We chose this option because changing the definition
etisserant@0:  * of simple_spec_init would force us to change all the other
etisserant@0:  * rules in which it appears. The change we made has no
etisserant@0:  * side-effects!
etisserant@0:  */
etisserant@0: 
etisserant@0: /* helper symbol for string_type_declaration */
etisserant@0: string_type_declaration_init:
etisserant@0:   /* empty */
etisserant@0: 	{$$ = NULL;}
etisserant@0: | ASSIGN character_string
etisserant@0: 	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*********************/
etisserant@0: /* B 1.4 - Variables */
etisserant@0: /*********************/
etisserant@0: variable:
etisserant@0:   symbolic_variable
etisserant@0: | direct_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: symbolic_variable:
etisserant@0: /* NOTE: To be entirely correct, variable_name should be replacemed by
etisserant@0:  *         prev_declared_variable_name | prev_declared_fb_name | prev_declared_global_var_name
etisserant@0:  */
mario@13:  identifier
etisserant@0: 	{$$ = new symbolic_variable_c($1);}
etisserant@0: | prev_declared_fb_name
etisserant@0: 	{$$ = new symbolic_variable_c($1);}
etisserant@0: | prev_declared_global_var_name
etisserant@0: 	{$$ = new symbolic_variable_c($1);}
mario@13: | prev_declared_variable_name
mario@13: 	{$$ = new symbolic_variable_c($1);}
etisserant@0: | multi_element_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE: in section B 1.7, when configuring a program, symbolic_variable
etisserant@0:  *       is used. Nevertheless, during the parsing of a configuration,
etisserant@0:  *       the variables in question are out of scope, so we should
etisserant@0:  *       be allowing any_identifier instead of prev_declared_variable_name!
etisserant@0:  *
etisserant@0:  *       We therefore need a new any_symbolic_variable construct that
etisserant@0:  *       allows the use of any_identifier instead of previously declared
etisserant@0:  *       variables, function blocks, etc...
etisserant@0:  */
etisserant@0: any_symbolic_variable:
etisserant@0: // variable_name -> replaced by any_identifier
etisserant@0:   any_identifier
etisserant@0: 	{$$ = new symbolic_variable_c($1);}
etisserant@0: | any_multi_element_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* for yet undeclared variable names ! */
etisserant@0: variable_name: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************************/
etisserant@0: /* B.1.4.1   Directly Represented Variables */
etisserant@0: /********************************************/
etisserant@0: direct_variable: direct_variable_token	{$$ = new direct_variable_c($1);};
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*************************************/
etisserant@0: /* B.1.4.2   Multi-element Variables */
etisserant@0: /*************************************/
etisserant@0: multi_element_variable:
etisserant@0:   array_variable
etisserant@0: | structured_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: /* please see note above any_symbolic_variable */
etisserant@0: any_multi_element_variable:
etisserant@0:   any_array_variable
etisserant@0: | any_structured_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: array_variable:
etisserant@0:   subscripted_variable '[' subscript_list ']'
etisserant@0: 	{$$ = new array_variable_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* please see note above any_symbolic_variable */
etisserant@0: any_array_variable:
etisserant@0:   any_subscripted_variable '[' subscript_list ']'
etisserant@0: 	{$$ = new array_variable_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: subscripted_variable:
etisserant@0:   symbolic_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* please see note above any_symbolic_variable */
etisserant@0: any_subscripted_variable:
etisserant@0:   any_symbolic_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: subscript_list:
etisserant@0:   subscript
etisserant@0: 	{$$ = new subscript_list_c(); $$->add_element($1);}
etisserant@0: | subscript_list ',' subscript
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: subscript:  expression;
etisserant@0: 
etisserant@0: 
etisserant@0: structured_variable:
etisserant@0:   record_variable '.' field_selector
etisserant@0: 	{$$ = new structured_variable_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* please see note above any_symbolic_variable */
etisserant@0: any_structured_variable:
etisserant@0:   any_record_variable '.' field_selector
etisserant@0: 	{$$ = new structured_variable_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: record_variable:
etisserant@0:   symbolic_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* please see note above any_symbolic_variable */
etisserant@0: any_record_variable:
etisserant@0:   any_symbolic_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: field_selector: any_identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /******************************************/
etisserant@0: /* B 1.4.3 - Declaration & Initialisation */
etisserant@0: /******************************************/
etisserant@0: input_declarations:
etisserant@0:   VAR_INPUT            input_declaration_list END_VAR
etisserant@0: 	{$$ = new input_declarations_c(NULL, $2);}
etisserant@0: | VAR_INPUT RETAIN     input_declaration_list END_VAR
etisserant@0: 	{$$ = new input_declarations_c(new retain_option_c(), $3);}
etisserant@0: | VAR_INPUT NON_RETAIN input_declaration_list END_VAR
etisserant@0: 	{$$ = new input_declarations_c(new non_retain_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for input_declarations */
etisserant@0: input_declaration_list:
etisserant@0:   input_declaration ';'
etisserant@0: 	{$$ = new input_declaration_list_c(); $$->add_element($1);}
etisserant@0: | input_declaration_list input_declaration ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: input_declaration:
etisserant@0:   var_init_decl
etisserant@0: | edge_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: edge_declaration:
etisserant@0:   var1_list ':' BOOL R_EDGE
etisserant@0: 	{$$ = new edge_declaration_c(new raising_edge_option_c(), $1);}
etisserant@0: | var1_list ':' BOOL F_EDGE
etisserant@0: 	{$$ = new edge_declaration_c(new falling_edge_option_c(), $1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: var_init_decl:
etisserant@0:   var1_init_decl
etisserant@0: | array_var_init_decl
etisserant@0: | structured_var_init_decl
etisserant@0: | fb_name_decl
etisserant@0: | string_var_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: var1_init_decl:
etisserant@0:   var1_list ':' simple_spec_init
etisserant@0: 	{$$ = new var1_init_decl_c($1, $3);}
etisserant@0: | var1_list ':' subrange_spec_init
etisserant@0: 	{$$ = new var1_init_decl_c($1, $3);}
etisserant@0: | var1_list ':' enumerated_spec_init
etisserant@0: 	{$$ = new var1_init_decl_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: var1_list:
etisserant@0:   variable_name
etisserant@0: 	{$$ = new var1_list_c(); $$->add_element($1);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0:  | var1_list ',' variable_name
etisserant@0: 	{$$ = $1; $$->add_element($3);
etisserant@0: 	 variable_name_symtable.insert($3, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: array_var_init_decl:
etisserant@0:  var1_list ':' array_spec_init
etisserant@0: 	{$$ = new array_var_init_decl_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: structured_var_init_decl:
etisserant@0:   var1_list ':' initialized_structure
etisserant@0: 	{$$ = new structured_var_init_decl_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE: see notes above fb_name_list and var1_list
etisserant@0:  *       for reason why ':' was removed from this rule!
etisserant@0:  *       In essence, to remove a shift/reduce conflict,
etisserant@0:  *       the ':' was moved to var1_list and fb_name_list!
etisserant@0:  */
etisserant@0: fb_name_decl:
etisserant@0: /*  fb_name_list ':' function_block_type_name */
etisserant@0:   fb_name_list_with_colon function_block_type_name
etisserant@0: 	{$$ = new fb_name_decl_c($1, $2, NULL);}
etisserant@0: /*| fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
etisserant@0: | fb_name_list_with_colon function_block_type_name ASSIGN structure_initialization
etisserant@0: 	{$$ = new fb_name_decl_c($1, $2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE: In order to remove a reduce/reduce conflict between
etisserant@0:  *       var1_list and fb_name_list, which are identical to each
etisserant@0:  *       other, fb_name_list has been redefined to be a var1_list.
etisserant@0:  *
etisserant@0:  *        In order to remove a further shift/reduce conflict, var1_list
etisserant@0:  *        is imediately transfomred into var1_list_with_colon
etisserant@0:  *        (i.e. it includes the ':' following the list), which
etisserant@0:  *        means that fb_name_list is built from a
etisserant@0:  *        var1_list_with_colon after all!
etisserant@0:  */
etisserant@0: /*
etisserant@0: fb_name_list:
etisserant@0:  (*  fb_name *)
etisserant@0:   identifier
etisserant@0: 	{$$ = new fb_name_list_c($1);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_fb_name_token);
etisserant@0: 	}
etisserant@0: (* | fb_name_list ',' fb_name *)
etisserant@0: | fb_name_list ',' identifier
etisserant@0: 	{$$ = $1; $$->add_element($3);
etisserant@0: 	 variable_name_symtable.insert($3, prev_declared_fb_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: fb_name_list_with_colon:
etisserant@0:   var1_list_with_colon
etisserant@0: 	{$$ = new fb_name_list_c();
etisserant@0: 	 /* fill up the new fb_name_list_c object with the references
etisserant@0: 	  * contained in the var1_list_c object.
etisserant@0: 	  */
etisserant@0: 	 FOR_EACH_ELEMENT(elem, $1, {$$->add_element(elem);});
etisserant@0: 	 delete $1;
etisserant@0: 	 /* change the tokens associated with the symbols stored in
etisserant@0: 	  * the variable name symbol table from prev_declared_variable_name_token
etisserant@0: 	  * to prev_declared_fb_name_token
etisserant@0: 	  */
etisserant@0: 	 FOR_EACH_ELEMENT(elem, $$, {variable_name_symtable.set(elem, prev_declared_fb_name_token);});
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for fb_name_list_with_colon */
etisserant@0: var1_list_with_colon:
etisserant@0:   var1_list ':'
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: // fb_name: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: output_declarations:
etisserant@0:   VAR_OUTPUT var_init_decl_list END_VAR
etisserant@0: 	{$$ = new output_declarations_c(NULL, $2);}
etisserant@0: | VAR_OUTPUT RETAIN var_init_decl_list END_VAR
etisserant@0: 	{$$ = new output_declarations_c(new retain_option_c(), $3);}
etisserant@0: | VAR_OUTPUT NON_RETAIN var_init_decl_list END_VAR
etisserant@0: 	{$$ = new output_declarations_c(new non_retain_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: input_output_declarations:
etisserant@0:   VAR_IN_OUT var_declaration_list END_VAR
etisserant@0: 	{$$ = new input_output_declarations_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for input_output_declarations */
etisserant@0: var_declaration_list:
etisserant@0:   var_declaration ';'
etisserant@0: 	{$$ = new var_declaration_list_c(); $$->add_element($1);}
etisserant@0: | var_declaration_list var_declaration ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: var_declaration:
etisserant@0:   temp_var_decl
etisserant@0: | fb_name_decl
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: temp_var_decl:
etisserant@0:   var1_declaration
etisserant@0: | array_var_declaration
etisserant@0: | structured_var_declaration
etisserant@0: | string_var_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: var1_declaration:
etisserant@0:   var1_list  ':' simple_specification
etisserant@0: 	{$$ = new var1_init_decl_c($1, $3);}
etisserant@0: | var1_list  ':' subrange_specification
etisserant@0: 	{$$ = new var1_init_decl_c($1, $3);}
etisserant@0: | var1_list  ':' enumerated_specification
etisserant@0: 	{$$ = new var1_init_decl_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: array_var_declaration:
etisserant@0:   var1_list ':' array_specification
etisserant@0: 	{$$ = new array_var_declaration_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: structured_var_declaration:
etisserant@0:   var1_list ':' prev_declared_structure_type_name
etisserant@0: 	{$$ = new structured_var_declaration_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: var_declarations:
etisserant@0:   VAR var_init_decl_list END_VAR
etisserant@0: 	{$$ = new var_declarations_c(NULL, $2);}
etisserant@0: | VAR CONSTANT var_init_decl_list END_VAR
etisserant@0: 	{$$ = new var_declarations_c(new constant_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: retentive_var_declarations:
etisserant@0:   VAR RETAIN var_init_decl_list END_VAR
etisserant@0: 	{$$ = new retentive_var_declarations_c($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: located_var_declarations:
etisserant@0:   VAR  located_var_decl_list END_VAR
etisserant@0: 	{$$ = new located_var_declarations_c(NULL, $2);}
etisserant@0: | VAR CONSTANT located_var_decl_list END_VAR
etisserant@0: 	{$$ = new located_var_declarations_c(new constant_option_c(), $3);}
etisserant@0: | VAR RETAIN located_var_decl_list END_VAR
etisserant@0: 	{$$ = new located_var_declarations_c(new retain_option_c(), $3);}
etisserant@0: | VAR NON_RETAIN located_var_decl_list END_VAR
etisserant@0: 	{$$ = new located_var_declarations_c(new non_retain_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for located_var_declarations */
etisserant@0: located_var_decl_list:
etisserant@0:   located_var_decl ';'
etisserant@0: 	{$$ = new located_var_decl_list_c(); $$->add_element($1);}
etisserant@0: | located_var_decl_list located_var_decl ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: located_var_decl:
etisserant@0:   variable_name location ':' located_var_spec_init
etisserant@0: 	{$$ = new located_var_decl_c($1, $2, $4);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: | location ':' located_var_spec_init
etisserant@0: 	{$$ = new located_var_decl_c(NULL, $1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: external_var_declarations:
etisserant@0:   VAR_EXTERNAL external_declaration_list END_VAR
etisserant@0: 	{$$ = new external_var_declarations_c(NULL, $2);}
etisserant@0: | VAR_EXTERNAL CONSTANT external_declaration_list END_VAR
etisserant@0: 	{$$ = new external_var_declarations_c(new constant_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for external_var_declarations */
etisserant@0: external_declaration_list:
etisserant@0:   external_declaration ';'
etisserant@0: 	{$$ = new external_declaration_list_c(); $$->add_element($1);}
etisserant@0: | external_declaration_list external_declaration';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: external_declaration:
etisserant@0:   global_var_name ':' simple_specification
etisserant@0: 	{$$ = new external_declaration_c($1, $3);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: | global_var_name ':' subrange_specification
etisserant@0: 	{$$ = new external_declaration_c($1, $3);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: | global_var_name ':' enumerated_specification
etisserant@0: 	{$$ = new external_declaration_c($1, $3);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: | global_var_name ':' array_specification
etisserant@0: 	{$$ = new external_declaration_c($1, $3);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: | global_var_name ':' prev_declared_structure_type_name
etisserant@0: 	{$$ = new external_declaration_c($1, $3);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: | global_var_name ':' function_block_type_name
etisserant@0: 	{$$ = new external_declaration_c($1, $3);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_fb_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: global_var_name: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: global_var_declarations:
etisserant@0:   VAR_GLOBAL global_var_decl_list END_VAR
etisserant@0: 	{$$ = new global_var_declarations_c(NULL, $2);}
etisserant@0: | VAR_GLOBAL CONSTANT global_var_decl_list END_VAR
etisserant@0: 	{$$ = new global_var_declarations_c(new constant_option_c(), $3);}
etisserant@0: | VAR_GLOBAL RETAIN global_var_decl_list END_VAR
etisserant@0: 	{$$ = new global_var_declarations_c(new retain_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for global_var_declarations */
etisserant@0: global_var_decl_list:
etisserant@0:   global_var_decl ';'
etisserant@0: 	{$$ = new global_var_decl_list_c(); $$->add_element($1);}
etisserant@0: | global_var_decl_list global_var_decl ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: global_var_decl:
etisserant@0:   global_var_spec ':'
etisserant@0: 	{$$ = new global_var_decl_c($1, NULL);}
etisserant@0: | global_var_spec ':' located_var_spec_init
etisserant@0: 	{$$ = new global_var_decl_c($1, $3);}
etisserant@0: | global_var_spec ':' function_block_type_name
etisserant@0: 	{$$ = new global_var_decl_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: global_var_spec:
etisserant@0:   global_var_list	{$$ = $1;}
etisserant@0: | location
lbessard@28: 	{$$ = new global_var_spec_c(NULL, $1);}
etisserant@0: | global_var_name location
etisserant@0: 	{$$ = new global_var_spec_c($1, $2);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_global_var_name_token);
etisserant@0: 	}
etisserant@0: 
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: located_var_spec_init:
etisserant@0:   simple_spec_init
etisserant@0: | subrange_spec_init
etisserant@0: | enumerated_spec_init
etisserant@0: | array_spec_init
etisserant@0: | initialized_structure
etisserant@0: | single_byte_string_spec
etisserant@0: | double_byte_string_spec
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: location:
etisserant@0:   AT direct_variable
etisserant@0: 	{$$ = new location_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: global_var_list:
etisserant@0:   global_var_name
etisserant@0: 	{$$ = new global_var_list_c(); $$->add_element($1);
etisserant@0: 	 variable_name_symtable.insert($1, prev_declared_global_var_name_token);
etisserant@0: 	}
etisserant@0: | global_var_list ',' global_var_name
etisserant@0: 	{$$ = $1; $$->add_element($3);
etisserant@0: 	 variable_name_symtable.insert($3, prev_declared_global_var_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: string_var_declaration:
etisserant@0:   single_byte_string_var_declaration
etisserant@0: | double_byte_string_var_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: single_byte_string_var_declaration:
etisserant@0:   var1_list ':' single_byte_string_spec
etisserant@0: 	{$$ = new single_byte_string_var_declaration_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* NOTE: The constructs
etisserant@0:  *
etisserant@0:  *       [W]STRING
etisserant@0:  *       and
etisserant@0:  *       [W]STRING ASSIGN single_byte_character_string
etisserant@0:  *
etisserant@0:  *       were removed as they are already contained
etisserant@0:  *       within a other constructs.
etisserant@0:  *
etisserant@0:  *       single_byte_string_spec is used in:
etisserant@0:  *        - single_byte_string_var_declaration ->
etisserant@0:  *           -> string_var_declaration ---> var_init_decl
etisserant@0:  *                                     |--> temp_var_decl
etisserant@0:  *                                     |--> var2_init_decl
etisserant@0:  *        - located_var_spec_init
etisserant@0:  *
etisserant@0:  *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
etisserant@0:  *        -> simple_spec -> simple_specification -> simple_spec_init ->
etisserant@0:  *        -> located_var_spec_init
etisserant@0:  *
etisserant@0:  *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
etisserant@0:  *        -> simple_spec -> simple_specification -> simple_spec_init ->
etisserant@0:  *        -> var1_init_decl -> var_init_decl
etisserant@0:  *
etisserant@0:  *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
etisserant@0:  *        -> simple_spec -> simple_specification -> simple_spec_init ->
etisserant@0:  *        -> var1_init_decl -> var2_init_decl
etisserant@0:  *
etisserant@0:  *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
etisserant@0:  *        -> simple_spec -> simple_specification ->
etisserant@0:  *        -> var1_declaration -> temp_var_decl
etisserant@0:  */
etisserant@0: single_byte_string_spec:
etisserant@0: /*  STRING
etisserant@0: 	{$$ = new single_byte_string_spec_c(NULL, NULL);}
etisserant@0: */
etisserant@0:   STRING '[' integer ']'
etisserant@0: 	{$$ = new single_byte_string_spec_c($3, NULL);}
etisserant@0: /*
etisserant@0: | STRING ASSIGN single_byte_character_string
etisserant@0: 	{$$ = new single_byte_string_spec_c(NULL, $3);}
etisserant@0: */
etisserant@0: | STRING '[' integer ']' ASSIGN single_byte_character_string
etisserant@0: 	{$$ = new single_byte_string_spec_c($3, $6);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: double_byte_string_var_declaration:
etisserant@0:   var1_list ':' double_byte_string_spec
etisserant@0: 	{$$ = new double_byte_string_var_declaration_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: double_byte_string_spec:
etisserant@0: /*  WSTRING
etisserant@0: 	{$$ = new double_byte_string_spec_c(NULL, NULL);}
etisserant@0: */
etisserant@0:   WSTRING '[' integer ']'
etisserant@0: 	{$$ = new double_byte_string_spec_c($3, NULL);}
etisserant@0: /*
etisserant@0: | WSTRING ASSIGN double_byte_character_string
etisserant@0: 	{$$ = new double_byte_string_spec_c(NULL, $3);}
etisserant@0: */
etisserant@0: | WSTRING '[' integer ']' ASSIGN double_byte_character_string
etisserant@0: 	{$$ = new double_byte_string_spec_c($3, $6);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: incompl_located_var_declarations:
etisserant@0:   VAR            incompl_located_var_decl_list END_VAR
etisserant@0: 	{$$ = new incompl_located_var_declarations_c(NULL, $2);}
etisserant@0: | VAR     RETAIN incompl_located_var_decl_list END_VAR
etisserant@0: 	{$$ = new incompl_located_var_declarations_c(new retain_option_c(), $3);}
etisserant@0: | VAR NON_RETAIN incompl_located_var_decl_list END_VAR
etisserant@0: 	{$$ = new incompl_located_var_declarations_c(new non_retain_option_c(), $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for incompl_located_var_declarations */
etisserant@0: incompl_located_var_decl_list:
etisserant@0:   incompl_located_var_decl ';'
etisserant@0: 	{$$ = new incompl_located_var_decl_list_c(); $$->add_element($1);}
etisserant@0: | incompl_located_var_decl_list incompl_located_var_decl ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: incompl_located_var_decl:
etisserant@0:   variable_name incompl_location ':' var_spec
etisserant@0: 	{$$ = new incompl_located_var_decl_c($1, $2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: incompl_location:
etisserant@0:   AT incompl_location_token
etisserant@0: 	{$$ = new incompl_location_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: var_spec:
etisserant@0:   simple_specification
etisserant@0: | subrange_specification
etisserant@0: | enumerated_specification
etisserant@0: | array_specification
etisserant@0: | prev_declared_structure_type_name
etisserant@0: | string_spec
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for var_spec */
etisserant@0: /* NOTE: The constructs
etisserant@0:  *
etisserant@0:  *       STRING
etisserant@0:  *       and
etisserant@0:  *       WSTRING
etisserant@0:  *
etisserant@0:  *       were removed as they are already contained
etisserant@0:  *       within a simple_specification.
etisserant@0:  */
etisserant@0: string_spec:
etisserant@0: /*  STRING
etisserant@0: 	{$$ = new single_byte_string_spec_c(NULL, NULL);}
etisserant@0: */
etisserant@0:   STRING '[' integer ']'
etisserant@0: 	{$$ = new single_byte_string_spec_c($3, NULL);}
etisserant@0: /*
etisserant@0: | WSTRING
etisserant@0: 	{$$ = new double_byte_string_spec_c(NULL, NULL);}
etisserant@0: */
etisserant@0: | WSTRING '[' integer ']'
etisserant@0: 	{$$ = new double_byte_string_spec_c($3, NULL);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* intermediate helper symbol for:
etisserant@0:  *  - non_retentive_var_decls
etisserant@0:  *  - output_declarations
etisserant@0:  *  - var_declarations
etisserant@0:  */
etisserant@0: var_init_decl_list:
etisserant@0:   var_init_decl ';'
etisserant@0: 	{$$ = new var_init_decl_list_c(); $$->add_element($1);}
etisserant@0: | var_init_decl_list var_init_decl ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************/
etisserant@0: /* B 1.5.1 - Functions */
etisserant@0: /***********************/
etisserant@0: /* The following rules should be set such as:
etisserant@0:  * function_name: function_name_no_clashes | function_name_simpleop_clashes | function_name_expression_clashes
etisserant@0:  * function_name: function_name_no_NOT_clashes | function_name_NOT_clashes;
etisserant@0:  */
etisserant@0: 
etisserant@0: function_name_no_clashes: prev_declared_derived_function_name | standard_function_name_no_clashes;
etisserant@0: function_name_simpleop_clashes: standard_function_name_simpleop_clashes;
etisserant@0: //function_name_expression_clashes: standard_function_name_expression_clashes;
etisserant@0: 
etisserant@0: function_name_no_NOT_clashes: prev_declared_derived_function_name | standard_function_name_no_NOT_clashes;
etisserant@0: //function_name_NOT_clashes: standard_function_name_NOT_clashes;
etisserant@0: 
etisserant@0: /*
etisserant@0: function_name:
etisserant@0:   prev_declared_derived_function_name
etisserant@0: | standard_function_name
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: /* NOTE: The list of standard function names
etisserant@0:  *       includes the standard functions MOD(), NOT()
etisserant@0:  *
etisserant@0:  *       Strangely enough, MOD and NOT are reserved keywords,
etisserant@0:  *       so shouldn't be used for function names.
etisserant@0:  *
etisserant@0:  *       The specification contradicts itself!
etisserant@0:  *       Our workaround  is to treat MOD as a token,
etisserant@0:  *       but to include this token as a
etisserant@0:  *       standard_function_name.
etisserant@0:  *
etisserant@0:  *       The names of all other standard functions get
etisserant@0:  *       preloaded into the library_element_symbol_table
etisserant@0:  *       with the token value of
etisserant@0:  *       standard_function_name_token
etisserant@0:  *       Actually, simply for completeness, MOD is also
etisserant@0:  *       loaded into the library_element_symbol_table, but
etisserant@0:  *       it is irrelevant since flex will catch MOD as a
etisserant@0:  *       token, before it interprets it as an identifier,
etisserant@0:  *       and looks in the library_element_symbol_table to check
etisserant@0:  *       whether it has been previously declared.
etisserant@0:  *
etisserant@0:  * NOTE: The same as the above also occurs with the IL
etisserant@0:  *       operators NOT AND OR XOR ADD SUB MUL DIV MOD
etisserant@0:  *       GT GE EQ LT LE NE.
etisserant@0:  *       Note that MOD is once again in the list!
etisserant@0:  *       Anyway, we give these the same treatement as
etisserant@0:  *       MOD, since we are writing a parser for ST and
etisserant@0:  *       IL simultaneously. If this were not the case,
etisserant@0:  *       the ST parser would not need the tokens NOT AND ...
etisserant@0:  *
etisserant@0:  * NOTE: Note that 'NOT' is special, as it conflicts
etisserant@0:  *       with two operators: the  IL 'NOT' operator, and
etisserant@0:  *       the unary operator 'NOT' in ST!!
etisserant@0:  *
etisserant@0:  *  NOTE: The IL language is ambiguous, since using NOT, AND, ...
etisserant@0:  *       may be interpreted as either an IL operator, or
etisserant@0:  *       as a standard function call!
etisserant@0:  *       I (Mario) opted to interpret it as an IL operator.
etisserant@0:  *       This requires changing the syntax for IL language
etisserant@0:  *       function   calling, to exclude all function with
etisserant@0:  *       names that clash with IL operators. I therefore
etisserant@0:  *       created the constructs
etisserant@0:  *       function_name_without_clashes
etisserant@0:  *       standard_function_name_without_clashes
etisserant@0:  *       to include all function names, except those that clash
etisserant@0:  *       with IL operators. These constructs are only used
etisserant@0:  *       within the IL language!
etisserant@0:  */
etisserant@0: /* The following rules should be set such as:
etisserant@0:  * standard_function_name: standard_function_name_no_clashes | standard_function_name_simpleop_clashes | standard_function_name_expression_clashes
etisserant@0:  * standard_function_name: standard_function_name_no_NOT_clashes | standard_function_name_NOT_clashes;
etisserant@0:  */
etisserant@0: 
etisserant@0: /*
etisserant@0: standard_function_name:
etisserant@0:   standard_function_name_no_clashes
etisserant@0: | standard_function_name_expression_clashes
etisserant@0: | standard_function_name_NOT_clashes
etisserant@0: //| standard_function_name_simpleop_only_clashes
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: standard_function_name_no_NOT_clashes:
etisserant@0:   standard_function_name_no_clashes
etisserant@0: | standard_function_name_expression_clashes
etisserant@0: //| standard_function_name_simpleop_only_clashes
etisserant@0: ;
etisserant@0: 
etisserant@0: standard_function_name_no_clashes:
etisserant@0:   standard_function_name_token
etisserant@0: 	{$$ = new identifier_c($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: standard_function_name_simpleop_clashes:
etisserant@0:   standard_function_name_NOT_clashes
etisserant@0: //| standard_function_name_simpleop_only_clashes
etisserant@0: ;
etisserant@0: 
etisserant@0: standard_function_name_NOT_clashes:
etisserant@0:   NOT
etisserant@0: 	{$$ = new identifier_c(strdup("NOT"));}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* Add here any other IL simple operators that collide
etisserant@0:  * with standard function names!
etisserant@0:  * Don't forget to uncomment the equivalent lines in
etisserant@0:  *   - standard_function_name_simpleop_clashes
etisserant@0:  *   - standard_function_name
etisserant@0:  *   - standard_function_name_no_NOT_clashes
etisserant@0:  */
etisserant@0: /*
etisserant@0: standard_function_name_simpleop_only_clashes:
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: standard_function_name_expression_clashes:
etisserant@0:   AND_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: //NOTE: AND2 (corresponding to the source code string '&') does not clash
etisserant@0: //      with a standard function name, so should be commented out!
etisserant@0: //| AND2_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | OR_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | XOR_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | ADD_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | SUB_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | MUL_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | DIV_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | MOD_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | GT_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | GE_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | EQ_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | LT_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | LE_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: | NE_operator	{$$ = il_operator_c_2_identifier_c($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: derived_function_name:
etisserant@0:   identifier
etisserant@0: | prev_declared_derived_function_name
etisserant@0: 	{$$ = $1;
etisserant@0: 	 if (not(allow_function_overloading))
etisserant@0: 	   ERROR;
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: function_declaration:
etisserant@0: /*  FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
etisserant@0:   function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION
etisserant@0: 	{$$ = new function_declaration_c($1, $3, $4, $5);
etisserant@0: 	 variable_name_symtable.pop();
etisserant@0: 	 if (allow_function_overloading) {
etisserant@0: 	   switch (library_element_symtable.find_value($1)) {
etisserant@0: 	     case prev_declared_derived_function_name_token:
etisserant@0: 	       /* do nothing, already in map. */
etisserant@0: 	       break;
etisserant@0: 	     case BOGUS_TOKEN_ID:
etisserant@0: 	       /* Not yet in map. Must insert...*/
etisserant@0: 	       library_element_symtable.insert($1, prev_declared_derived_function_name_token);
etisserant@0: 	       break;
etisserant@0: 	     default:
etisserant@0: 	       /* Already in map but associated with something else other than a funtion name! */
etisserant@0: 	       ERROR;
etisserant@0: 	   }
etisserant@0: 	 } else {
etisserant@0: 	   library_element_symtable.insert($1, prev_declared_derived_function_name_token);
etisserant@0: 	 }
etisserant@0: 	}
etisserant@0: /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
etisserant@0: | function_name_declaration ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION
etisserant@0: 	{$$ = new function_declaration_c($1, $3, $4, $5);
etisserant@0: 	 variable_name_symtable.pop();
etisserant@0: 	 if (allow_function_overloading) {
etisserant@0: 	   switch (library_element_symtable.find_value($1)) {
etisserant@0: 	     case prev_declared_derived_function_name_token: /* do nothing, already in map. */ break;
etisserant@0: 	     case BOGUS_TOKEN_ID: library_element_symtable.insert($1, prev_declared_derived_function_name_token); break;
etisserant@0: 	     default: ERROR;
etisserant@0: 	   }
etisserant@0: 	 } else {
etisserant@0: 	   library_element_symtable.insert($1, prev_declared_derived_function_name_token);
etisserant@0: 	 }
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for function_declaration */
etisserant@0: /* NOTE: due to reduce/reduce conflicts between identifiers
etisserant@0:  *       being reduced to either a variable or an enumerator value,
etisserant@0:  *       we were forced to keep a symbol table of the names
etisserant@0:  *       of all declared variables. Variables are no longer
etisserant@0:  *       created from simple identifier_token, but from
etisserant@0:  *       prev_declared_variable_name_token.
etisserant@0:  *
etisserant@0:  *       BUT, in functions the function name itself may be used as
etisserant@0:  *       a variable! In order to be able to parse this correctly,
etisserant@0:  *       the token parser (flex) must return a prev_declared_variable_name_token
etisserant@0:  *       when it comes across the function name, while parsing
etisserant@0:  *       the function itself.
etisserant@0:  *       We do this by inserting the function name into the variable
etisserant@0:  *       symbol table, and having flex return a prev_declared_variable_name_token
etisserant@0:  *       whenever it comes across it.
etisserant@0:  *       When we finish parsing the function the variable name
etisserant@0:  *       symbol table is cleared of all entries, and the function
etisserant@0:  *       name is inserted into the library element symbol table. This
etisserant@0:  *       means that from then onwards flex will return a
etisserant@0:  *       derived_function_name_token whenever it comes across the
etisserant@0:  *       function name.
etisserant@0:  *
etisserant@0:  *       In order to insert the function name into the variable_name
etisserant@0:  *       symbol table BEFORE the function body gets parsed, we
etisserant@0:  *       need the parser to reduce a construct that contains the
etisserant@0:  *       the function name. That is why we created this extra
etisserant@0:  *       construct (function_name_declaration), i.e. to force
etisserant@0:  *       the parser to reduce it, before parsing the function body!
etisserant@0:  */
etisserant@0: function_name_declaration:
etisserant@0:   FUNCTION derived_function_name
etisserant@0: 	{$$ = $2;
etisserant@0: 	 /* the function name functions as a
etisserant@0: 	  * variable within the function itself!
etisserant@0: 	  *
etisserant@0: 	  * Remember that the variable_name_symtable
etisserant@0: 	  * is cleared once the end of the function
etisserant@0: 	  * is parsed.
etisserant@0: 	  */
etisserant@0: 	 variable_name_symtable.insert($2, prev_declared_variable_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* intermediate helper symbol for function_declaration */
etisserant@0: io_OR_function_var_declarations_list:
etisserant@0:   /* empty */
etisserant@0: 	{$$ = new var_declarations_list_c();}
etisserant@0: | io_OR_function_var_declarations_list io_var_declarations
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | io_OR_function_var_declarations_list function_var_decls
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: io_var_declarations:
etisserant@0:   input_declarations
etisserant@0: | output_declarations
etisserant@0: | input_output_declarations
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: function_var_decls:
etisserant@0:   VAR CONSTANT var2_init_decl_list END_VAR
etisserant@0: 	{$$ = new function_var_decls_c(new constant_option_c(), $3);}
etisserant@0: | VAR var2_init_decl_list END_VAR
etisserant@0: 	{$$ = new function_var_decls_c(NULL, $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* intermediate helper symbol for function_var_decls */
etisserant@0: var2_init_decl_list:
etisserant@0:   var2_init_decl ';'
etisserant@0: 	{$$ = new var2_init_decl_list_c(); $$->add_element($1);}
etisserant@0: | var2_init_decl_list var2_init_decl ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: function_body:
etisserant@0:   statement_list	{$$ = $1;} /* if we leave it for the default action we get a type clash! */
etisserant@0: | instruction_list	{$$ = $1;} /* if we leave it for the default action we get a type clash! */
etisserant@0: /*
etisserant@0: | ladder_diagram
etisserant@0: | function_block_diagram
etisserant@0: */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: var2_init_decl:
etisserant@0:   var1_init_decl
etisserant@0: | array_var_init_decl
etisserant@0: | structured_var_init_decl
etisserant@0: | string_var_declaration
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*****************************/
etisserant@0: /* B 1.5.2 - Function Blocks */
etisserant@0: /*****************************/
etisserant@0: function_block_type_name:
etisserant@0:   prev_declared_derived_function_block_name
etisserant@0: | standard_function_block_name
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: standard_function_block_name: standard_function_block_name_token {$$ = new identifier_c($1);};
etisserant@0: 
etisserant@0: derived_function_block_name: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: function_block_declaration:
etisserant@0:   FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_FUNCTION_BLOCK
etisserant@0: 	{$$ = new function_block_declaration_c($2, $3, $4);
etisserant@0: 	 library_element_symtable.insert($2, prev_declared_derived_function_block_name_token);
etisserant@0: 	 /* Clear the variable_name_symtable. Since
etisserant@0: 	  * we have finished parsing the function block,
etisserant@0: 	  * the variable names are now out of scope, so
etisserant@0: 	  * are no longer valid!
etisserant@0: 	  */
etisserant@0: 	 variable_name_symtable.pop();
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* intermediate helper symbol for function_declaration */
etisserant@0: /*  { io_var_declarations | other_var_declarations }   */
etisserant@0: /*
etisserant@0:  * NOTE: we re-use the var_declarations_list_c
etisserant@0:  */
etisserant@0: io_OR_other_var_declarations_list:
etisserant@0:   /* empty */
etisserant@0: 	{$$ = new var_declarations_list_c();}
etisserant@0: | io_OR_other_var_declarations_list io_var_declarations
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | io_OR_other_var_declarations_list other_var_declarations
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* NOTE:
etisserant@0:  *  The IEC specification gives the following definition:
etisserant@0:  *  other_var_declarations ::=
etisserant@0:  *     external_var_declarations
etisserant@0:  *   | var_declarations
etisserant@0:  *   | retentive_var_declarations
etisserant@0:  *   | non_retentive_var_declarations
etisserant@0:  *   | temp_var_decls
etisserant@0:  *   | incompl_located_var_declarations
etisserant@0:  *
etisserant@0:  *  Nvertheless, the symbol non_retentive_var_declarations
etisserant@0:  *  is not defined in the spec. This seems to me (Mario)
etisserant@0:  *  to be a typo, so non_retentive_var_declarations
etisserant@0:  *  has been replaced with non_retentive_var_decls
etisserant@0:  *  in the following rule!
etisserant@0:  */
etisserant@0: other_var_declarations:
etisserant@0:   temp_var_decls
etisserant@0: | non_retentive_var_decls
etisserant@0: | external_var_declarations
etisserant@0: | var_declarations
etisserant@0: | retentive_var_declarations
etisserant@0: | incompl_located_var_declarations
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: temp_var_decls:
etisserant@0:   VAR_TEMP temp_var_decls_list END_VAR
etisserant@0: 	{$$ = new temp_var_decls_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* intermediate helper symbol for temp_var_decls */
etisserant@0: temp_var_decls_list:
etisserant@0:   temp_var_decl ';'
etisserant@0: 	{$$ = new temp_var_decls_list_c(); $$->add_element($1);}
etisserant@0: | temp_var_decls_list temp_var_decl ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: non_retentive_var_decls:
etisserant@0:   VAR NON_RETAIN var_init_decl_list END_VAR
etisserant@0: 	{$$ = new non_retentive_var_decls_c($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: function_block_body:
etisserant@0:   statement_list	{$$ = $1;}
etisserant@0: | instruction_list	{$$ = $1;}
etisserant@1: | sequential_function_chart	{$$ = $1;}
etisserant@0: /*
etisserant@0: | ladder_diagram
etisserant@0: | function_block_diagram
etisserant@0: | <other languages>
etisserant@0: */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /**********************/
etisserant@0: /* B 1.5.3 - Programs */
etisserant@0: /**********************/
etisserant@0: program_type_name: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: program_declaration:
etisserant@0:   PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM
etisserant@0: 	{$$ = new program_declaration_c($2, $3, $4);
etisserant@0: 	 library_element_symtable.insert($2, prev_declared_program_type_name_token);
etisserant@0: 	 /* Clear the variable_name_symtable. Since
etisserant@0: 	  * we have finished parsing the program declaration,
etisserant@0: 	  * the variable names are now out of scope, so
etisserant@0: 	  * are no longer valid!
etisserant@0: 	  */
etisserant@0: 	 variable_name_symtable.pop();
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for program_declaration */
etisserant@0: /*
etisserant@0:  * NOTE: we re-use the var_declarations_list_c
etisserant@0:  */
etisserant@0: program_var_declarations_list:
etisserant@0:   /* empty */
etisserant@0: 	{$$ = new var_declarations_list_c();}
etisserant@0: | program_var_declarations_list io_var_declarations
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | program_var_declarations_list other_var_declarations
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | program_var_declarations_list located_var_declarations
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: /*
etisserant@0: | program_var_declarations_list program_access_decls
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* TODO ... */
etisserant@0: /*
etisserant@0: program_access_decls:
etisserant@0:   VAR_ACCESS program_access_decl_list END_VAR
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: /* helper symbol for program_access_decls */
etisserant@0: /*
etisserant@0: program_access_decl_list:
etisserant@0:   program_access_decl ';'
etisserant@0: | program_access_decl_list program_access_decl ';'
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: /*
etisserant@0: program_access_decl:
etisserant@0:   access_name ':' symbolic_variable ':' non_generic_type_name
etisserant@0: | access_name ':' symbolic_variable ':' non_generic_type_name direction
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************************/
etisserant@1: /* B 1.6 Sequential Function Chart elements *
lbessard@3: /********************************************/
etisserant@0: 
etisserant@0: sequential_function_chart:
etisserant@0:   sfc_network
etisserant@1: 	{$$ = new sequential_function_chart_c(); $$->add_element($1);}
etisserant@0: | sequential_function_chart sfc_network
etisserant@1: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: sfc_network:
etisserant@0:   initial_step
etisserant@1: 	{$$ = new sfc_network_c(); $$->add_element($1);}
etisserant@0: | sfc_network step
etisserant@1: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | sfc_network transition
etisserant@1: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | sfc_network action
etisserant@1: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: initial_step:
etisserant@0:   INITIAL_STEP step_name ':' action_association_list END_STEP
mario@13: //  INITIAL_STEP identifier ':' action_association_list END_STEP
etisserant@1: 	{$$ = new initial_step_c($2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: step:
etisserant@0:   STEP step_name ':' action_association_list END_STEP
mario@13: //  STEP identifier ':' action_association_list END_STEP
etisserant@1: 	{$$ = new step_c($2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for:
etisserant@0:  *  - initial_step
etisserant@0:  *  - step
etisserant@1:  */
etisserant@0: action_association_list:
etisserant@1:   /* empty */
etisserant@1: 	{$$ = new action_association_list_c();}
etisserant@0: | action_association_list action_association ';'
etisserant@1: 	{$$ = $1; $$->add_element($2);}
etisserant@1: ;
etisserant@1: 
etisserant@0: 
mario@13: // step_name: identifier;
mario@13: step_name: any_identifier;
etisserant@0: 
etisserant@0: action_association:
etisserant@0:   action_name '(' action_qualifier indicator_name_list ')'
etisserant@1: 	{$$ = new action_association_c($1, $3, $4, NULL);}
etisserant@1: ;
etisserant@1: 
etisserant@1: /* helper symbol for action_association */
etisserant@0: indicator_name_list:
etisserant@1:   /* empty */
etisserant@1: 	{$$ = new indicator_name_list_c();}
etisserant@0: | indicator_name_list ',' indicator_name
etisserant@1: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
mario@13: // action_name: identifier;
mario@13: action_name: any_identifier;
etisserant@0: 
etisserant@0: action_qualifier:
etisserant@1:   /* empty */
etisserant@1: 	{$$ = NULL;}
etisserant@1: | qualifier
etisserant@1: 	{$$ = new action_qualifier_c($1, NULL);}
etisserant@0: | timed_qualifier ',' action_time
etisserant@1: 	{$$ = new action_qualifier_c($1, $3);}
etisserant@1: ;
etisserant@1: 
etisserant@1: qualifier:
etisserant@1: N		{$$ = new qualifier_c(strdup("N"));}
etisserant@1: /* NOTE: the following two clash with the R and S IL operators.
etisserant@1:  * It will have to be handled when we include parsing of SFC...
etisserant@1:  */
etisserant@1: /*
etisserant@1: | R		{$$ = new identifier_c(strdup("R"));}
etisserant@1: | S		{$$ = new identifier_c(strdup("S"));}
etisserant@1: */
etisserant@1: | P		{$$ = new qualifier_c(strdup("P"));}
etisserant@0: ;
etisserant@0: 
etisserant@0: timed_qualifier:
etisserant@1: L		{$$ = new timed_qualifier_c(strdup("L"));}
etisserant@1: | D		{$$ = new timed_qualifier_c(strdup("D"));}
etisserant@1: | SD		{$$ = new timed_qualifier_c(strdup("SD"));}
etisserant@1: | DS		{$$ = new timed_qualifier_c(strdup("DS"));}
etisserant@1: | SL		{$$ = new timed_qualifier_c(strdup("SL"));}
etisserant@0: ;
etisserant@0: 
etisserant@0: action_time:
etisserant@0:   duration
lbessard@10: | variable
lbessard@10: ;
lbessard@10: 
lbessard@10: indicator_name: variable;
etisserant@0: 
mario@13: // transition_name: identifier;
mario@13: transition_name: any_identifier;
mario@13: 
etisserant@0: 
etisserant@0: steps:
etisserant@0:   step_name
etisserant@1: 	{$$ = new steps_c($1, NULL);}
etisserant@0: | '(' step_name_list ')'
etisserant@1: 	{$$ = new steps_c(NULL, $2);}
etisserant@1: ;
etisserant@0: 
etisserant@0: step_name_list:
etisserant@0:   step_name ',' step_name
etisserant@1: 	{$$ = new step_name_list_c(); $$->add_element($1); $$->add_element($3);}
etisserant@0: | step_name_list ',' step_name
etisserant@1: 	{$$ = $1; $$->add_element($3);}
etisserant@1: ;
etisserant@0: 
mario@13: 
lbessard@3: transition_header:
lbessard@3:   TRANSITION FROM steps TO steps
lbessard@3: 	{$$.first = NULL; $$.second = NULL; $$.third = $3; $$.fourth = $5; cmd_goto_body_state();}
lbessard@3: | TRANSITION transition_name FROM steps TO steps 
mario@13: //| TRANSITION identifier FROM steps TO steps 
lbessard@3: 	{$$.first = $2; $$.second = NULL; $$.third = $4; $$.fourth = $6; cmd_goto_body_state();}
lbessard@3: | TRANSITION '(' PRIORITY ASSIGN integer ')' FROM steps TO steps
lbessard@3: 	{$$.first = NULL; $$.second = $5; $$.third = $8; $$.fourth = $10; cmd_goto_body_state();}
lbessard@3: | TRANSITION transition_name '(' PRIORITY ASSIGN integer ')' FROM steps TO steps
mario@13: //| TRANSITION identifier '(' PRIORITY ASSIGN integer ')' FROM steps TO steps
lbessard@3: 	{$$.first = $2; $$.second = $6; $$.third = $9; $$.fourth = $11; cmd_goto_body_state();}
lbessard@3: ;
lbessard@3: 
lbessard@3: transition_condition_il:
lbessard@10:   ':' eol_list simple_instr_list
lbessard@17: 	{$$ = $3;}
lbessard@10: ;
lbessard@3: 
lbessard@3: transition_condition_st:
lbessard@3:   ASSIGN expression ';'
lbessard@17: 	{$$ = $2}
lbessard@10: ;
lbessard@3: 
lbessard@3: transition:
lbessard@3:   transition_header transition_condition_il END_TRANSITION
mario@5:         {$$ = new transition_c($1.first, $1.second, $1.third, $1.fourth, $2, NULL);}
lbessard@3: |  transition_header transition_condition_st END_TRANSITION
mario@5:         {$$ = new transition_c($1.first, $1.second, $1.third, $1.fourth, NULL, $2);}
lbessard@3: ;
lbessard@3: 
lbessard@3: action_header:
lbessard@3:   ACTION action_name ':' 
mario@13: //  ACTION identifier ':' 
lbessard@3: 	{$$.first = $2; cmd_goto_body_state();}
lbessard@3: ;
lbessard@3: 
etisserant@0: 
etisserant@0: action:
lbessard@3:   action_header function_block_body END_ACTION
lbessard@3: 	{$$ = new action_c($1.first, $2);}
etisserant@1: ;
etisserant@1: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 1.7 Configuration elements */
etisserant@0: /********************************/
etisserant@0: /* NOTE:
etisserant@0:  * It is not clear from reading the specification to which namespace
etisserant@0:  * the names of resources, tasks and programs belong to.
etisserant@0:  *
etisserant@0:  * The following syntax assumes that resource and program names belong to the
etisserant@0:  * same namespace as the variables defined within
etisserant@0:  * the resource/configuration (i.e. VAR_GLOBAL).
etisserant@0:  * Task names belong to a namespace all of their own, since they don't
etisserant@0:  * produce conflicts in the syntax parser, so we might just as well
etisserant@0:  * leave them be! ;-)
etisserant@0:  * The above decision was made taking into
etisserant@0:  * account that inside a VAR_CONFIG declaration global variables
etisserant@0:  * may be referenced starting off from the resource name as:
etisserant@0:  *   resource_name.program_name.variable_name
etisserant@0:  * Notice how resource names and program names are used in a very similar
etisserant@0:  * manner as are variable names.
etisserant@0:  * Using a single namespace for all the above mentioned names
etisserant@0:  * also makes it easier to write the syntax parser!! ;-) Using a private
etisserant@0:  * namespace for each of the name types (resource names, program names,
etisserant@0:  * global varaiable names), i.e. letting the names be re-used across
etisserant@0:  * each of the groups (resource, program, global variables), produces
etisserant@0:  * reduce/reduce conflicts in the syntax parser. Actually, it is only
etisserant@0:  * the resource names that need to be distinguished into a 
etisserant@0:  * prev_delcared_resource_name so as not to conflict with [gloabl] variable
etisserant@0:  * names in the 'data' construct.
etisserant@0:  * The program names are only tracked to make sure that two programs do not
etisserant@0:  * get the same name.
etisserant@0:  *
etisserant@0:  * Using a single namespace does have the drawback that the user will
etisserant@0:  * not be able to re-use names for resources or programs if these
etisserant@0:  * have already been used to name a variable!
etisserant@0:  *
etisserant@0:  * If it ever becomes necessary to change this interpretation of
etisserant@0:  * the syntax, then this section of the syntax parser must be updated!
etisserant@0:  */
etisserant@0: prev_declared_global_var_name: prev_declared_global_var_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_resource_name: prev_declared_resource_name_token {$$ = new identifier_c($1);};
etisserant@0: prev_declared_program_name: prev_declared_program_name_token {$$ = new identifier_c($1);};
etisserant@0: // prev_declared_task_name: prev_declared_task_name_token {$$ = new identifier_c($1);};
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: configuration_name: identifier;
etisserant@0: 
etisserant@0: /* NOTE: The specification states that valid resource type names
etisserant@0:  *       are implementation defined, i.e. each implementaion will define
etisserant@0:  *       what resource types it supports.
etisserant@0:  *       We are implementing this syntax parser to be used by any
etisserant@0:  *       implementation, so at the moment we accept any identifier
etisserant@0:  *       as a resource type name.
etisserant@0:  *       This implementation should probably be changed in the future. We
etisserant@0:  *       should probably have a resource_type_name_token, and let the
etisserant@0:  *       implementation load the global symbol library with the
etisserant@0:  *       accepted resource type names before parsing the code.
etisserant@0:  *
etisserant@0:  */
etisserant@0: resource_type_name: any_identifier;
etisserant@0: 
etisserant@0: configuration_declaration:
etisserant@0:   CONFIGURATION configuration_name
etisserant@0:    optional_global_var_declarations
etisserant@0:    single_resource_declaration
etisserant@0:    {variable_name_symtable.pop();}
etisserant@0:    optional_access_declarations
etisserant@0:    optional_instance_specific_initializations
etisserant@0:   END_CONFIGURATION
etisserant@0: 	{$$ = new configuration_declaration_c($2, $3, $4, $6, $7);
etisserant@0: 	 library_element_symtable.insert($2, prev_declared_configuration_name_token);
etisserant@0: 	 variable_name_symtable.pop();
etisserant@0: 	}
etisserant@0: | CONFIGURATION configuration_name
etisserant@0:    optional_global_var_declarations
etisserant@0:    resource_declaration_list
etisserant@0:    optional_access_declarations
etisserant@0:    optional_instance_specific_initializations
etisserant@0:  END_CONFIGURATION
etisserant@0: 	{$$ = new configuration_declaration_c($2, $3, $4, $5, $6);
etisserant@0: 	 library_element_symtable.insert($2, prev_declared_configuration_name_token);
etisserant@0: 	 variable_name_symtable.pop();
etisserant@0: 	}
etisserant@0: | CONFIGURATION error END_CONFIGURATION
etisserant@0: 	{$$ = NULL;
etisserant@0: 	 print_err_msg(current_filename, @2.last_line, "error in configuration declaration.");
etisserant@0: 	 /* yychar */
etisserant@0: 	 yyerrok;
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for
etisserant@0: //  - configuration_declaration
etisserant@0: //  - resource_declaration
etisserant@0: //
etisserant@0: optional_global_var_declarations:
etisserant@0:   // empty
etisserant@0: 	{$$ = NULL;}
etisserant@0: | global_var_declarations
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: // helper symbol for configuration_declaration //
etisserant@0: optional_access_declarations:
etisserant@0:   // empty
etisserant@0: 	{$$ = NULL;}
etisserant@0: //| access_declarations
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for configuration_declaration //
etisserant@0: optional_instance_specific_initializations:
etisserant@0:   // empty
etisserant@0: 	{$$ = NULL;}
etisserant@0: | instance_specific_initializations
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for configuration_declaration //
etisserant@0: resource_declaration_list:
etisserant@0:   resource_declaration
etisserant@0: 	{$$ = new resource_declaration_list_c(); $$->add_element($1);}
etisserant@0: | resource_declaration_list resource_declaration
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: resource_declaration:
etisserant@0:   RESOURCE {variable_name_symtable.push();} resource_name ON resource_type_name
etisserant@0:    optional_global_var_declarations
etisserant@0:    single_resource_declaration
etisserant@0:   END_RESOURCE
etisserant@0: 	{$$ = new resource_declaration_c($3, $5, $6, $7);
mario@13: 	 variable_name_symtable.pop();
etisserant@0: 	 variable_name_symtable.insert($3, prev_declared_resource_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: single_resource_declaration:
etisserant@0:  task_configuration_list program_configuration_list
etisserant@0: 	{$$ = new single_resource_declaration_c($1, $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: // helper symbol for single_resource_declaration //
etisserant@0: task_configuration_list:
etisserant@0:   // empty
etisserant@0: 	{$$ = new task_configuration_list_c();}
etisserant@0: | task_configuration_list task_configuration ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: // helper symbol for single_resource_declaration //
etisserant@0: program_configuration_list:
etisserant@0:   program_configuration ';'
etisserant@0: 	{$$ = new program_configuration_list_c(); $$->add_element($1);}
etisserant@0: | program_configuration_list program_configuration ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: resource_name: identifier;
etisserant@0: 
etisserant@0: /*
etisserant@0: access_declarations:
etisserant@0:  VAR_ACCESS access_declaration_list END_VAR
etisserant@0: 	{$$ = NULL;}
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for access_declarations //
etisserant@0: access_declaration_list:
etisserant@0:   access_declaration ';'
etisserant@0: | access_declaration_list access_declaration ';'
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: access_declaration:
etisserant@0:   access_name ':' access_path ':' non_generic_type_name
etisserant@0: | access_name ':' access_path ':' non_generic_type_name direction
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: access_path:
etisserant@0:   direct_variable
etisserant@0: | prev_delcared_resource_name '.' direct_variable
etisserant@0: | any_fb_name_list symbolic_variable
etisserant@0: | prev_delcared_resource_name '.' any_fb_name_list symbolic_variable
etisserant@0: | prev_delcared_program_name '.'  any_fb_name_list symbolic_variable
etisserant@0: | prev_delcared_resource_name '.' prev_delcared_program_name '.' any_fb_name_list symbolic_variable
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: // helper symbol for
etisserant@0: //  - access_path
etisserant@0: //  - instance_specific_init
etisserant@0: //
etisserant@0: /* NOTE: The fb_name_list refers to funtion block variables
etisserant@0:  *       that have been declared in a scope outside the one we are
etisserant@0:  *       currently parsing, so we must accept them to be any_identifier!
etisserant@0:  *
etisserant@0:  *       Beware that other locations of this syntax parser also require
etisserant@0:  *       a fb_name_list. In those locations the function blocks are being declared,
etisserant@0:  *       so only currently un-used identifiers (i.e. identifier) may be accepted.
etisserant@0:  *
etisserant@0:  *       In order to distinguish the two, here we use any_fb_name_list, while
etisserant@0:  *       in the the locations we simply use fb_name_list!
etisserant@0:  */
etisserant@0: any_fb_name_list:
etisserant@0:   // empty
etisserant@0: 	{$$ = new any_fb_name_list_c();}
etisserant@0: //| fb_name_list fb_name '.'
etisserant@0: | any_fb_name_list any_identifier '.'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: global_var_reference:
etisserant@0: //  [resource_name '.'] global_var_name ['.' structure_element_name] //
etisserant@0:                                   prev_declared_global_var_name
etisserant@0: 	{$$ = new global_var_reference_c(NULL, $1, NULL);}
etisserant@0: |                                 prev_declared_global_var_name '.' structure_element_name
etisserant@0: 	{$$ = new global_var_reference_c(NULL, $1, $3);}
etisserant@0: | prev_declared_resource_name '.' prev_declared_global_var_name
etisserant@0: 	{$$ = new global_var_reference_c($1, $3, NULL);}
etisserant@0: | prev_declared_resource_name '.' prev_declared_global_var_name '.' structure_element_name
etisserant@0: 	{$$ = new global_var_reference_c($1, $3, $5);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: //access_name: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: program_output_reference:
etisserant@0: /* NOTE:
etisserant@0:  * program_output_reference is merely used within data_source.
etisserant@0:  * data_source is merely used within task_initialization
etisserant@0:  * task_initialization appears in a configuration declaration
etisserant@0:  * _before_ the programs are declared, so we cannot use
etisserant@0:  * prev_declared_program_name, as what might seem correct at first.
etisserant@0:  *
etisserant@0:  * The semantic checker must later check whether the identifier
etisserant@0:  * used really refers to a program declared after the task
etisserant@0:  * initialization!
etisserant@0:  */
etisserant@0: //  prev_declared_program_name '.' symbolic_variable
etisserant@0:   program_name '.' symbolic_variable
etisserant@0: 	{$$ = new program_output_reference_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: program_name: identifier;
etisserant@0: 
etisserant@0: /*
etisserant@0: direction:
etisserant@0:   READ_WRITE
etisserant@0: 	{$$ = NULL;}
etisserant@0: | READ_ONLY
etisserant@0: 	{$$ = NULL;}
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: task_configuration:
etisserant@0:   TASK task_name task_initialization
etisserant@0: 	{$$ = new task_configuration_c($2, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* NOTE: The specification does nopt mention the namespace to which task names
etisserant@0:  *       should belong to. Unlike resource and program names, for the moment we
etisserant@0:  *       let the task names belong to their own private namespace, as they do not
etisserant@0:  *       produce any conflicts in the syntax parser.
etisserant@0:  *       If in the future our interpretation of the spec. turns out to be incorrect,
etisserant@0:  *       the definition of task_name may have to be changed!
etisserant@0:  */
etisserant@0: task_name: any_identifier;
etisserant@0: 
etisserant@0: task_initialization:
etisserant@0: //  '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' //
etisserant@0:   '(' PRIORITY ASSIGN integer ')'
etisserant@0: 	{$$ = new task_initialization_c(NULL, NULL, $4);}
etisserant@0: | '(' SINGLE ASSIGN data_source ','   PRIORITY ASSIGN integer ')'
etisserant@0: 	{$$ = new task_initialization_c($4, NULL, $8);}
etisserant@0: | '(' INTERVAL ASSIGN data_source ',' PRIORITY ASSIGN integer ')'
etisserant@0: 	{$$ = new task_initialization_c(NULL, $4, $8);}
etisserant@0: | '(' SINGLE ASSIGN data_source ',' INTERVAL ASSIGN data_source ',' PRIORITY ASSIGN integer ')'
etisserant@0: 	{$$ = new task_initialization_c($4, $8, $12);}
etisserant@0: ;
etisserant@0: 
etisserant@0: data_source:
etisserant@0:   constant
etisserant@0: | global_var_reference
etisserant@0: | program_output_reference
etisserant@0: | direct_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: program_configuration:
etisserant@0: //  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] //
etisserant@0:   PROGRAM program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements
etisserant@0: 	{$$ = new program_configuration_c(NULL, $2, $3, $5, $6);
etisserant@0: 	 variable_name_symtable.insert($2, prev_declared_program_name_token);
etisserant@0: 	}
etisserant@0: | PROGRAM RETAIN program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements
etisserant@0: 	{$$ = new program_configuration_c(new retain_option_c(), $3, $4, $6, $7);
etisserant@0: 	 variable_name_symtable.insert($3, prev_declared_program_name_token);
etisserant@0: 	}
etisserant@0: | PROGRAM NON_RETAIN program_name optional_task_name ':' prev_declared_program_type_name optional_prog_conf_elements
etisserant@0: 	{$$ = new program_configuration_c(new non_retain_option_c(), $3, $4, $6, $7);
etisserant@0: 	 variable_name_symtable.insert($3, prev_declared_program_name_token);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for program_configuration //
etisserant@0: optional_task_name:
etisserant@0:   // empty //
etisserant@0: 	{$$ = NULL;}
etisserant@0: | WITH task_name
etisserant@0: 	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for program_configuration //
etisserant@0: optional_prog_conf_elements:
etisserant@0:   // empty //
etisserant@0: 	{$$ = NULL;}
etisserant@0: | '(' prog_conf_elements ')'
etisserant@0: 	{$$ = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: prog_conf_elements:
etisserant@0:   prog_conf_element
etisserant@0: 	{$$ = new prog_conf_elements_c(); $$->add_element($1);}
etisserant@0: | prog_conf_elements ',' prog_conf_element
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: prog_conf_element:
etisserant@0:   fb_task
etisserant@0: | prog_cnxn
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: fb_task:
etisserant@0:   // fb_name WITH task_name
etisserant@0: /* NOTE: The fb_name refers to funtion block variables
etisserant@0:  *       that have been declared in a scope outside the one we are
etisserant@0:  *       currently parsing, so we must accept them to be any_identifier!
etisserant@0:  */
etisserant@0:   any_identifier WITH task_name
etisserant@0: 	{$$ = new fb_task_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE:
etisserant@0:  *  The semantics of configuring a program are rather confusing, so here is
etisserant@0:  *  my (Mario) understanding on the issue...
etisserant@0:  *
etisserant@0:  *  A function/program may have as its input variables a simple variable
etisserant@0:  *  (BYTE, WORD, etc...), an array (ARRAY [1 .. 3] OF BYTE, ...) , or a structure.
etisserant@0:  *  Nevertheless, when calling this function from within a st or il language statement
etisserant@0:  *  it is not possible to allocate a value to a single element of the array or structure
etisserant@0:  *  typed input variable, as the accepted syntax is simply '(' variable_name ':=' variable ')'
etisserant@0:  *  Notice how the variable_name does not include things such as 'a.elem1' or 'a[1]'!
etisserant@0:  *
etisserant@0:  *  Nevertheless, when configuring a program from within a configuration,
etisserant@0:  *  it becomes possible to allocate values to individual elements of the
etisserant@0:  *  array or structured type input variable, as the syntax is now
etisserant@0:  *  '(' symbolic_variable ':=' data_sink|prog_data_source ')'
etisserant@0:  *  Notice how the symbolic_variable _does_ include things such as 'a.elem1' or 'a[1]'!
etisserant@0:  *
etisserant@0:  *  Conclusion: Unlike other locations in the syntax where SENDTO appears,
etisserant@0:  *  here it is not valid to replace symbolic_variable with any_identifier!
etisserant@0:  *  Nevertheless, it is also not correct to leave symbolic_variable as it is,
etisserant@0:  *  as we have defined it to only include previously declared variables,
etisserant@0:  *  which is not the case in this situation. Here symbolic_variable is refering
etisserant@0:  *  to variables that were defined within the scope of the program that is being
etisserant@0:  *  called, and _not_ within the scope of the configuration that is calling the
etisserant@0:  *  program, so the variables in question are not declared in the current scope!
etisserant@0:  *
etisserant@0:  *  We therefore need to define a new symbolic_variable, that accepts any_identifier
etisserant@0:  *  instead of previosuly declared variable names, to be used in the definition of
etisserant@0:  *  prog_cnxn!
etisserant@0:  */
etisserant@0: prog_cnxn:
etisserant@0:   any_symbolic_variable ASSIGN prog_data_source
etisserant@0: 	{$$ = new prog_cnxn_assign_c($1, $3);}
etisserant@0: | any_symbolic_variable SENDTO data_sink
etisserant@0: 	{$$ = new prog_cnxn_sendto_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: prog_data_source:
etisserant@0:   constant
etisserant@0: | enumerated_value
etisserant@0: | global_var_reference
etisserant@0: | direct_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: data_sink:
etisserant@0:   global_var_reference
etisserant@0: | direct_variable
etisserant@0: ;
etisserant@0: 
etisserant@0: instance_specific_initializations:
etisserant@0:  VAR_CONFIG instance_specific_init_list END_VAR
etisserant@0: 	{$$ = new instance_specific_initializations_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: // helper symbol for instance_specific_initializations //
etisserant@0: instance_specific_init_list:
etisserant@0:   instance_specific_init ';'
etisserant@0: 	{$$ = new instance_specific_init_list_c(); $$->add_element($1);}
etisserant@0: | instance_specific_init_list instance_specific_init ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: instance_specific_init:
etisserant@0: //
etisserant@0: //  resource_name '.' program_name '.' {fb_name '.'}
etisserant@0: //  ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' function_block_type_name ':=' structure_initialization))
etisserant@0: //
etisserant@0: //  prev_declared_resource_name '.' prev_declared_program_name '.' any_fb_name_list variable_name ':' located_var_spec_init
etisserant@0: /* NOTE: variable_name has been changed to any_identifier (and not simply identifier) because the
etisserant@0:  *       variables being referenced have been declared outside the scope currently being parsed!
etisserant@0:  */
etisserant@0: /* NOTE: program_name has not been changed to prev_declared_program_name because the
etisserant@0:  *       programs being referenced have been declared outside the scope currently being parsed!
etisserant@0:  *       The programs are only kept inside the scope of the resource in which they are defined.
etisserant@0:  */
etisserant@0:   prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier ':' located_var_spec_init
etisserant@0: 	{$$ = new instance_specific_init_c($1, $3, $5, $6, NULL, $8);}
etisserant@0: | prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier location ':' located_var_spec_init
etisserant@0: 	{$$ = new instance_specific_init_c($1, $3, $5, $6, $7, $9);}
etisserant@0: | prev_declared_resource_name '.' program_name '.' any_fb_name_list any_identifier ':' fb_initialization
etisserant@0: 	{$5->add_element($6); $$ = new instance_specific_init_c($1, $3, $5, NULL, NULL, $8);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for instance_specific_init */
etisserant@0: fb_initialization:
etisserant@0:   function_block_type_name ASSIGN structure_initialization
etisserant@0: 	{$$ = new fb_initialization_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /***********************************/
etisserant@0: /* B 2.1 Instructions and Operands */
etisserant@0: /***********************************/
etisserant@0: /* helper symbol for many IL instructions, etc... */
etisserant@0: /* eat up any extra EOL tokens... */
etisserant@0: 
etisserant@0: eol_list:
etisserant@0:   EOL
etisserant@0: | eol_list EOL
etisserant@0: ;
etisserant@0: 
etisserant@0: /*
etisserant@0: eol_list:
etisserant@0:   '\n'
etisserant@0: | eol_list '\n'
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: instruction_list:
etisserant@0:   il_instruction
etisserant@0: 	{$$ = new instruction_list_c(); $$->add_element($1);}
mario@13: | pragma eol_list
mario@13: 	{$$ = new instruction_list_c(); $$->add_element($1);}
etisserant@0: | instruction_list il_instruction
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | instruction_list pragma
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | instruction_list error
etisserant@0: 	{$$ = $1;
etisserant@0: 	 print_err_msg(current_filename, @2.last_line, "error in IL instruction.");
etisserant@0: 	 /* yychar */
etisserant@0: 	 yyerrok;
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: il_instruction:
etisserant@0:   il_incomplete_instruction eol_list
etisserant@0: 	{$$ = new il_instruction_c(NULL, $1);}
etisserant@0: | label ':' il_incomplete_instruction eol_list
etisserant@0: 	{$$ = new il_instruction_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for il_instruction */
etisserant@0: il_incomplete_instruction:
etisserant@0:   il_simple_operation
etisserant@0: | il_expression
etisserant@0: | il_jump_operation
etisserant@0: | il_fb_call
etisserant@0: | il_formal_funct_call
etisserant@0: | il_return_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: label: identifier;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: il_simple_operation:
etisserant@0:   il_simple_operator
etisserant@0: 	{$$ = new il_simple_operation_c($1, NULL);}
etisserant@0: | il_simple_operator_noclash il_operand
etisserant@0: 	{$$ = new il_simple_operation_c($1, $2);}
etisserant@0: | il_simple_operator_clash_il_operand
etisserant@0: 	{$$ = new il_simple_operation_c($1.first, $1.second);}
etisserant@0: /* NOTE: the line
etisserant@0:  *         | il_simple_operator
etisserant@0:  *       already contains the 'NOT' operator, as well as all the
etisserant@0:  *       expression operators ('MOD', 'AND', etc...), all of which
etisserant@0:  *       may also be a function name! This means that these operators/functions,
etisserant@0:  *       without any operands, could be reduced to either an operator or a
etisserant@0:  *       function call. I (Mario) have chosen to reduce it to an operator.
etisserant@0:  *
etisserant@0:  *       The line
etisserant@0:  *         | function_name
etisserant@0:  *       has been replaced with the lines
etisserant@0:  *         | function_name_no_clashes
etisserant@0:  *       in order to include all possible function names except
etisserant@0:  *       those whose names coincide with operators !!
etisserant@0:  */
etisserant@0: | function_name_no_clashes
etisserant@0: 	{$$ = new il_function_call_c($1, NULL);}
etisserant@0: /* NOTE: the line
etisserant@0:  *         | il_simple_operator il_operand
etisserant@0:  *       already contains the 'NOT', 'MOD', etc. operators, followed by a single il_operand,
etisserant@0:  *       which may also be reduced to a function name with an operand_list of a single
etisserant@0:  *       il_operand! This would lead us to a reduce/reduce conflict!
etisserant@0:  *
etisserant@0:  *       I (Mario) have chosen to reduce it to an operand, rather than a function call.
etisserant@0:  *
etisserant@0:  *       The line
etisserant@0:  *         | function_name il_operand_list
etisserant@0:  *       has been replaced with the line
etisserant@0:  *         | function_name_no_clashes il_operand_list
etisserant@0:  *       in order to include all possible function names except
etisserant@0:  *       for the function names which clash with expression and simple operators.
etisserant@0:  *
etisserant@0:  *       Note that:
etisserant@0:  *       this alternative syntax does not cover the possibility of
etisserant@0:  *       the function 'NOT', 'MOD', etc... being called with more than one il_operand!
etisserant@0:  *       We therefore need to include an extra rule where the
etisserant@0:  *       function_name_expression_clashes and function_name_simpleop_clashes
etisserant@0:  *       are followed by a il_operand_list with __two__ or more il_operands!!
etisserant@0:  */
etisserant@0: | function_name_no_clashes il_operand_list
etisserant@0: 	{$$ = new il_function_call_c($1, $2);}
etisserant@0: | il_simple_operator_clash_il_operand ',' il_operand_list
etisserant@0: 	{list_c *list = new il_operand_list_c();
etisserant@0: 	 list->add_element($1.second);
etisserant@0: 	 FOR_EACH_ELEMENT(elem, $3, {list->add_element(elem);})
etisserant@0: 	 $$ = new il_function_call_c(il_operator_c_2_identifier_c($1.first), list);
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: il_simple_operator_clash_il_operand:
etisserant@0:   il_simple_operator_clash il_operand
etisserant@0: 	{$$.first = $1; $$.second = $2;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: il_expression:
etisserant@0:   il_expr_operator_noclash '(' eol_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, NULL, NULL);}
etisserant@0: | il_expr_operator_noclash '(' il_operand eol_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, $3, NULL);}
etisserant@0: | il_expr_operator_noclash '(' eol_list simple_instr_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, NULL, $4);}
etisserant@0: | il_expr_operator_noclash '(' il_operand eol_list simple_instr_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, $3, $5);}
etisserant@0: /*
etisserant@0: */
etisserant@0: | il_expr_operator_clash '(' eol_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, NULL, NULL);}
etisserant@0: | il_expr_operator_clash '(' il_operand eol_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, $3, NULL);}
etisserant@0: | il_expr_operator_clash '(' il_operand eol_list simple_instr_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, $3, $5);}
etisserant@0: /*
etisserant@0: */
etisserant@0: | il_expr_operator_clash_eol_list simple_instr_list ')'
etisserant@0: 	{$$ = new il_expression_c($1, NULL, $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_jump_operation:
etisserant@0:   il_jump_operator label
etisserant@0: 	{$$ = new il_jump_operation_c($1, $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_fb_call:
etisserant@0:   il_call_operator prev_declared_fb_name
etisserant@0: 	{$$ = new il_fb_call_c($1, $2, NULL, NULL);}
etisserant@0: | il_call_operator prev_declared_fb_name '(' ')'
etisserant@0: 	{$$ = new il_fb_call_c($1, $2, NULL, NULL);}
etisserant@0: | il_call_operator prev_declared_fb_name '(' eol_list ')'
etisserant@0: 	{$$ = new il_fb_call_c($1, $2, NULL, NULL);}
etisserant@0: | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
etisserant@0: 	{$$ = new il_fb_call_c($1, $2, $4, NULL);}
etisserant@0: | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
etisserant@0: 	{$$ = new il_fb_call_c($1, $2, NULL, $5);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE: Please read note above the definition of function_name_without_clashes */
etisserant@0: il_formal_funct_call:
etisserant@0: /*  function_name '(' eol_list ')'  */
etisserant@0: /* NOTE: il_formal_funct_call is only used in the definition of
etisserant@0:  *         - il_incomplete_instruction
etisserant@0:  *         - il_simple_instruction
etisserant@0:  *       In both of the above, il_expression also
etisserant@0:  *       shows up as another option. This means that the functions whose
etisserant@0:  *       names clash with expressions, followed by '(' eol_list ')', are
etisserant@0:  *       already included. We must therefore leave them out in this
etisserant@0:  *       definition in order to remove reduce/reduce conflicts.
etisserant@0:  *
etisserant@0:  *       In summary: 'MOD' '(' eol_list ')', and all other functions whose
etisserant@0:  *       names clash with expressions may be interpreted by the syntax by
etisserant@0:  *       two different routes. I (Mario) chose to interpret them
etisserant@0:  *       as operators, rather than as function calls!
etisserant@0:  */
etisserant@0:   function_name_no_clashes '(' eol_list ')'
etisserant@0: 	{$$ = new il_formal_funct_call_c($1, NULL);}
etisserant@0: | function_name_simpleop_clashes '(' eol_list ')'
etisserant@0: 	{$$ = new il_formal_funct_call_c($1, NULL);}
etisserant@0: /* | function_name '(' eol_list il_param_list ')' */
etisserant@0: | function_name_no_clashes '(' eol_list il_param_list ')'
etisserant@0: 	{$$ = new il_formal_funct_call_c($1, $4);}
etisserant@0: | function_name_simpleop_clashes '(' eol_list il_param_list ')'
etisserant@0: 	{$$ = new il_formal_funct_call_c($1, $4);}
etisserant@0: /* the function_name_expression_clashes had to be first reduced to
etisserant@0:  * an intermediary symbol in order to remove a reduce/reduce conflict.
etisserant@0:  * In essence, the syntax requires more than one look ahead token
etisserant@0:  * in order to be parsed. We resolve this by reducing a collection of
etisserant@0:  * symbols into a temporary symbol (il_expr_operator_clash_eol_list), that
etisserant@0:  * will later be replaced by the correct symbol. The correct symbol will
etisserant@0:  * now be determined by a single look ahead token, as all the common
etisserant@0:  * symbols have been reduced to the temporary symbol
etisserant@0:  * il_expr_operator_clash_eol_list !
etisserant@0:  *
etisserant@0:  * Unfortunately, this work around results in the wrong symbol
etisserant@0:  * being created for the abstract syntax tree.
etisserant@0:  * We need to figure out which symbol was created, destroy it,
etisserant@0:  * and create the correct symbol for our case.
etisserant@0:  * This is a lot of work, so I put it in a function
etisserant@0:  * at the end of this file... il_operator_c_2_identifier_c()
etisserant@0:  */
etisserant@0: | il_expr_operator_clash_eol_list il_param_list ')'
etisserant@0: 	{$$ = new il_formal_funct_call_c(il_operator_c_2_identifier_c($1), $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_expr_operator_clash_eol_list:
etisserant@0:   il_expr_operator_clash '(' eol_list
etisserant@0: 	{$$ = $1;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
mario@13: /* NOTE: We use enumerated_value_without_identifier instead of enumerated_value
mario@13:  *       in order to remove a reduce/reduce conflict between reducing an
mario@13:  *       identifier to a variable or an enumerated_value.
mario@13:  */
etisserant@0: il_operand:
etisserant@0:   variable
mario@13: | enumerated_value_without_identifier
etisserant@0: | constant
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_operand_list:
etisserant@0:   il_operand
etisserant@0: 	{$$ = new il_operand_list_c(); $$->add_element($1);}
etisserant@0: | il_operand_list ',' il_operand
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: simple_instr_list:
etisserant@0:   il_simple_instruction
etisserant@0: 	{$$ = new simple_instr_list_c(); $$->add_element($1);}
etisserant@0: | simple_instr_list il_simple_instruction
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_simple_instruction:
etisserant@0:   il_simple_operation eol_list
etisserant@0: | il_expression eol_list
etisserant@0: | il_formal_funct_call eol_list
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE: the correct definition of il_param_list is
etisserant@0:  * il_param_list ::= {il_param_instruction} il_param_last_instruction
etisserant@0:  *
etisserant@0:  * where {...} denotes zero or many il_param_instruction's.
etisserant@0:  *
etisserant@0:  * We could do this by defining the following:
etisserant@0:  * il_param_list: il_param_instruction_list il_param_last_instruction;
etisserant@0:  * il_param_instruction_list : ** empty ** | il_param_instruction_list il_param_instruction;
etisserant@0:  *
etisserant@0:  * Unfortunately, the above leads to reduce/reduce conflicts.
etisserant@0:  * The chosen alternative (as follows) does not have any conflicts!
etisserant@0:  * il_param_list: il_param_last_instruction | il_param_instruction_list il_param_last_instruction;
etisserant@0:  * il_param_instruction_list : il_param_instruction_list | il_param_instruction_list il_param_instruction;
etisserant@0:  */
etisserant@0: il_param_list:
etisserant@0:   il_param_instruction_list il_param_last_instruction
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | il_param_last_instruction
etisserant@0: 	{$$ = new il_param_list_c(); $$->add_element($1);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* Helper symbol for il_param_list */
etisserant@0: il_param_instruction_list:
etisserant@0:   il_param_instruction
etisserant@0: 	{$$ = new il_param_list_c(); $$->add_element($1);}
etisserant@0: | il_param_instruction_list il_param_instruction
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_param_instruction:
etisserant@0:   il_param_assignment ',' eol_list
etisserant@0: | il_param_out_assignment ',' eol_list
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_param_last_instruction:
etisserant@0:   il_param_assignment eol_list
etisserant@0: | il_param_out_assignment eol_list
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_param_assignment:
etisserant@0:   il_assign_operator il_operand
etisserant@0: 	{$$ = new il_param_assignment_c($1, $2, NULL);}
etisserant@0: | il_assign_operator '(' eol_list simple_instr_list ')'
etisserant@0: 	{$$ = new il_param_assignment_c($1, NULL, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_param_out_assignment:
etisserant@0:   il_assign_out_operator variable
etisserant@0: 	{$$ = new il_param_out_assignment_c($1, $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*******************/
etisserant@0: /* B 2.2 Operators */
etisserant@0: /*******************/
etisserant@0: sendto_identifier: sendto_identifier_token {$$ = new identifier_c($1);};
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE:
etisserant@0:  *  The spec includes the operator 'EQ '
etisserant@0:  * Note that EQ is followed by a space.
etisserant@0:  * I am considering this a typo, and defining the operator
etisserant@0:  * as 'EQ'
etisserant@0:  * (Mario)
etisserant@0:  */
etisserant@0: LD_operator: 		LD 	{$$ = new LD_operator_c();};
etisserant@0: LDN_operator: 		LDN 	{$$ = new LDN_operator_c();};
etisserant@0: ST_operator: 		ST 	{$$ = new ST_operator_c();};
etisserant@0: STN_operator: 		STN 	{$$ = new STN_operator_c();};
etisserant@0: NOT_operator: 		NOT 	{$$ = new NOT_operator_c();};
etisserant@0: S_operator: 		S 	{$$ = new S_operator_c();};
etisserant@0: R_operator: 		R 	{$$ = new R_operator_c();};
etisserant@0: S1_operator: 		S1 	{$$ = new S1_operator_c();};
etisserant@0: R1_operator: 		R1 	{$$ = new R1_operator_c();};
etisserant@0: CLK_operator: 		CLK 	{$$ = new CLK_operator_c();};
etisserant@0: CU_operator: 		CU 	{$$ = new CU_operator_c();};
etisserant@0: CD_operator: 		CD 	{$$ = new CD_operator_c();};
etisserant@0: PV_operator: 		PV 	{$$ = new PV_operator_c();};
etisserant@0: IN_operator: 		IN 	{$$ = new IN_operator_c();};
etisserant@0: PT_operator: 		PT 	{$$ = new PT_operator_c();};
etisserant@0: AND_operator: 		AND 	{$$ = new AND_operator_c();};
etisserant@0: AND2_operator: 		AND2 	{$$ = new AND_operator_c();}; /* '&' in the source code! */
etisserant@0: OR_operator: 		OR 	{$$ = new OR_operator_c();};
etisserant@0: XOR_operator: 		XOR 	{$$ = new XOR_operator_c();};
etisserant@0: ANDN_operator: 		ANDN 	{$$ = new ANDN_operator_c();};
etisserant@0: ANDN2_operator:		ANDN2 	{$$ = new ANDN_operator_c();}; /* '&N' in the source code! */
etisserant@0: ORN_operator: 		ORN 	{$$ = new ORN_operator_c();};
etisserant@0: XORN_operator: 		XORN 	{$$ = new XORN_operator_c();};
etisserant@0: ADD_operator: 		ADD 	{$$ = new ADD_operator_c();};
etisserant@0: SUB_operator: 		SUB 	{$$ = new SUB_operator_c();};
etisserant@0: MUL_operator: 		MUL 	{$$ = new MUL_operator_c();};
etisserant@0: DIV_operator: 		DIV 	{$$ = new DIV_operator_c();};
etisserant@0: MOD_operator: 		MOD 	{$$ = new MOD_operator_c();};
etisserant@0: GT_operator: 		GT 	{$$ = new GT_operator_c();};
etisserant@0: GE_operator: 		GE 	{$$ = new GE_operator_c();};
etisserant@0: EQ_operator: 		EQ 	{$$ = new EQ_operator_c();};
etisserant@0: LT_operator: 		LT 	{$$ = new LT_operator_c();};
etisserant@0: LE_operator: 		LE 	{$$ = new LE_operator_c();};
etisserant@0: NE_operator: 		NE 	{$$ = new NE_operator_c();};
etisserant@0: CAL_operator: 		CAL 	{$$ = new CAL_operator_c();};
etisserant@0: CALC_operator: 		CALC 	{$$ = new CALC_operator_c();};
etisserant@0: CALCN_operator: 	CALCN 	{$$ = new CALCN_operator_c();};
etisserant@0: RET_operator: 		RET 	{$$ = new RET_operator_c();};
etisserant@0: RETC_operator: 		RETC 	{$$ = new RETC_operator_c();};
etisserant@0: RETCN_operator: 	RETCN 	{$$ = new RETCN_operator_c();};
etisserant@0: JMP_operator: 		JMP 	{$$ = new JMP_operator_c();};
etisserant@0: JMPC_operator: 		JMPC 	{$$ = new JMPC_operator_c();};
etisserant@0: JMPCN_operator: 	JMPCN 	{$$ = new JMPCN_operator_c();};
etisserant@0: 
etisserant@0: /*
etisserant@0:  MAY CONFLICT WITH STANDARD FUNCTION NAMES!!!
etisserant@0: 
etisserant@0: NOT_operator: NOT {new NOT_operator_c();};
etisserant@0: 
etisserant@0: AND_operator: AND {new AND_operator_c();};
etisserant@0: OR_operator: OR {new OR_operator_c();};
etisserant@0: XOR_operator: XOR {new XOR_operator_c();};
etisserant@0: 
etisserant@0: ADD_operator: ADD {new ADD_operator_c();};
etisserant@0: SUB_operator: SUB {new SUB_operator_c();};
etisserant@0: MUL_operator: MUL {new MUL_operator_c();};
etisserant@0: DIV_operator: DIV {new DIV_operator_c();};
etisserant@0: MOD_operator: MOD {new MOD_operator_c();};
etisserant@0: 
etisserant@0: GT_operator: GT {new GT_operator_c();};
etisserant@0: GE_operator: GE {new GE_operator_c();};
etisserant@0: EQ_operator: EQ {new EQ_operator_c();};
etisserant@0: LT_operator: LT {new LT_operator_c();};
etisserant@0: LE_operator: LE {new LE_operator_c();};
etisserant@0: NE_operator: NE {new NE_operator_c();};
etisserant@0: */
etisserant@0: 
etisserant@0: 
etisserant@0: il_simple_operator:
etisserant@0:   il_simple_operator_clash
etisserant@0: | il_simple_operator_noclash
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_simple_operator_noclash:
etisserant@0:   LD_operator
etisserant@0: | LDN_operator
etisserant@0: | ST_operator
etisserant@0: | STN_operator
etisserant@0: | S_operator
etisserant@0: | R_operator
etisserant@0: | S1_operator
etisserant@0: | R1_operator
etisserant@0: | CLK_operator
etisserant@0: | CU_operator
etisserant@0: | CD_operator
etisserant@0: | PV_operator
etisserant@0: | IN_operator
etisserant@0: | PT_operator
etisserant@0: | il_expr_operator_noclash
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_simple_operator_clash:
etisserant@0:   il_simple_operator_clash1
etisserant@0: | il_simple_operator_clash2
etisserant@0: ;
etisserant@0: 
etisserant@0: il_simple_operator_clash1:
etisserant@0:   NOT_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: il_simple_operator_clash2:
etisserant@0:   il_expr_operator_clash
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /*
etisserant@0: il_expr_operator:
etisserant@0:   il_expr_operator_noclash
etisserant@0: | il_expr_operator_clash
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: il_expr_operator_clash:
etisserant@0:   AND_operator
etisserant@0: | OR_operator
etisserant@0: | XOR_operator
etisserant@0: | ADD_operator
etisserant@0: | SUB_operator
etisserant@0: | MUL_operator
etisserant@0: | DIV_operator
etisserant@0: | MOD_operator
etisserant@0: | GT_operator
etisserant@0: | GE_operator
etisserant@0: | EQ_operator
etisserant@0: | LT_operator
etisserant@0: | LE_operator
etisserant@0: | NE_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_expr_operator_noclash:
etisserant@0:   ANDN_operator
etisserant@0: | ANDN2_operator  /* string '&N' in source code! */
etisserant@0: | AND2_operator  /* string '&' in source code! */
etisserant@0: | ORN_operator
etisserant@0: | XORN_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: il_assign_operator:
etisserant@0: /*  variable_name ASSIGN */
etisserant@0:   any_identifier ASSIGN
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_assign_out_operator:
etisserant@0: /*  variable_name SENDTO */
etisserant@0: /*  any_identifier SENDTO */
etisserant@0:   sendto_identifier SENDTO
etisserant@0: 	{$$ = new il_assign_out_operator_c(NULL, $1);}
etisserant@0: /*| NOT variable_name SENDTO */
etisserant@0: | NOT sendto_identifier SENDTO
etisserant@0: 	{$$ = new il_assign_out_operator_c(new not_paramassign_c(), $2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_call_operator:
etisserant@0:   CAL_operator
etisserant@0: | CALC_operator
etisserant@0: | CALCN_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_return_operator:
etisserant@0:   RET_operator
etisserant@0: | RETC_operator
etisserant@0: | RETCN_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: il_jump_operator:
etisserant@0:   JMP_operator
etisserant@0: | JMPC_operator
etisserant@0: | JMPCN_operator
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /***********************/
etisserant@0: /* B 3.1 - Expressions */
etisserant@0: /***********************/
etisserant@0: expression:
etisserant@0:   xor_expression
etisserant@0: | expression OR xor_expression
etisserant@0: 	{$$ = new or_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: xor_expression:
etisserant@0:   and_expression
etisserant@0: | xor_expression XOR and_expression
etisserant@0: 	{$$ = new xor_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: and_expression:
etisserant@0:   comparison
etisserant@0: | and_expression '&' comparison
etisserant@0: 	{$$ = new and_expression_c($1, $3);}
etisserant@0: | and_expression AND comparison
etisserant@0: 	{$$ = new and_expression_c($1, $3);}
etisserant@0: /* NOTE: The lexical parser never returns the token '&'.
etisserant@0:  *       The '&' string is interpreted by the lexcial parser as the token
etisserant@0:  *       AND2!
etisserant@0:  *       This means that the first rule with '&' is actually not required,
etisserant@0:  *       but we leave it in nevertheless just in case we later decide
etisserant@0:  *       to remove theh AND2 token...
etisserant@0:  */
etisserant@0: | and_expression AND2 comparison
etisserant@0: 	{$$ = new and_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: comparison:
etisserant@0:   equ_expression
etisserant@0: | comparison '=' equ_expression
etisserant@0: 	{$$ = new equ_expression_c($1, $3);}
etisserant@0: | comparison OPER_NE equ_expression
etisserant@0: 	{$$ = new notequ_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: equ_expression:
etisserant@0:   add_expression
etisserant@0: | equ_expression '<' add_expression
etisserant@0: 	{$$ = new lt_expression_c($1, $3);}
etisserant@0: | equ_expression '>' add_expression
etisserant@0: 	{$$ = new gt_expression_c($1, $3);}
etisserant@0: | equ_expression OPER_LE add_expression
etisserant@0: 	{$$ = new le_expression_c($1, $3);}
etisserant@0: | equ_expression OPER_GE add_expression
etisserant@0: 	{$$ = new ge_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* Not required...
etisserant@0: comparison_operator: '<' | '>' | '>=' '<='
etisserant@0: */
etisserant@0: 
etisserant@0: add_expression:
etisserant@0:   term
etisserant@0: | add_expression '+' term
etisserant@0: 	{$$ = new add_expression_c($1, $3);}
etisserant@0: | add_expression '-' term
etisserant@0: 	{$$ = new sub_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* Not required...
etisserant@0: add_operator: '+' | '-'
etisserant@0: */
etisserant@0: 
etisserant@0: term:
etisserant@0:   power_expression
etisserant@0: | term '*' power_expression
etisserant@0: 	{$$ = new mul_expression_c($1, $3);}
etisserant@0: | term '/' power_expression
etisserant@0: 	{$$ = new div_expression_c($1, $3);}
etisserant@0: | term MOD power_expression
etisserant@0: 	{$$ = new mod_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* Not required...
etisserant@0: multiply_operator: '*' | '/' | 'MOD'
etisserant@0: */
etisserant@0: 
etisserant@0: power_expression:
etisserant@0:   unary_expression
etisserant@0: | power_expression OPER_EXP unary_expression
etisserant@0: 	{$$ = new power_expression_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: unary_expression:
etisserant@0:   primary_expression
etisserant@0: | '-' primary_expression
etisserant@0: 	{$$ = new neg_expression_c($2);}
etisserant@0: | NOT primary_expression
etisserant@0: 	{$$ = new not_expression_c($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* Not required...
etisserant@0: unary_operator: '-' | 'NOT'
etisserant@0: */
etisserant@0: 
etisserant@0: 
etisserant@0: /* NOTE: using constant as a possible symbol for primary_expression
etisserant@0:  *       leads to a reduce/reduce conflict.
etisserant@0:  *
etisserant@0:  *       The text '-9' may be parsed as either a
etisserant@0:  *       expression<-primary_expression<-constant<-signed_integer
etisserant@0:  *       (i.e. the constant 9 negative)
etisserant@0:  *       OR
etisserant@0:  *       expression<-unary_expression<-constant<-integer
etisserant@0:  *       (i.e. the constant 9, preceded by a unary negation)
etisserant@0:  *
etisserant@0:  *       To remove the conlfict, we only allow constants without
etisserant@0:  *       a preceding '-' to be used in primary_expression
etisserant@0:  */
mario@13: /* NOTE: We use enumerated_value_without_identifier instead of enumerated_value
mario@13:  *       in order to remove a reduce/reduce conflict between reducing an
mario@13:  *       identifier to a variable or an enumerated_value.
mario@13:  */
etisserant@0: primary_expression:
etisserant@0: /* constant */
etisserant@0:   non_negative_constant
mario@13: | enumerated_value_without_identifier
etisserant@0: | variable
etisserant@0: | '(' expression ')'
etisserant@0: 	{$$ = $2;}
etisserant@0: |  function_invocation
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* intermediate helper symbol for primary_expression */
etisserant@0: /* NOTE: function_name includes the standard function name 'NOT' !
etisserant@0:  *       This introduces a reduce/reduce conflict, as NOT(var)
etisserant@0:  *       may be parsed as either a function_invocation, or a
etisserant@0:  *       unary_expression.
etisserant@0:  *
etisserant@0:  *       I (Mario) have opted to remove the possible reduction
etisserant@0:  *       to function invocation, which means replacing the rule
etisserant@0:  *           function_name '(' param_assignment_list ')'
etisserant@0:  *       with
etisserant@0:  *           function_name_no_NOT_clashes '(' param_assignment_list ')'
etisserant@0:  *
etisserant@0:  *       Notice how the new rule does not include the situation where
etisserant@0:  *       the function NOT is called with more than one parameter, which
etisserant@0:  *       the original rule does include! Callinf the NOT function with more
etisserant@0:  *       than one argument is probably a semantic error anyway, so it
etisserant@0:  *       doesn't make much sense to take it into account.
etisserant@0:  *
etisserant@0:  *       Nevertheless, if we were to to it entirely correctly,
etisserant@0:  *       leaving the semantic checks for the next compiler stage,
etisserant@0:  *       this syntax parser would need to include such a possibility.
etisserant@0:  *
etisserant@0:  *       We will leave this out for now. No need to complicate the syntax
etisserant@0:  *       more than the specification does by contradicting itself, and
etisserant@0:  *       letting names clash!
etisserant@0:  */
etisserant@0: function_invocation:
etisserant@0: /*  function_name '(' param_assignment_list ')' */
etisserant@0:   function_name_no_NOT_clashes '(' param_assignment_list ')'
etisserant@0: 	{$$ = new function_invocation_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /********************/
etisserant@0: /* B 3.2 Statements */
etisserant@0: /********************/
etisserant@0: statement_list:
mario@13:   statement ';'
mario@13: 	{$$ = new statement_list_c(); $$->add_element($1);}
mario@13: | pragma
mario@13: 	{$$ = new statement_list_c(); $$->add_element($1);}
etisserant@0: | statement_list statement ';'
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | statement_list pragma
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: | statement_list error ';'
etisserant@0: 	{$$ = $1;
etisserant@0: 	 print_err_msg(current_filename, @2.last_line, "error in statement.");
etisserant@0: 	 /* yychar */
etisserant@0: 	 yyerrok;
etisserant@0: 	}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: statement:
etisserant@0:   assignment_statement
etisserant@0: | subprogram_control_statement
etisserant@0: | selection_statement
etisserant@0: | iteration_statement
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /*********************************/
etisserant@0: /* B 3.2.1 Assignment Statements */
etisserant@0: /*********************************/
etisserant@0: assignment_statement:
etisserant@0:   variable ASSIGN expression
etisserant@0: 	{$$ = new assignment_statement_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /*****************************************/
etisserant@0: /* B 3.2.2 Subprogram Control Statements */
etisserant@0: /*****************************************/
etisserant@0: subprogram_control_statement:
etisserant@0:   fb_invocation
etisserant@0: | return_statement
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: return_statement:
etisserant@0:   RETURN	{$$ = new return_statement_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: fb_invocation:
etisserant@0:   prev_declared_fb_name '(' ')'
etisserant@0: 	{$$ = new fb_invocation_c($1, NULL);	}
etisserant@0: | prev_declared_fb_name '(' param_assignment_list ')'
etisserant@0: 	{$$ = new fb_invocation_c($1, $3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for
etisserant@0:  * - fb_invocation
etisserant@0:  * - function_invocation
etisserant@0:  */
etisserant@0: param_assignment_list:
etisserant@0:   param_assignment
etisserant@0: 	{$$ = new param_assignment_list_c(); $$->add_element($1);}
etisserant@0: | param_assignment_list ',' param_assignment
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: param_assignment:
etisserant@0: /*  variable_name ASSIGN expression */
etisserant@0:   any_identifier ASSIGN expression
etisserant@0: 	{$$ = new input_variable_param_assignment_c($1, $3);}
etisserant@0: | expression
etisserant@0: /*| variable_name SENDTO variable */
etisserant@0: /*| any_identifier SENDTO variable */
etisserant@0: | sendto_identifier SENDTO variable
etisserant@0: 	{$$ = new output_variable_param_assignment_c(NULL,$1, $3);}
etisserant@0: /*| variable_name SENDTO variable */
etisserant@0: /*| NOT any_identifier SENDTO variable*/
etisserant@0: | NOT sendto_identifier SENDTO variable
etisserant@0: 	{$$ = new output_variable_param_assignment_c(new not_paramassign_c(),$2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 3.2.3 Selection Statements */
etisserant@0: /********************************/
etisserant@0: selection_statement:
etisserant@0:   if_statement
etisserant@0: | case_statement
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: if_statement:
etisserant@0:   IF expression THEN statement_list elseif_statement_list END_IF
etisserant@0: 	{$$ = new if_statement_c($2, $4, $5, NULL);}
etisserant@0: | IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF
etisserant@0: 	{$$ = new if_statement_c($2, $4, $5, $7);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for if_statement */
etisserant@0: elseif_statement_list:
etisserant@0:   /* empty */
etisserant@0: 	{$$ = new elseif_statement_list_c();}
etisserant@0: | elseif_statement_list elseif_statement
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* helper symbol for elseif_statement_list */
etisserant@0: elseif_statement:
etisserant@0:   ELSIF expression THEN statement_list
etisserant@0: 	{$$ = new elseif_statement_c($2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: case_statement:
etisserant@0:   CASE expression OF case_element_list END_CASE
etisserant@0: 	{$$ = new case_statement_c($2, $4, NULL);}
etisserant@0: | CASE expression OF case_element_list ELSE statement_list END_CASE
etisserant@0: 	{$$ = new case_statement_c($2, $4, $6);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: /* helper symbol for case_statement */
etisserant@0: case_element_list:
etisserant@0:   case_element
etisserant@0: 	{$$ = new case_element_list_c(); $$->add_element($1);}
etisserant@0: | case_element_list case_element
etisserant@0: 	{$$ = $1; $$->add_element($2);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: case_element:
etisserant@0:   case_list ':' statement_list
etisserant@0: 	{$$ = new case_element_c($1, $3);}
mario@20: | case_list ':' statement_list identifier BOGUS_TOKEN_ID
mario@20: 	{$$ = new case_element_c($1, $3); ERROR;}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: case_list:
etisserant@0:   case_list_element
etisserant@0: 	{$$ = new case_list_c(); $$->add_element($1);}
etisserant@0: | case_list ',' case_list_element
etisserant@0: 	{$$ = $1; $$->add_element($3);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: case_list_element:
etisserant@0:   signed_integer
etisserant@0: | enumerated_value
etisserant@0: | subrange
mario@13: /*
mario@13: | identifier
mario@13: 	{$$ = $1;}
mario@13: | prev_declared_enumerated_type_name '#' any_identifier
mario@13: 	{$$ = new enumerated_value_c($1, $3);}
mario@13: */
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /********************************/
etisserant@0: /* B 3.2.4 Iteration Statements */
etisserant@0: /********************************/
etisserant@0: iteration_statement:
etisserant@0:   for_statement
etisserant@0: | while_statement
etisserant@0: | repeat_statement
etisserant@0: | exit_statement
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: for_statement:
etisserant@0:   FOR control_variable ASSIGN expression TO expression BY expression DO statement_list END_FOR
etisserant@0: 	{$$ = new for_statement_c($2, $4, $6, $8, $10);}
etisserant@0: | FOR control_variable ASSIGN expression TO expression DO statement_list END_FOR
etisserant@0: 	{$$ = new for_statement_c($2, $4, $6, NULL, $8);}
etisserant@0: ;
etisserant@0: 
etisserant@0: /* The spec has the syntax
etisserant@0:  * control_variable: identifier;
etisserant@0:  * but then defines the semantics of control_variable
etisserant@0:  * (Section 3.3.2.4) as being of an integer type
etisserant@0:  * (e.g., SINT, INT, or DINT).
etisserant@0:  *
etisserant@0:  * Obviously this presuposes that the control_variable
etisserant@0:  * must have been declared in some VAR .. END_VAR
mario@13:  * We could therefore change the syntax to read
etisserant@0:  * control_variable: prev_declared_variable_name;
mario@13:  * 
mario@13:  * However, it is probaly best if we leave the semantic checks
mario@13:  * to the semantic analyser of pass 2.
etisserant@0: */
mario@13: // control_variable: prev_declared_variable_name {$$ = $1;};
mario@13: control_variable: identifier {$$ = $1;};
etisserant@0: 
etisserant@0: /* Integrated directly into for_statement */
etisserant@0: /*
etisserant@0: for_list:
etisserant@0:   expression TO expression [BY expression]
etisserant@0: ;
etisserant@0: */
etisserant@0: 
etisserant@0: 
etisserant@0: while_statement:
etisserant@0:   WHILE expression DO statement_list END_WHILE
etisserant@0: 	{$$ = new while_statement_c($2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: repeat_statement:
etisserant@0:   REPEAT statement_list UNTIL expression END_REPEAT
etisserant@0: 	{$$ = new repeat_statement_c($2, $4);}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: exit_statement:
etisserant@0:   EXIT	{$$ = new exit_statement_c();}
etisserant@0: ;
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: %%
etisserant@0: 
etisserant@0: #include <stdio.h>	/* required for printf() */
etisserant@0: #include <errno.h>
etisserant@0: #include "../util/symtable.hh"
etisserant@0: 
etisserant@0: /* variables defined in code generated by flex... */
etisserant@0: extern FILE *yyin;
etisserant@0: extern int yylineno;
etisserant@0: 
mario@15: 
mario@15: 
mario@15: /* A global flag used to tell the parser if overloaded funtions should be allowed.
mario@15:  * The IEC 61131-3 standard allows overloaded funtions in the standard library,
mario@15:  * but disallows them in user code...
mario@15:  */
mario@15: bool allow_function_overloading = false;
mario@15: 
mario@15: /* A pointer to the root of the parsing tree that will be generated 
mario@15:  * by bison.
mario@15:  */
mario@15: symbol_c *tree_root;
mario@15: 
mario@15: 
mario@15: 
etisserant@0: /* The following function is called automatically by bison whenever it comes across
etisserant@0:  * an error. Unfortunately it calls this function before executing the code that handles
etisserant@0:  * the error itself, so we cannot print out the correct line numbers of the error location
etisserant@0:  * over here.
etisserant@0:  * Our solution is to store the current error message in a global variable, and have all
etisserant@0:  * error action handlers call the function print_err_msg() after setting the location
etisserant@0:  * (line number) variable correctly.
etisserant@0:  */
etisserant@0: const char *current_error_msg;
etisserant@0: void yyerror (const char *error_msg) {
etisserant@0:   current_error_msg = error_msg;
etisserant@0: /* fprintf(stderr, "error %d: %s\n", yynerrs // global variable //, error_msg); */
etisserant@0:   print_include_stack();
etisserant@0: }
etisserant@0: 
etisserant@0: 
etisserant@0: void print_err_msg(const char *filename, int lineno, const char *additional_error_msg) {
etisserant@0:   fprintf(stderr, "error %d: %s\n", yynerrs, additional_error_msg);
etisserant@0:   print_include_stack();
etisserant@0:   fprintf(stderr, "%s:%d: %s\n", filename, lineno, current_error_msg);
etisserant@0: }
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: /* convert between an il_operator to a function name */
etisserant@0: /* This a kludge!
etisserant@0:  * It is required because our language requires more than one
etisserant@0:  * look ahead token, and bison only works with one!
etisserant@0:  */
etisserant@0: #define op_2_str(op, str) {\
etisserant@0:   op ## _operator_c *ptr = dynamic_cast<op ## _operator_c *>(il_operator); \
etisserant@0:   if (ptr != NULL) name = str; \
etisserant@0: }
etisserant@0: 
etisserant@0: /* NOTE: this code is very ugly and un-eficient, but I (Mario) have many
etisserant@0:  *       more things to worry about right now, so just let it be...
etisserant@0:  */
etisserant@0: symbol_c *il_operator_c_2_identifier_c(symbol_c *il_operator) {
etisserant@0:   const char *name = NULL;
etisserant@0: 
etisserant@0:   op_2_str(NOT, "NOT");
etisserant@0: 
etisserant@0:   op_2_str(AND, "AND");
etisserant@0:   op_2_str(OR, "OR");
etisserant@0:   op_2_str(XOR, "XOR");
etisserant@0:   op_2_str(ADD, "ADD");
etisserant@0:   op_2_str(SUB, "SUB");
etisserant@0:   op_2_str(MUL, "MUL");
etisserant@0:   op_2_str(DIV, "DIV");
etisserant@0:   op_2_str(MOD, "MOD");
etisserant@0:   op_2_str(GT, "GT");
etisserant@0:   op_2_str(GE, "GE");
etisserant@0:   op_2_str(EQ, "EQ");
etisserant@0:   op_2_str(LT, "LT");
etisserant@0:   op_2_str(LE, "LE");
etisserant@0:   op_2_str(NE, "NE");
etisserant@0: 
etisserant@0:   op_2_str(LD, "LD");
etisserant@0:   op_2_str(LDN, "LDN");
etisserant@0:   op_2_str(ST, "ST");
etisserant@0:   op_2_str(STN, "STN");
etisserant@0: 
etisserant@0:   op_2_str(S, "S");
etisserant@0:   op_2_str(R, "R");
etisserant@0:   op_2_str(S1, "S1");
etisserant@0:   op_2_str(R1, "R1");
etisserant@0: 
etisserant@0:   op_2_str(CLK, "CLK");
etisserant@0:   op_2_str(CU, "CU");
etisserant@0:   op_2_str(CD, "CD");
etisserant@0:   op_2_str(PV, "PV");
etisserant@0:   op_2_str(IN, "IN");
etisserant@0:   op_2_str(PT, "PT");
etisserant@0: 
etisserant@0:   op_2_str(ANDN, "ANDN");
etisserant@0:   op_2_str(ORN, "ORN");
etisserant@0:   op_2_str(XORN, "XORN");
etisserant@0: 
etisserant@0:   op_2_str(ADD, "ADD");
etisserant@0:   op_2_str(SUB, "SUB");
etisserant@0:   op_2_str(MUL, "MUL");
etisserant@0:   op_2_str(DIV, "DIV");
etisserant@0: 
etisserant@0:   op_2_str(GT, "GT");
etisserant@0:   op_2_str(GE, "GE");
etisserant@0:   op_2_str(EQ, "EQ");
etisserant@0:   op_2_str(LT, "LT");
etisserant@0:   op_2_str(LE, "LE");
etisserant@0:   op_2_str(NE, "NE");
etisserant@0: 
etisserant@0:   op_2_str(CAL, "CAL");
etisserant@0:   op_2_str(CALC, "CALC");
etisserant@0:   op_2_str(CALCN, "CALCN");
etisserant@0:   op_2_str(RET, "RET");
etisserant@0:   op_2_str(RETC, "RETC");
etisserant@0:   op_2_str(RETCN, "RETCN");
etisserant@0:   op_2_str(JMP, "JMP");
etisserant@0:   op_2_str(JMPC, "JMPC");
etisserant@0:   op_2_str(JMPCN, "JMPCN");
etisserant@0: 
etisserant@0:   if (name == NULL)
etisserant@0:     ERROR;
etisserant@0: 
etisserant@0:   free(il_operator);
etisserant@0:   return new identifier_c(strdup(name));
etisserant@0: }
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: const char *standard_function_names[] = {
etisserant@0: // 2.5.1.5.1  Type conversion functions
etisserant@0: /*
etisserant@0:  *_TO_**
etisserant@0:  TRUNC
etisserant@0:  *_BCD_TO_**
etisserant@0:  **_TO_BCD_*
etisserant@0:  (REAL or LREAL to SINT, INT, DINT or LINT)
etisserant@0: */
etisserant@0: "TRUNC",
etisserant@0: "TIME_TO_REAL",
etisserant@0: // 2.5.1.5.2  Numerical functions
etisserant@0: //   Table 23 - Standard functions of one numeric variable
etisserant@0: "ABS","SQRT","LN","LOG","EXP","SIN","COS","TAN","ASIN","ACOS","ATAN",
etisserant@0: //   Table 24 - Standard arithmetic functions
etisserant@0: "ADD","MUL","SUB","DIV","MOD"/* See note (a) */,"EXPT","MOVE",
etisserant@0: // 2.5.1.5.3  Bit string functions
etisserant@0: //   Table 25 - Standard bit shift functions
etisserant@0: "SHL","SHR","ROR","ROL",
etisserant@0: // 2.5.1.5.4  Selection and comparison functions
etisserant@0: //   Table 26 - Standard bitwise Boolean functions
etisserant@0: "AND","OR","XOR","NOT",
etisserant@0: //   Table 27 - Standard selection functions
etisserant@0: "SEL","MAX","MIN","LIMIT","MUX",
etisserant@0: //   Table 28 - Standard comparison functions
etisserant@0: "GT","GE","EQ","LE","LT","NE",
etisserant@0: // 2.5.1.5.5  Character string functions
etisserant@0: //   Table 29 - Standard character string functions
etisserant@0: "LEN","LEFT","RIGHT","MID","CONCAT","INSERT","DELETE","REPLACE","FIND",
etisserant@0: // 2.5.1.5.6  Functions of time data types
etisserant@0: //   Table 30 - Functions of time data types
etisserant@0: "ADD_TIME","ADD_TOD_TIME","ADD_DT_TIME","SUB_TIME","SUB_DATE_DATE",
etisserant@0: "SUB_TOD_TIME","SUB_TOD_TOD","SUB_DT_TIME","SUB_DT_DT","MULTIME",
etisserant@0: "DIVTIME","CONCAT_DATE_TOD",
etisserant@0: // 2.5.1.5.7  Functions of enumerated data types
etisserant@0: //   Table 31 - Functions of enumerated data types
etisserant@0: // "SEL", /* already above! We cannot have duplicates! */
etisserant@0: // "MUX", /* already above! We cannot have duplicates! */
etisserant@0: // "EQ",  /* already above! We cannot have duplicates! */
etisserant@0: // "NE",  /* already above! We cannot have duplicates! */
etisserant@0: 
etisserant@0: /* end of array marker! Do not remove! */
etisserant@0: NULL
etisserant@0: 
etisserant@0: /* Note (a):
etisserant@0:  *  This function has a name equal to a reserved keyword.
etisserant@0:  *  This means that adding it here is irrelevant because the
etisserant@0:  *  lexical parser will consider it the XXX token before
etisserant@0:  *  it interprets it as an identifier and looks it up
etisserant@0:  *  in the library elements symbol table.
etisserant@0:  */
etisserant@0: };
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: 
etisserant@0: const char *standard_function_block_names[] = {
etisserant@0: // 2.5.2.3.1  Bistable elements
etisserant@0: //   Table 34 - Standard bistable function blocks
etisserant@0: //"SR","RS",
etisserant@0: // 2.5.2.3.2  Edge detection
etisserant@0: //   Table 35 - Standard edge detection function blocks
etisserant@0: "R_TRIG","F_TRIG",
etisserant@0: // 2.5.2.3.3  Counters
etisserant@0: //   Table 36 - Standard counter function blocks
etisserant@0: "CTU","CTU_LINT","CTU_UDINT","CTU_ULINT",
etisserant@0: "CTD","CTD_DINT","CTD_LINT","CTD_UDINT",
etisserant@0: "CTUD","CTUD_DINT","CTUD_LINT","CTUD_ULINT",
etisserant@0: // 2.5.2.3.4  Timers
etisserant@0: //   Table 37 - Standard timer function blocks
etisserant@0: "TP","TON","TOF",
etisserant@0: /* end of array marker! Do not remove! */
etisserant@0: NULL
etisserant@0: };
etisserant@0: 
etisserant@0: 
etisserant@0: #define LIBFILE "ieclib.txt"
etisserant@0: #define DEF_LIBFILENAME LIBDIRECTORY "/" LIBFILE
etisserant@0: 
mario@15: int stage1_2__(const char *filename, const char *includedir, symbol_c **tree_root_ref) {
etisserant@0:   FILE *in_file = NULL, *lib_file = NULL;
etisserant@0:   char *libfilename = NULL;
etisserant@0: 
etisserant@0:   if((in_file = fopen(filename, "r")) == NULL) {
etisserant@0:     char *errmsg = strdup2("Error opening main file ", filename);
etisserant@0:     perror(errmsg);
etisserant@0:     free(errmsg);
etisserant@0:     return -1;
etisserant@0:   }
etisserant@0: 
etisserant@0:   if (includedir != NULL) {
etisserant@0:     if ((libfilename = strdup3(includedir, "/", LIBFILE)) == NULL) {
etisserant@0:       fprintf (stderr, "Out of memory. Bailing out!\n");
etisserant@0:       return -1;
etisserant@0:     }
etisserant@0: 
etisserant@0:     if((lib_file = fopen(libfilename, "r")) == NULL) {
etisserant@0:       char *errmsg = strdup2("Error opening library file ", libfilename);
etisserant@0:       perror(errmsg);
etisserant@0:       free(errmsg);
etisserant@0:     }
etisserant@0:   }
etisserant@0: 
etisserant@0:   if (lib_file == NULL) {
etisserant@0:     /* we try again... */
etisserant@0:     if ((libfilename = strdup(DEF_LIBFILENAME)) == NULL) {
etisserant@0:       fprintf (stderr, "Out of memory. Bailing out!\n");
etisserant@0:       return -1;
etisserant@0:     }
etisserant@0: 
etisserant@0:     if((lib_file = fopen(libfilename, "r")) == NULL) {
etisserant@0:       char *errmsg = strdup2("Error opening library file ", libfilename);
etisserant@0:       perror(errmsg);
etisserant@0:       free(errmsg);
etisserant@0:     }
etisserant@0:   }
etisserant@0: 
etisserant@0:   if (lib_file == NULL) {
etisserant@0:     /* we give up... */
etisserant@0:     free(libfilename);
etisserant@0:     fclose(in_file);
etisserant@0:     return -1;
etisserant@0:   }
etisserant@0: 
etisserant@0:   /* first parse the standard library file... */
etisserant@0:   yyin = lib_file;
etisserant@0:   yylineno = 1;
etisserant@0:   allow_function_overloading = true;
etisserant@0:   current_filename = libfilename;
etisserant@0:   if (yyparse() != 0)
etisserant@0:       ERROR;
etisserant@0: 
etisserant@0:   if (yynerrs > 0) {
etisserant@0:     fprintf (stderr, "\nFound %d error(s) in %s. Bailing out!\n", yynerrs /* global variable */, libfilename);
etisserant@0:     ERROR;
etisserant@0:   }
etisserant@0:   free(libfilename);
etisserant@0:   fclose(lib_file);
etisserant@0: 
etisserant@0:   /* if by any chance the library is not complete, we
etisserant@0:    * now add the missing reserved keywords to the list!!!
etisserant@0:    */
etisserant@0:   for(int i = 0; standard_function_names[i] != NULL; i++)
etisserant@0:     if (library_element_symtable.find_value(standard_function_names[i]) ==
etisserant@0:         library_element_symtable.end_value())
etisserant@0:       library_element_symtable.insert(standard_function_names[i], standard_function_name_token);
etisserant@0: 
etisserant@0:   for(int i = 0; standard_function_block_names[i] != NULL; i++)
etisserant@0:     if (library_element_symtable.find_value(standard_function_block_names[i]) ==
etisserant@0:         library_element_symtable.end_value())
etisserant@0:       library_element_symtable.insert(standard_function_block_names[i], standard_function_block_name_token);
etisserant@0: 
etisserant@0: #if YYDEBUG
etisserant@0:   yydebug = 1;
etisserant@0: #endif
etisserant@0: 
etisserant@0:   /* now parse the input file... */
etisserant@0:   yyin = in_file;
etisserant@0:   yylineno = 1;
etisserant@0:   allow_function_overloading = false;
etisserant@0:   current_filename = filename;
etisserant@0:   if (yyparse() != 0)
etisserant@0:     exit(EXIT_FAILURE);
etisserant@0: 
etisserant@0:   if (yynerrs > 0) {
etisserant@0:     fprintf (stderr, "\nFound %d error(s). Bailing out!\n", yynerrs /* global variable */);
etisserant@0:     exit(EXIT_FAILURE);
etisserant@0:   }
etisserant@0: 
etisserant@0:   if (tree_root_ref != NULL)
etisserant@0:     *tree_root_ref = tree_root;
etisserant@0: 
etisserant@0:   fclose(in_file);
etisserant@0:   return 0;
etisserant@0: }
etisserant@0: 
etisserant@0: 
etisserant@0: