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