Initial commit. Last MatPLC CVS with some makefile inclusion removed in order to compile fine out of MatPLC.
authoretisserant
Wed, 31 Jan 2007 15:32:38 +0100
changeset 0 fb772792efd1
child 1 5d893a68be6e
Initial commit. Last MatPLC CVS with some makefile inclusion removed in order to compile fine out of MatPLC.
.cdtproject
.project
.settings/org.eclipse.cdt.core.prefs
AnnexF/average_st.txt
AnnexF/cmd_monitor_il.txt
AnnexF/cmd_monitor_st.txt
AnnexF/delay_st.txt
AnnexF/derivative_st.txt
AnnexF/diffeq_st.txt
AnnexF/fwd_rev_mon_il.txt
AnnexF/fwd_rev_mon_st.txt
AnnexF/gravel_st.txt
AnnexF/hysteresis_st.txt
AnnexF/integral_st.txt
AnnexF/lag1_st.txt
AnnexF/pid_st.txt
AnnexF/ramp_st.txt
AnnexF/readme
AnnexF/stack_int_il.txt
AnnexF/stack_int_st.txt
AnnexF/transfer_st.txt
AnnexF/weigh_il.txt
AnnexF/weigh_st.txt
Makefile
absyntax/Makefile
absyntax/absyntax.cc
absyntax/absyntax.def
absyntax/absyntax.hh
absyntax/visitor.cc
absyntax/visitor.hh
lib/bcd_to_int.txt
lib/bistable.txt
lib/counter.txt
lib/edge_detection.txt
lib/ieclib.txt
lib/int_to_bcd.txt
lib/ramp_st.txt
lib/time_math.txt
lib/timer.txt
main.cc
ramp.cc
readme
stage1_2/Makefile
stage1_2/iec.flex
stage1_2/iec.y
stage4/Makefile
stage4/generate_cc/Makefile
stage4/generate_cc/decompose_var_instance_name.cc
stage4/generate_cc/function_call_iterator.cc
stage4/generate_cc/function_call_param_iterator.cc
stage4/generate_cc/function_param_iterator.cc
stage4/generate_cc/generate_cc.cc
stage4/generate_cc/generate_cc.hh
stage4/generate_cc/generate_cc_base.cc
stage4/generate_cc/generate_cc_configbody.cc
stage4/generate_cc/generate_cc_il.cc
stage4/generate_cc/generate_cc_st.cc
stage4/generate_cc/generate_cc_tempvardecl.cc
stage4/generate_cc/generate_cc_typedecl.cc
stage4/generate_cc/generate_cc_vardecl.cc
stage4/generate_cc/plciec.cc
stage4/generate_cc/plciec.h
stage4/generate_cc/search_base_type.cc
stage4/generate_cc/search_constant_type.cc
stage4/generate_cc/search_fb_instance_decl.cc
stage4/generate_cc/search_var_instance_decl.cc
stage4/generate_cc/search_varfb_instance_type.cc
stage4/generate_cc/spec_init_separator.cc
stage4/generate_cc/type_initial_value.cc
stage4/generate_iec/Makefile
stage4/generate_iec/generate_iec.cc
stage4/generate_iec/generate_iec.hh
stage4/stage4.cc
stage4/stage4.hh
util/dsymtable.cc
util/dsymtable.hh
util/symtable.cc
util/symtable.hh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.cdtproject	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse-cdt version="2.0"?>
+
+<cdtproject id="org.eclipse.cdt.make.core.make">
+<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+<extension id="org.eclipse.cdt.core.domsourceindexer" point="org.eclipse.cdt.core.CIndexer"/>
+<data>
+<item id="scannerConfiguration">
+<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="true" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="true"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+<buildOutputProvider>
+<openAction enabled="false" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="makefileGenerator">
+<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
+<parser enabled="false"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="false" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="false"/>
+</scannerInfoProvider>
+</profile>
+<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+<buildOutputProvider>
+<openAction enabled="false" filePath=""/>
+<parser enabled="true"/>
+</buildOutputProvider>
+<scannerInfoProvider id="specsFile">
+<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
+<parser enabled="false"/>
+</scannerInfoProvider>
+</profile>
+</item>
+<item id="org.eclipse.cdt.core.pathentry">
+<pathentry kind="src" path=""/>
+<pathentry kind="out" path=""/>
+<pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>
+</item>
+</data>
+</cdtproject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.project	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>matiec</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.make.core.makeBuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.arguments</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.core.errorOutputParser</key>
+					<value>org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser;</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.environment</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.target.inc</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.target.clean</key>
+					<value>clean</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.command</key>
+					<value>make</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.target.auto</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>false</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.make.core.makeNature</nature>
+		<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.settings/org.eclipse.cdt.core.prefs	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,3 @@
+#Wed Jan 31 15:26:34 CET 2007
+eclipse.preferences.version=1
+indexerId=org.eclipse.cdt.core.fastIndexer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/average_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,18 @@
+ FUNCTION_BLOCK AVERAGE
+   VAR_INPUT
+     RUN : BOOL ;      (* 1 = run, 0 = reset *)
+     XIN : REAL ;     (* Input variable *)
+     N   : INT ;      (* 0 <= N < 128 or manufacturer- *)
+   END_VAR            (*      specified maximum value  *)
+   VAR_OUTPUT XOUT : REAL ; END_VAR (* Averaged output *)
+   VAR SUM  : REAL := 0.0; (* Running sum *)
+       FIFO : DELAY ;      (* N-Element FIFO *)
+   END_VAR
+   SUM := SUM - FIFO.XOUT ;
+   FIFO (RUN := RUN , XIN := XIN, N := N) ;
+   SUM := SUM + FIFO.XOUT ;
+   IF RUN THEN XOUT := SUM/N ;
+   ELSE SUM := N*XIN ; XOUT := XIN ;
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/cmd_monitor_il.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,37 @@
+FUNCTION_BLOCK CMD_MONITOR
+ VAR_INPUT AUTO_CMD : BOOL ; (* Automated command *)
+          AUTO_MODE : BOOL ; (* AUTO_CMD enable *)
+            MAN_CMD : BOOL ; (* Manual Command *)
+        MAN_CMD_CHK : BOOL ; (* Negated MAN_CMD to debounce *)  
+          T_CMD_MAX : TIME ; (* Max time from CMD to FDBK *)
+               FDBK : BOOL ; (* Confirmation of CMD completion     
+                                by operative unit *)               
+                ACK : BOOL ; (* Acknowledge/cancel ALRM *)         
+ END_VAR
+ VAR_OUTPUT CMD : BOOL ;   (* Command to operative unit *)
+           ALRM : BOOL ;   (* T_CMD_MAX expired without FDBK *)
+ END_VAR
+ VAR CMD_TMR : TON ;    (* CMD-to-FDBK timer *)
+     ALRM_FF : SR ;     (* Note over-riding S input: *)
+ END_VAR                (* Command must be cancelled before
+                              "ACK" can cancel alarm *)
+ (* Function Block Body *)
+LD	T_CMD_MAX	
+ST	CMD_TMR.PT	(* Store an input to the TON FB *)
+LD	AUTO_CMD	
+AND	AUTO_MODE	
+OR(	MAN_CMD	
+ANDN	AUTO_MODE	
+ANDN	MAN_CMD_CHK	
+)		
+ST	CMD	
+IN	CMD_TMR	(* Invoke the TON FB *)
+LD	CMD_TMR.Q	
+ANDN	FDBK	
+ST	ALRM_FF.S1	(* Store an input to the SR FB *)
+LD	ACK	
+R	ALRM_FF	(* Invoke the SR FB *)
+LD	ALRM_FF.Q1	
+ST    	ALRM	
+
+END_FUNCTION_BLOCK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/cmd_monitor_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,25 @@
+FUNCTION_BLOCK CMD_MONITOR
+ VAR_INPUT AUTO_CMD : BOOL ; (* Automated command *)
+          AUTO_MODE : BOOL ; (* AUTO_CMD enable *)
+            MAN_CMD : BOOL ; (* Manual Command *)
+        MAN_CMD_CHK : BOOL ; (* Negated MAN_CMD to debounce *)  
+          T_CMD_MAX : TIME ; (* Max time from CMD to FDBK *)
+               FDBK : BOOL ; (* Confirmation of CMD completion     
+                                by operative unit *)               
+                ACK : BOOL ; (* Acknowledge/cancel ALRM *)         
+ END_VAR
+ VAR_OUTPUT CMD : BOOL ;   (* Command to operative unit *)
+           ALRM : BOOL ;   (* T_CMD_MAX expired without FDBK *)
+ END_VAR
+ VAR CMD_TMR : TON ;    (* CMD-to-FDBK timer *)
+     ALRM_FF : SR ;     (* Note over-riding S input: *)
+ END_VAR                (* Command must be cancelled before
+                              "ACK" can cancel alarm *)
+ (* Function Block Body *)
+    CMD := AUTO_CMD & AUTO_MODE
+          OR MAN_CMD & NOT MAN_CMD_CHK & NOT AUTO_MODE ;
+    CMD_TMR (IN := CMD, PT := T_CMD_MAX);
+    ALRM_FF (S1 := CMD_TMR.Q & NOT FDBK, R := ACK);
+    ALRM := ALRM_FF.Q1;
+
+END_FUNCTION_BLOCK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/delay_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,18 @@
+FUNCTION_BLOCK DELAY    (* N-sample delay *)
+  VAR_INPUT
+    RUN : BOOL ;     (* 1 = run, 0 = reset *)
+    XIN : REAL ;
+    N   : INT        (* 0 <= N < 128 or manufacturer- *)
+  END_VAR            (*      specified maximum value  *)
+  VAR_OUTPUT XOUT : REAL; END_VAR   (* Delayed output *)
+  VAR X : ARRAY [0..127]     (* N-Element queue *)
+               OF REAL;      (* with FIFO discipline *)
+      I, IXIN, IXOUT : INT := 0;
+  END_VAR
+  IF RUN THEN IXIN := MOD(IXIN + 1, 128) ; X[IXIN] := XIN ;
+              IXOUT := MOD(IXOUT + 1, 128) ; XOUT := X[IXOUT];
+  ELSE XOUT := XIN ; IXIN := N ; IXOUT := 0;
+       FOR I := 0 TO N DO X[I] := XIN; END_FOR;
+  END_IF ;
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/derivative_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,18 @@
+ FUNCTION_BLOCK DERIVATIVE
+   VAR_INPUT
+     RUN : BOOL ;          (* 0 = reset                  *)
+     XIN : REAL ;          (* Input to be differentiated *)
+     CYCLE : TIME ;        (* Sampling period            *)
+   END_VAR
+   VAR_OUTPUT
+     XOUT : REAL ;         (* Differentiated output      *)
+   END_VAR
+   VAR X1, X2, X3 : REAL ; END_VAR
+   IF RUN THEN
+      XOUT := (3.0 * (XIN - X3) + X1 - X2)
+              / (10.0 * TIME_TO_REAL(CYCLE)) ;
+      X3 := X2 ; X2 := X1 ; X1 := XIN ;
+   ELSE XOUT := 0.0; X1 := XIN ; X2 := XIN ; X3 := XIN ;
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/diffeq_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,30 @@
+ FUNCTION_BLOCK DIFFEQ
+   VAR_INPUT
+     RUN : BOOL ;             (* 1 = run, 0 = reset *)
+     XIN : REAL ;
+     A : ARRAY[1..] OF REAL ; (* Input coefficients *)
+     M : INT ;                (* Length of input history  *)
+     B : ARRAY[0..] OF REAL ; (* Output coefficients *)
+     N : INT ;                (* Length of output history *)        
+   END_VAR
+   VAR_OUTPUT XOUT : REAL := 0.0 ; END_VAR
+   VAR  (* NOTE : Manufacturer may specify other array sizes *)   
+     XI : ARRAY [0..128] OF REAL ; (* Input history  *)
+     XO : ARRAY [0..128] OF REAL ; (* Output history *)
+     I : INT ;
+   END_VAR
+   XO[0] := XOUT ; XI[0] := XIN ;
+   XOUT := B[0] * XIN ;
+   IF RUN THEN
+      FOR I := M TO 1 BY -1 DO
+          XOUT := XOUT + A[I] * XO[I] ; XO[I] := XO[I-1];
+      END_FOR;
+      FOR I := N TO 1 BY -1 DO
+          XOUT := XOUT + B[I] * XI[I] ; XI[I] := XI[I-1];
+      END_FOR;
+   ELSE
+      FOR I := 1 TO M DO XO[I] := 0.0; END_FOR;
+      FOR I := 1 TO N DO XI[I] := 0.0; END_FOR;
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/fwd_rev_mon_il.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,77 @@
+FUNCTION_BLOCK FWD_REV_MON
+VAR_INPUT AUTO : BOOL ;(* Enable automated commands *)
+  ACK : BOOL ;         (* Acknowledge/cancel all alarms *)
+  AUTO_FWD : BOOL ;    (* Automated forward command *)
+  MAN_FWD : BOOL ;     (* Manual forward command *)
+  MAN_FWD_CHK : BOOL ; (* Negated MAN_FWD for debouncing *)
+  T_FWD_MAX : TIME ;  (* Maximum time from FWD_CMD to FWD_FDBK *)
+  FWD_FDBK : BOOL ;    (* Confirmation of FWD_CMD completion *)
+                       (*   by operative unit *)
+  AUTO_REV : BOOL ;    (* Automated reverse command *)
+  MAN_REV : BOOL ;     (* Manual reverse command *)
+  MAN_REV_CHK : BOOL ; (* Negated MAN_REV for debouncing *)
+  T_REV_MAX : TIME ;  (* Maximum time from REV_CMD to REV_FDBK *)  
+  REV_FDBK : BOOL ;    (* Confirmation of REV_CMD completion *)
+END_VAR                (*    by operative unit *)
+VAR_OUTPUT KLAXON : BOOL ;      (* Any alarm active *)
+  FWD_REV_ALRM : BOOL; (* Forward/reverse command conflict *)
+  FWD_CMD : BOOL ;     (* "Forward" command to operative unit *)
+  FWD_ALRM : BOOL ;    (* T_FWD_MAX expired without FWD_FDBK *)
+  REV_CMD : BOOL ;     (* "Reverse" command to operative unit *)
+  REV_ALRM : BOOL ;    (* T_REV_MAX expired without REV_FDBK *)
+END_VAR
+VAR FWD_MON : CMD_MONITOR; (* "Forward" command monitor *)
+  REV_MON : CMD_MONITOR;   (* "Reverse" command monitor *)
+  FWD_REV_FF : SR ;      (* Forward/Reverse contention latch *)
+END_VAR
+(* Function Block body *)
+LD	AUTO	(* Load common inputs *)
+ST	FWD_MON.AUTO_MODE	
+ST	REV_MON.AUTO_MODE	
+LD	ACK	
+ST	FWD_MON.ACK	
+ST	REV_MON.ACK	
+ST	FWD_REV_FF.R	
+LD	AUTO_FWD	(* Load inputs to FWD_MON *)
+ST	FWD_MON.AUTO_CMD	
+LD	MAN_FWD	
+ST	FWD_MON.MAN_CMD	
+LD	MAN_FWD_CHK	
+ST	FWD_MON.MAN_CMD_CHK	
+LD	T_FWD_MAX	
+ST	FWD_MON.T_CMD_MAX	
+LD	FWD_FDBK	
+ST	FWD_MON.FDBK	
+CAL	FWD_MON	(* Activate FWD_MON *)
+LD	AUTO_REV	(* Load inputs to REV_MON *)
+ST	REV_MON.AUTO_CMD	
+LD	MAN_REV	
+ST	REV_MON.MAN_CMD	
+LD	MAN_REV_CHK	
+ST	REV_MON.MAN_CMD_CHK	
+LD	T_REV_MAX	
+ST	REV_MON.T_CMD_MAX	
+LD	REV_FDBK	
+ST	REV_MON.FDBK	
+CAL	REV_MON	(* Activate REV_MON *)
+LD	FWD_MON.CMD	(* Check for contention *)
+AND	REV_MON.CMD	
+S1	FWD_REV_FF	(* Latch contention condition *)
+LD	FWD_REV_FF.Q	
+ST	FWD_REV_ALRM	(* Contention alarm *)
+LD	FWD_MON.CMD	(* "Forward" command and alarm *)
+ANDN	FWD_REV_ALRM	
+ST	FWD_CMD	
+LD	FWD_MON.ALRM	
+ST	FWD_ALRM	
+LD	REV_MON.CMD	(* "Reverse" command and alarm *)
+ANDN	FWD_REV_ALRM	
+ST	REV_CMD	
+LD	REV_MON.ALRM	
+ST	REV_ALRM	
+OR	FWD_ALRM	(* OR all alarms *)
+OR	FWD_REV_ALRM	
+ST	KLAXON	
+
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/fwd_rev_mon_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,53 @@
+FUNCTION_BLOCK FWD_REV_MON
+VAR_INPUT AUTO : BOOL ;(* Enable automated commands *)
+  ACK : BOOL ;         (* Acknowledge/cancel all alarms *)
+  AUTO_FWD : BOOL ;    (* Automated forward command *)
+  MAN_FWD : BOOL ;     (* Manual forward command *)
+  MAN_FWD_CHK : BOOL ; (* Negated MAN_FWD for debouncing *)
+  T_FWD_MAX : TIME ;  (* Maximum time from FWD_CMD to FWD_FDBK *)
+  FWD_FDBK : BOOL ;    (* Confirmation of FWD_CMD completion *)
+                       (*   by operative unit *)
+  AUTO_REV : BOOL ;    (* Automated reverse command *)
+  MAN_REV : BOOL ;     (* Manual reverse command *)
+  MAN_REV_CHK : BOOL ; (* Negated MAN_REV for debouncing *)
+  T_REV_MAX : TIME ;  (* Maximum time from REV_CMD to REV_FDBK *)  
+  REV_FDBK : BOOL ;    (* Confirmation of REV_CMD completion *)
+END_VAR                (*    by operative unit *)
+VAR_OUTPUT KLAXON : BOOL ;      (* Any alarm active *)
+  FWD_REV_ALRM : BOOL; (* Forward/reverse command conflict *)
+  FWD_CMD : BOOL ;     (* "Forward" command to operative unit *)
+  FWD_ALRM : BOOL ;    (* T_FWD_MAX expired without FWD_FDBK *)
+  REV_CMD : BOOL ;     (* "Reverse" command to operative unit *)
+  REV_ALRM : BOOL ;    (* T_REV_MAX expired without REV_FDBK *)
+END_VAR
+VAR FWD_MON : CMD_MONITOR; (* "Forward" command monitor *)
+  REV_MON : CMD_MONITOR;   (* "Reverse" command monitor *)
+  FWD_REV_FF : SR ;      (* Forward/Reverse contention latch *)
+END_VAR
+(* Function Block body *)
+(* Evaluate internal function blocks *)
+  FWD_MON    (AUTO_MODE   := AUTO,
+              ACK         := ACK,
+              AUTO_CMD    := AUTO_FWD,
+              MAN_CMD     := MAN_FWD,
+              MAN_CMD_CHK := MAN_FWD_CHK,
+              T_CMD_MAX   := T_FWD_MAX,
+              FDBK        := FWD_FDBK);
+  REV_MON    (AUTO_MODE   := AUTO,
+              ACK         := ACK,
+              AUTO_CMD    := AUTO_REV,
+              MAN_CMD     := MAN_REV,
+              MAN_CMD_CHK := MAN_REV_CHK,
+              T_CMD_MAX   := T_REV_MAX,
+              FDBK        := REV_FDBK);
+  FWD_REV_FF (S1 := FWD_MON.CMD & REV_MON.CMD, R := ACK); 
+(* Transfer data to outputs *)
+  FWD_REV_ALRM := FWD_REV_FF.Q1;
+  FWD_CMD := FWD_MON.CMD & NOT FWD_REV_ALRM;
+  FWD_ALRM := FWD_MON.ALRM;
+  REV_CMD := REV_MON.CMD & NOT FWD_REV_ALRM;
+  REV_ALRM := REV_MON.ALRM;
+  KLAXON := FWD_ALRM OR REV_ALRM OR FWD_REV_ALRM;
+
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/gravel_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,129 @@
+PROGRAM GRAVEL  (* Gravel measurement and loading system *)
+ VAR_INPUT
+    OFF_PB         : BOOL ;
+    ON_PB          : BOOL ;
+    FILL_PB        : BOOL ;
+    SIREN_ACK      : BOOL ;
+    LOAD_PB        : BOOL ; (* Load truck from bin *)
+    JOG_PB         : BOOL ;
+    LAMP_TEST      : BOOL ;
+    TRUCK_ON_RAMP  : BOOL ; (* Optical sensor *)
+    SILO_EMPTY_LS  : BOOL ;
+    BIN_EMPTY_LS   : BOOL ;
+    SETPOINT       : BYTE ; (* 2-digit BCD *)
+ END_VAR
+ VAR_OUTPUT
+    CONTROL_LAMP    : BOOL ;
+    TRUCK_LAMP      : BOOL ;
+    SILO_EMPTY_LAMP : BOOL ;
+    CONVEYOR_LAMP   : BOOL ;
+    CONVEYOR_MOTOR  : BOOL ;
+    SILO_VALVE      : BOOL ;
+    BIN_VALVE       : BOOL ;
+    SIREN           : BOOL ;
+    BIN_LEVEL       : BYTE ;
+ END_VAR
+ VAR
+  BLINK_TIME : TIME; (* BLINK ON/OFF time *)
+  PULSE_TIME : TIME; (* LEVEL_CTR increment interval *)
+  RUNOUT_TIME: TIME; (* Conveyor running time after loading *)
+  RUN_IN_TIME: TIME; (* Conveyor running time before loading *)
+  SILENT_TIME: TIME; (* Siren silent time after SIREN_ACK *)
+  OK_TO_RUN  : BOOL; (* 1 = Conveyor is allowed to run *)
+  (* Function Blocks *)
+  BLINK: TON; (* Blinker OFF period timer / ON output *)
+  BLANK: TON; (* Blinker ON period timer / blanking pulse *)
+  PULSE: TON; (* LEVEL_CTR pulse interval timer *)
+  SIREN_FF: RS;
+  SILENCE_TMR: TP; (* Siren silent period timer *)
+ END_VAR
+ VAR RETAIN LEVEL_CTR : CTU ; END_VAR
+   (* Program body *)
+   (* Major operating states *)
+   INITIAL_STEP START : END_STEP
+   TRANSITION FROM START TO FILL_BIN
+      := FILL_PB & CONTROL.X ; END_TRANSITION
+   STEP FILL_BIN: SILO_VALVE(N); END_STEP
+   TRANSITION FROM FILL_BIN TO START
+      := NOT FILL_PB OR NOT CONTROL.X ; END_TRANSITION
+   TRANSITION FROM FILL_BIN TO LOAD_WAIT := LEVEL_CTR.Q ;
+   END_TRANSITION
+   STEP LOAD_WAIT : END_STEP
+   TRANSITION FROM LOAD_WAIT TO RUN_IN
+      := LOAD_PB & OK_TO_RUN ; END_TRANSITION
+   STEP RUN_IN : END_STEP
+   TRANSITION FROM RUN_IN TO LOAD_WAIT := NOT OK_TO_RUN ;
+   END_TRANSITION
+   TRANSITION FROM RUN_IN TO DUMP_BIN
+      := RUN_IN.T > RUN_IN_TIME;
+   END_TRANSITION
+   STEP DUMP_BIN: BIN_VALVE(N); END_STEP
+   TRANSITION FROM DUMP_BIN TO LOAD_WAIT := NOT OK_TO_RUN ;
+   END_TRANSITION
+   TRANSITION FROM DUMP_BIN TO RUNOUT := BIN_EMPTY_LS ;
+   END_TRANSITION
+   STEP RUNOUT : END_STEP
+   TRANSITION FROM RUNOUT TO LOAD_WAIT := NOT OK_TO_RUN ;
+   END_TRANSITION
+   TRANSITION FROM RUNOUT TO START
+      := RUNOUT.T >= RUNOUT_TIME ; END_TRANSITION
+(* Control state sequencing *)
+INITIAL_STEP CONTROL_OFF: END_STEP
+TRANSITION FROM CONTROL_OFF TO CONTROL
+     := ON_PB & NOT OFF_PB ; END_TRANSITION
+STEP CONTROL: CONTROL_ACTION(N); END_STEP
+ACTION CONTROL_ACTION:
+   BLINK(EN:=CONTROL.X & NOT BLANK.Q, PT := BLINK_TIME) ;
+   BLANK(EN:=BLINK.Q, PT := BLINK_TIME) ;
+   OK_TO_RUN := CONTROL.X & TRUCK_ON_RAMP ;
+   CONVEYOR_MOTOR :=
+     OK_TO_RUN & OR(JOG_PB, RUN_IN.X, DUMP_BIN.X, RUNOUT.X);   
+END_ACTION
+TRANSITION FROM CONTROL TO CONTROL_OFF := OFF_PB ;
+END_TRANSITION
+(* Monitor Logic *)
+INITIAL_STEP MONITOR: MONITOR_ACTION(N); END_STEP
+ACTION MONITOR_ACTION:
+  CONVEYOR_LAMP := CONVEYOR_MOTOR & BLINK.Q ;
+  CONTROL_LAMP := CONTROL.X OR LAMP_TEST ;
+  TRUCK_LAMP := TRUCK_ON_RAMP OR LAMP_TEST ;
+  SILO_EMPTY_LAMP := BLINK.Q & SILO_EMPTY_LS OR LAMP_TEST ;
+  SILENCE_TMR(IN:=SIREN_ACK, PT:=SILENT_TIME) ;
+  SIREN_FF(S:=SILO_EMPTY_LS, R1:=SILENCE_TMR.Q) ;
+  SIREN := SIREN_FF.Q1 ;
+  PULSE(IN:=FILL_BIN.X & NOT PULSE.Q, PT:=PULSE_TIME) ;
+  LEVEL_CTR(R := BIN_EMPTY_LS, CU := PULSE.Q,
+            PV := BCD_TO_INT(SETPOINT)) ;
+  BIN_LEVEL := INT_TO_BCD(LEVEL_CTR.CV) ;
+END_ACTION
+
+END_PROGRAM
+
+ CONFIGURATION GRAVEL_CONTROL
+   RESOURCE PROC1 ON PROC_TYPE_Y
+     PROGRAM G : GRAVEL
+      (* Inputs *)
+       (OFF_PB        := %I0.0 ,
+        ON_PB         := %I0.1 ,
+        FILL_PB       := %I0.2 ,
+        SIREN_ACK     := %I0.3 ,
+        LOAD_PB       := %I0.4 ,
+        JOG_PB        := %I0.5 ,
+        LAMP_TEST     := %I0.7 ,
+        TRUCK_ON_RAMP := %I1.4 ,
+        SILO_EMPTY_LS := %I1.5 ,
+        BIN_EMPTY_LS  := %I1.6 ,
+        SETPOINT      := %IB2  ,
+       (* Outputs *)
+        CONTROL_LAMP    => %Q4.0,
+        TRUCK_LAMP      => %Q4.2,
+        SILO_EMPTY_LAMP => %Q4.3,
+        CONVEYOR_LAMP   => %Q5.3,
+        CONVEYOR_MOTOR  => %Q5.4,
+        SILO_VALVE      => %Q5.5,
+        BIN_VALVE       => %Q5.6,
+        SIREN           => %Q5.7,
+        BIN_LEVEL       => %B6) ;
+   END_RESOURCE
+ END_CONFIGURATION
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/hysteresis_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,10 @@
+FUNCTION_BLOCK HYSTERESIS
+    (* Boolean hysteresis on difference *)
+    (* of REAL inputs, XIN1 - XIN2      *)
+  VAR_INPUT XIN1, XIN2, EPS : REAL; END_VAR
+  VAR_OUTPUT Q : BOOL := 0; END_VAR
+  IF Q THEN IF XIN1 < (XIN2 - EPS) THEN Q := 0; END_IF ;
+  ELSIF XIN1 > (XIN2 + EPS) THEN Q := 1 ;
+  END_IF ;
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/integral_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,18 @@
+ FUNCTION_BLOCK INTEGRAL
+   VAR_INPUT
+     RUN : BOOL ;       (* 1 = integrate, 0 = hold *)
+     R1 : BOOL ;        (* Overriding reset        *)
+     XIN : REAL ;       (* Input variable          *)
+     X0  : REAL ;       (* Initial value           *)
+     CYCLE : TIME ;     (* Sampling period         *)
+   END_VAR
+   VAR_OUTPUT
+     Q : BOOL ;         (* NOT R1                  *)
+     XOUT : REAL ;      (* Integrated output       *)
+   END_VAR
+   Q := NOT R1 ;
+   IF R1 THEN XOUT := X0 ;
+   ELSIF RUN THEN XOUT := XOUT + XIN * TIME_TO_REAL(CYCLE);
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/lag1_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,16 @@
+ FUNCTION_BLOCK LAG1
+   VAR_INPUT
+     RUN : BOOL ;     (* 1 = run, 0 = reset *)
+     XIN : REAL ;     (* Input variable *)
+     TAU : TIME ;     (* Filter time constant *)
+     CYCLE : TIME ;   (* Sampling time interval *)
+   END_VAR
+   VAR_OUTPUT XOUT : REAL ; END_VAR  (* Filtered output *)
+   VAR K : REAL ;     (* Smoothing constant, 0.0<=K<1.0 *)
+   END_VAR
+   IF RUN THEN XOUT := XOUT + K * (XIN - XOUT) ;
+   ELSE XOUT := XIN ;
+        K := TIME_TO_REAL(CYCLE) / TIME_TO_REAL(CYCLE + TAU) ;
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/pid_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,25 @@
+ FUNCTION_BLOCK PID
+   VAR_INPUT
+     AUTO : BOOL ;        (* 0 - manual , 1 - automatic *)
+     PV : REAL ;          (* Process variable *)
+     SP : REAL ;          (* Set point *)
+     X0 : REAL ;          (* Manual output adjustment - *)
+                          (* Typically from transfer station *)
+     KP : REAL ;          (* Proportionality constant *)
+     TR : REAL ;          (* Reset time *)
+     TD : REAL ;          (* Derivative time constant *)
+     CYCLE : TIME ;       (* Sampling period *)
+   END_VAR
+   VAR_OUTPUT XOUT : REAL; END_VAR
+   VAR ERROR : REAL ;        (* PV - SP *)
+       ITERM : INTEGRAL ;    (* FB for integral term  *)
+       DTERM : DERIVATIVE ;  (* FB for derivative term *)
+   END_VAR
+   ERROR := PV - SP ;
+   (*** Adjust ITERM so that XOUT := X0 when AUTO = 0 ***)
+   ITERM (RUN := AUTO, R1 := NOT AUTO, XIN := ERROR,
+          X0 := TR * (X0 - ERROR), CYCLE := CYCLE) ;
+   DTERM (RUN := AUTO, XIN := ERROR, CYCLE := CYCLE) ;
+   XOUT := KP * (ERROR + ITERM.XOUT/TR + DTERM.XOUT*TD) ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/ramp_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,25 @@
+ FUNCTION_BLOCK RAMP
+   VAR_INPUT
+     RUN : BOOL ;      (* 0 - track X0, 1 - ramp to/track X1 *)     
+     X0,X1 : REAL ;
+     TR : TIME ;       (* Ramp duration *)
+     CYCLE : TIME ;    (* Sampling period *)
+   END_VAR
+   VAR_OUTPUT
+     BUSY : BOOL ; (* BUSY = 1 during ramping period *)
+     XOUT : REAL := 0.0 ;
+   END_VAR
+   VAR XI : REAL ;       (* Initial value *)
+       T : TIME := T#0s; (* Elapsed time of ramp *)
+   END_VAR
+   BUSY := RUN ;
+   IF RUN THEN
+      IF T >= TR THEN BUSY := 0 ; XOUT := X1 ;
+      ELSE XOUT := XI + (X1-XI) * TIME_TO_REAL(T)
+                                / TIME_TO_REAL(TR) ;
+           T := T + CYCLE ;
+      END_IF ;
+   ELSE XOUT := X0 ; XI := X0 ; T := t#0s ;
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/readme	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,6 @@
+		IEC 61131-3 Annex F	Examples (informative)
+
+This directory contains example code take from:
+
+Annex F of Draft 2nd edition of the IEC 61131-3 standard (1998)
+"PROGRAMMABLE CONTROLLERS - PROGRAMMING LANGUAGES"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/stack_int_il.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,58 @@
+FUNCTION_BLOCK STACK_INT
+  VAR_INPUT PUSH, POP: BOOL R_EDGE; (* Basic stack operations *)
+            R1 : BOOL ;          (* Over-riding reset *)
+            IN : INT ;           (* Input to be pushed *)
+            N  : INT ;           (* Maximum depth after reset *)
+  END_VAR
+  VAR_OUTPUT EMPTY : BOOL := 1 ;     (* Stack empty *)
+             OFLO  : BOOL := 0 ;     (* Stack overflow *)
+             OUT   : INT  := 0 ;     (* Top of stack data *)
+  END_VAR
+  VAR STK : ARRAY[0..127] OF INT; (* Internal stack *)
+      NI : INT :=128  ;           (* Storage for N upon reset *)
+      PTR : INT := -1 ;           (* Stack pointer *)
+  END_VAR
+    (* Function Block body *)
+	LD	R1	(* Dispatch on operations *)
+	JMPC	RESET	
+	LD	POP	
+	ANDN	EMPTY	(* Don't pop empty stack *)
+	JMPC	POP_STK	
+	LD	PUSH	
+	ANDN	OFLO	(* Don't push overflowed stack *)
+	JMPC	PUSH_STK	
+	RET		(* Return if no operations active *)
+RESET:	LD	0	(* Stack reset operations *)
+	ST	OFLO	
+	LD	1	
+	ST   	EMPTY	
+	LD	-1	
+	ST 	PTR	
+	CAL	LIMIT(MN:=1,IN:=N,MX:=128)
+	ST	NI	
+	JMP	ZRO_OUT	
+POP_STK:	LD	0	
+	ST	OFLO	(* Popped stack is not overflowing *)
+	LD	PTR	
+	SUB	1	
+	ST	PTR	
+	LT	0	(* Empty when PTR < 0 *)
+	ST	EMPTY	
+	JMPC	ZRO_OUT	
+	LD	STK[PTR]	
+	JMP	SET_OUT	
+PUSH_STK:	LD	0	
+	ST	EMPTY	(* Pushed stack is not empty *)
+	LD	PTR	
+	ADD	1	
+	ST	PTR	
+	EQ	NI	(* Overflow when PTR = NI *)
+	ST	OFLO	
+	JMPC	ZRO_OUT	
+	LD	IN	
+	ST	STK[PTR]	(* Push IN onto STK *)
+	JMP	SET_OUT	
+ZRO_OUT:	LD	0	(* OUT=0 for EMPTY or OFLO *)
+SET_OUT:	ST 	OUT	
+
+  END_FUNCTION_BLOCK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/stack_int_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,31 @@
+FUNCTION_BLOCK STACK_INT
+  VAR_INPUT PUSH, POP: BOOL R_EDGE; (* Basic stack operations *)
+            R1 : BOOL ;          (* Over-riding reset *)
+            IN : INT ;           (* Input to be pushed *)
+            N  : INT ;           (* Maximum depth after reset *)
+  END_VAR
+  VAR_OUTPUT EMPTY : BOOL := 1 ;     (* Stack empty *)
+             OFLO  : BOOL := 0 ;     (* Stack overflow *)
+             OUT   : INT  := 0 ;     (* Top of stack data *)
+  END_VAR
+  VAR STK : ARRAY[0..127] OF INT; (* Internal stack *)
+      NI : INT :=128  ;           (* Storage for N upon reset *)
+      PTR : INT := -1 ;           (* Stack pointer *)
+  END_VAR
+    (* Function Block body *)
+    IF R1 THEN
+       OFLO := 0; EMPTY := 1; PTR := -1;
+       NI := LIMIT (MN:=1,IN:=N,MX:=128); OUT := 0;
+    ELSIF POP & NOT EMPTY THEN
+       OFLO := 0; PTR := PTR-1; EMPTY := PTR < 0;
+       IF EMPTY THEN OUT := 0;
+       ELSE OUT := STK[PTR];
+       END_IF ;
+    ELSIF PUSH & NOT OFLO THEN
+       EMPTY := 0; PTR := PTR+1; OFLO := (PTR = NI);
+       IF NOT OFLO THEN OUT := IN ; STK[PTR] := IN;
+       ELSE OUT := 0;
+       END_IF ;
+    END_IF ;
+
+  END_FUNCTION_BLOCK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/transfer_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,25 @@
+FUNCTION_BLOCK TRANSFER
+ VAR_INPUT
+   AUTO : BOOL ;     (* 1 - track X0, 0 - ramp or hold *)
+   XIN : REAL ;      (* Typically from PID Function Block *)
+   FAST_RATE, SLOW_RATE : REAL ; (* Up/down ramp slopes *)
+   FAST_UP, SLOW_UP, (* Typically pushbuttons *)
+   FAST_DOWN, SLOW_DOWN : BOOL;
+   CYCLE : TIME ;    (* Sampling period *)
+ END_VAR
+ VAR_OUTPUT XOUT : REAL ; END_VAR
+ VAR XFER_RAMP : INTEGRAL ;
+     RAMP_RATE : REAL ;
+ END_VAR
+ RAMP_RATE := 0.0 ;
+ IF NOT AUTO THEN
+  IF FAST_UP THEN RAMP_RATE := FAST_RATE; END_IF;
+  IF SLOW_UP THEN RAMP_RATE := RAMP_RATE + SLOW_RATE; END_IF;
+  IF FAST_DOWN THEN RAMP_RATE := RAMP_RATE - FAST_RATE; END_IF;
+  IF SLOW_DOWN THEN RAMP_RATE := RAMP_RATE - SLOW_RATE; END_IF;
+ END_IF ;
+ XFER_RAMP (RUN := 1, CYCLE := CYCLE, R1 := AUTO,
+            XIN := RAMP_RATE, X0 := XIN) ;
+ XOUT := XFER_RAMP.XOUT;
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/weigh_il.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,18 @@
+FUNCTION WEIGH : WORD     (* BCD encoded *)
+  VAR_INPUT  (* "EN" input is used to indicate "scale ready" *)
+    weigh_command : BOOL;
+    gross_weight : WORD ; (* BCD encoded *)
+    tare_weight : INT ;
+  END_VAR
+(* Function Body *)
+	LD	weigh_command	
+	JMPC	WEIGH_NOW	
+	ST	ENO	(* No weighing, 0 to "ENO" *)
+	RET		
+WEIGH_NOW:	LD	gross_weight	
+	BCD_TO_INT		
+	SUB	tare_weight	
+	INT_TO_BCD		(* Return evaluated weight *)
+	ST	WEIGH	
+
+END_FUNCTION                     (* Implicit "ENO" *)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AnnexF/weigh_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,12 @@
+FUNCTION WEIGH : WORD     (* BCD encoded *)
+  VAR_INPUT  (* "EN" input is used to indicate "scale ready" *)
+    weigh_command : BOOL;
+    gross_weight : WORD ; (* BCD encoded *)
+    tare_weight : INT ;
+  END_VAR
+(* Function Body *)
+IF weigh_command THEN
+  WEIGH := INT_TO_BCD (BCD_TO_INT(gross_weight) - tare_weight);
+END_IF ;
+
+END_FUNCTION                     (* Implicit "ENO" *)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,63 @@
+# include the system specific Makefile
+#include ../../Makefile.$(shell uname)
+ 
+default: all
+
+all: iec2cc iec2iec
+
+install: all
+	install -d $(INSTALL_PREDIR)/$(INSTALL_BINDIR)/ 
+	install -d $(INSTALL_PREDIR)/$(IECLIBDIR)/
+	install iec2cc    $(INSTALL_PREDIR)/$(INSTALL_BINDIR)/
+	install lib/*.txt $(INSTALL_PREDIR)/$(IECLIBDIR)/
+#	install iec2iec   $(INSTALL_PREDIR)/$(INSTALL_BINDIR)/
+
+
+uninstall:
+	rm -f $(INSTALL_PREDIR)/$(INSTALL_BINDIR)/iec2cc
+	rm -f $(INSTALL_PREDIR)/$(INSTALL_BINDIR)/iec2iec
+	for ff in `cd lib; ls *.txt; cd ..` do echo $$ff done
+#	for ff in `cd lib; ls *.txt; cd ..` do rm -f $(INSTALL_PREDIR)/$(IECLIBDIR)/$$ff done
+
+
+clean:
+	-rm -f iec2iec iec2cc *.o absyntax/*.o Makefile.depend
+# make something everywhere (ie, in all Makefiles that have that target)
+	find . -depth -mindepth 2 -maxdepth 2 -name Makefile -printf %h\\n | xargs -i make -C{} $@
+
+
+
+#get warnings, debugging information and optimization
+CXXFLAGS  = -Wall -pedantic -Wpointer-arith -Wwrite-strings
+# CXXFLAGS += -Werror
+CXXFLAGS += -ggdb -O3 -funroll-loops
+# Note: if the optimizer crashes, we'll leave out the -O3 for those files
+
+CXXFLAGS += -I.
+
+
+
+LIBS  = absyntax/absyntax.o absyntax/visitor.o
+LIBS += stage1_2/iec.y.o stage1_2/iec.flex.o
+
+iec2cc: main.o stage4/generate_cc/generate_cc.o stage4/stage4.o $(LIBS)
+	$(CXX) -o iec2cc main.o stage4/stage4.o stage4/generate_cc/generate_cc.o $(LIBS)
+
+
+iec2iec: main.o stage4/generate_iec/generate_iec.o stage4/stage4.o $(LIBS)
+	$(CXX) -o iec2iec main.o stage4/stage4.o stage4/generate_iec/generate_iec.o $(LIBS)
+
+
+#how to make things in subdirectories etc
+../% /% absyntax/% stage1_2/% stage3/% stage4/% util/%:
+	$(MAKE) -C $(@D) $(@F)
+
+Makefile.depend depend:
+	$(CXX) -MM -MG -I. *.cc \
+	  | perl -pe 's/:/ Makefile.depend:/' > Makefile.depend
+
+include Makefile.depend
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax/Makefile	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,30 @@
+# include the system specific Makefile
+#include ../../../Makefile.$(shell uname)
+
+
+
+
+default: all
+
+all: absyntax.o visitor.o
+
+clean:
+	rm -f *.o
+	find . -depth -mindepth 2 -maxdepth 2 -name Makefile -printf %h\\n | xargs -i make -C{} $@
+
+
+#get warnings, debugging information and optimization
+CXXFLAGS  = -Wall -pedantic -Wpointer-arith -Wwrite-strings
+# CXXFLAGS += -Werror
+
+CXXFLAGS += -ggdb -O3 -funroll-loops
+# Note: if the optimizer crashes, we'll leave out the -O3 for those files
+
+CXXFLAGS += -I. -I../* -I../../absyntax
+
+
+
+#how to make things in subdirectories etc
+../% /% absyntax/% stage1_2/% stage3/% stage4/% util/%:
+	        $(MAKE) -C $(@D) $(@F)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax/absyntax.cc	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,159 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/*
+ * Definition of the Abstract Syntax data structure components
+ */
+
+#include <stdio.h>
+#include <stdlib.h>	/* required for exit() */
+#include <string.h>
+
+#include "absyntax.hh"
+//#include "../stage1_2/iec.hh" /* required for BOGUS_TOKEN_ID, etc... */
+#include "visitor.hh"
+
+#define ABORT(str) {printf("ERROR: %s\n", str); exit(0);}
+
+
+
+symbol_c *tree_root = NULL;
+
+
+
+
+/* The base class of all symbols */
+symbol_c::symbol_c(void) {
+  lineno = 0;
+}
+
+symbol_c::symbol_c(long lineno) {
+  this->lineno = lineno;
+}
+
+
+
+token_c::token_c(const char *value) {
+  this->value = value;
+//  printf("New token: %s\n", value);
+}
+
+
+
+
+
+
+list_c::list_c(void) {
+  n = 0;
+  elements = NULL;
+}
+
+list_c::list_c(symbol_c *elem) {
+  n = 0;
+  elements = NULL;
+  add_element(elem);
+}
+
+/* insert a new element */
+void list_c::add_element(symbol_c *elem) {
+//printf("list_c::add_element()\n");
+  n++;
+  elements = (symbol_c **)realloc(elements, n * sizeof(symbol_c *));
+  if (elements == NULL)
+    ABORT("Out of memory");
+  elements[n - 1] = elem;
+}
+
+
+
+
+
+#define SYM_LIST(class_name_c)							\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+#define SYM_TOKEN(class_name_c)							\
+class_name_c::class_name_c(const char *value): token_c(value) {}			\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+#define SYM_REF0(class_name_c)			\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+#define SYM_REF2(class_name_c, ref1, ref2)	\
+class_name_c::class_name_c(symbol_c *ref1,	\
+			   symbol_c *ref2) {	\
+  this->ref1 = ref1;				\
+  this->ref2 = ref2;				\
+}						\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
+class_name_c::class_name_c(symbol_c *ref1,		\
+			   symbol_c *ref2,		\
+			   symbol_c *ref3,		\
+			   symbol_c *ref4) {		\
+  this->ref1 = ref1;					\
+  this->ref2 = ref2;					\
+  this->ref3 = ref3;					\
+  this->ref4 = ref4;					\
+}							\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+class_name_c::class_name_c(symbol_c *ref1,				\
+			   symbol_c *ref2,				\
+			   symbol_c *ref3,				\
+			   symbol_c *ref4,				\
+			   symbol_c *ref5,				\
+			   symbol_c *ref6) {				\
+  this->ref1 = ref1;						\
+  this->ref2 = ref2;						\
+  this->ref3 = ref3;						\
+  this->ref4 = ref4;						\
+  this->ref5 = ref5;						\
+  this->ref6 = ref6;						\
+}								\
+void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
+
+
+
+#include "absyntax.def"
+
+
+
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax/absyntax.def	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,852 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/*
+ * Definition of the Abstract Syntax data structure components
+ */
+
+
+/*
+ * ABSYNTAX.DEF
+ *
+ * This generates the parse tree structure used to bind the components
+ * identified by Bison in the correct syntax order. At the end of the
+ * Bison analysis the tree is walked in a sequential fashion generating
+ * the relavent code.
+ */
+
+
+/***************************/
+/* 2.1.6 - Pragmas */
+/***************************/
+SYM_TOKEN(pragma_c)
+
+
+/***************************/
+/* B 0 - Programming Model */
+/***************************/
+SYM_LIST(library_c)
+
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+/*******************************************/
+/* B 1.1 - Letters, digits and identifiers */
+/*******************************************/
+SYM_TOKEN(identifier_c)
+
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+SYM_TOKEN(real_c)
+SYM_TOKEN(integer_c)
+SYM_TOKEN(binary_integer_c)
+SYM_TOKEN(octal_integer_c)
+SYM_TOKEN(hex_integer_c)
+
+/* Note:
+ * We do not have signed_integer_c and signed_real_c classes.
+ * These are stored in the parse tree as a integer_c or real_c
+ * preceded by a unary minus operator.
+ */
+/* Not required:
+SYM_TOKEN(signed_integer_c)
+SYM_TOKEN(signed_real_c)
+*/
+
+SYM_REF2(numeric_literal_c, type, value)
+SYM_REF2(integer_literal_c, type, value)
+SYM_REF2(real_literal_c, type, value)
+SYM_REF2(bit_string_literal_c, type, value)
+SYM_REF2(boolean_literal_c, type, value)
+
+/* helper class for boolean_literal_c */
+SYM_REF0(boolean_true_c)
+
+/* helper class for boolean_literal_c */
+SYM_REF0(boolean_false_c)
+
+
+/*******************************/
+/* B.1.2.2   Character Strings */
+/*******************************/
+SYM_TOKEN(double_byte_character_string_c)
+SYM_TOKEN(single_byte_character_string_c)
+
+
+/***************************/
+/* B 1.2.3 - Time Literals */
+/***************************/
+
+/************************/
+/* B 1.2.3.1 - Duration */
+/************************/
+SYM_REF0(neg_time_c)
+SYM_REF2(duration_c, neg, interval)
+SYM_TOKEN(fixed_point_c)
+SYM_REF2(days_c, days, hours)
+SYM_REF2(hours_c, hours, minutes)
+SYM_REF2(minutes_c, minutes, seconds)
+SYM_REF2(seconds_c, seconds, milliseconds)
+SYM_REF2(milliseconds_c, milliseconds, unused)
+
+
+/************************************/
+/* B 1.2.3.2 - Time of day and Date */
+/************************************/
+SYM_REF2(time_of_day_c, daytime, unused)
+SYM_REF4(daytime_c, day_hour, day_minute, day_second, unused)
+SYM_REF2(date_c, date_literal, unused)
+SYM_REF4(date_literal_c, year, month, day, unused)
+SYM_REF2(date_and_time_c, date_literal, daytime)
+
+
+/**********************/
+/* B.1.3 - Data types */
+/**********************/
+/***********************************/
+/* B 1.3.1 - Elementary Data Types */
+/***********************************/
+SYM_REF0(time_type_name_c)
+SYM_REF0(bool_type_name_c)
+SYM_REF0(sint_type_name_c)
+SYM_REF0(int_type_name_c)
+SYM_REF0(dint_type_name_c)
+SYM_REF0(lint_type_name_c)
+SYM_REF0(usint_type_name_c)
+SYM_REF0(uint_type_name_c)
+SYM_REF0(udint_type_name_c)
+SYM_REF0(ulint_type_name_c)
+SYM_REF0(real_type_name_c)
+SYM_REF0(lreal_type_name_c)
+SYM_REF0(date_type_name_c)
+SYM_REF0(tod_type_name_c)
+SYM_REF0(dt_type_name_c)
+SYM_REF0(byte_type_name_c)
+SYM_REF0(word_type_name_c)
+SYM_REF0(dword_type_name_c)
+SYM_REF0(lword_type_name_c)
+SYM_REF0(string_type_name_c)
+SYM_REF0(wstring_type_name_c)
+
+
+
+/********************************/
+/* B.1.3.2 - Generic data types */
+/********************************/
+
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+/*  TYPE type_declaration_list END_TYPE */
+SYM_REF2(data_type_declaration_c, type_declaration_list, unused)
+
+/* helper symbol for data_type_declaration */
+SYM_LIST(type_declaration_list_c)
+
+/*  simple_type_name ':' simple_spec_init */
+SYM_REF2(simple_type_declaration_c, simple_type_name, simple_spec_init)
+
+
+/* simple_specification ASSIGN constant */
+SYM_REF2(simple_spec_init_c, simple_specification, constant)
+
+/*  subrange_type_name ':' subrange_spec_init */
+SYM_REF2(subrange_type_declaration_c, subrange_type_name, subrange_spec_init)
+
+/* subrange_specification ASSIGN signed_integer */
+SYM_REF2(subrange_spec_init_c, subrange_specification, signed_integer)
+
+/*  integer_type_name '(' subrange')' */
+SYM_REF2(subrange_specification_c, integer_type_name, subrange)
+
+/*  signed_integer DOTDOT signed_integer */
+SYM_REF2(subrange_c, lower_limit, upper_limit)
+
+/*  enumerated_type_name ':' enumerated_spec_init */
+SYM_REF2(enumerated_type_declaration_c, enumerated_type_name, enumerated_spec_init)
+
+/* enumerated_specification ASSIGN enumerated_value */
+SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value)
+
+/* helper symbol for enumerated_specification->enumerated_spec_init */
+/* enumerated_value_list ',' enumerated_value */
+SYM_LIST(enumerated_value_list_c)
+
+/* enumerated_type_name '#' identifier */
+SYM_REF2(enumerated_value_c, type, value)
+
+/*  identifier ':' array_spec_init */
+SYM_REF2(array_type_declaration_c, identifier, array_spec_init)
+
+/* array_specification [ASSIGN array_initialization} */
+/* array_initialization may be NULL ! */
+SYM_REF2(array_spec_init_c, array_specification, array_initialization)
+
+/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+SYM_REF2(array_specification_c, array_subrange_list, non_generic_type_name)
+
+/* helper symbol for array_specification */
+/* array_subrange_list ',' subrange */
+SYM_LIST(array_subrange_list_c)
+
+/* array_initialization:  '[' array_initial_elements_list ']' */
+/* helper symbol for array_initialization */
+/* array_initial_elements_list ',' array_initial_elements */
+SYM_LIST(array_initial_elements_list_c)
+
+/* integer '(' [array_initial_element] ')' */
+/* array_initial_element may be NULL ! */
+SYM_REF2(array_initial_elements_c, integer, array_initial_element)
+
+/*  structure_type_name ':' structure_specification */
+SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification)
+
+/* structure_type_name ASSIGN structure_initialization */
+/* structure_initialization may be NULL ! */
+SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+
+/* helper symbol for structure_declaration */
+/* structure_declaration:  STRUCT structure_element_declaration_list END_STRUCT */
+/* structure_element_declaration_list structure_element_declaration ';' */
+SYM_LIST(structure_element_declaration_list_c)
+
+/*  structure_element_name ':' *_spec_init */
+SYM_REF2(structure_element_declaration_c, structure_element_name, spec_init)
+
+/* helper symbol for structure_initialization */
+/* structure_initialization: '(' structure_element_initialization_list ')' */
+/* structure_element_initialization_list ',' structure_element_initialization */
+SYM_LIST(structure_element_initialization_list_c)
+
+/*  structure_element_name ASSIGN value */
+SYM_REF2(structure_element_initialization_c, structure_element_name, value)
+
+/*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
+/*
+ * NOTE:
+ * (Summary: Contrary to what is expected, the
+ *           string_type_declaration_c is not used to store
+ *           simple string type declarations that do not include
+ *           size limits.
+ *           For e.g.:
+ *             str1_type: STRING := "hello!"
+ *           will be stored in a simple_type_declaration_c
+ *           instead of a string_type_declaration_c.
+ *           The following:
+ *             str2_type: STRING [64] := "hello!"
+ *           will be stored in a sring_type_declaration_c
+ *
+ *           Read on for why this is done...
+ * End Summary)
+ *
+ * According to the spec, the valid construct
+ * TYPE new_str_type : STRING := "hello!"; END_TYPE
+ * has two possible routes to type_declaration...
+ *
+ * Route 1:
+ * type_declaration: single_element_type_declaration
+ * single_element_type_declaration: simple_type_declaration
+ * simple_type_declaration: identifier ':' simple_spec_init
+ * simple_spec_init: simple_specification ASSIGN constant
+ * (shift:  identifier <- 'new_str_type')
+ * simple_specification: elementary_type_name
+ * elementary_type_name: STRING
+ * (shift: elementary_type_name <- STRING)
+ * (reduce: simple_specification <- elementary_type_name)
+ * (shift: constant <- "hello!")
+ * (reduce: simple_spec_init: simple_specification ASSIGN constant)
+ * (reduce: ...)
+ *
+ *
+ * Route 2:
+ * type_declaration: string_type_declaration
+ * string_type_declaration: identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init
+ * (shift:  identifier <- 'new_str_type')
+ * elementary_string_type_name: STRING
+ * (shift: elementary_string_type_name <- STRING)
+ * (shift: string_type_declaration_size <-  empty )
+ * string_type_declaration_init: ASSIGN character_string
+ * (shift: character_string <- "hello!")
+ * (reduce: string_type_declaration_init <- ASSIGN character_string)
+ * (reduce: string_type_declaration <- identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init )
+ * (reduce: type_declaration <- string_type_declaration)
+ *
+ *
+ * At first glance it seems that removing route 1 would make
+ * the most sense. Unfortunately the construct 'simple_spec_init'
+ * shows up multiple times in other rules, so changing this construct
+ * would also mean changing all the rules in which it appears.
+ * I (Mario) therefore chose to remove route 2 instead. This means
+ * that the above declaration gets stored in a
+ * simple_type_declaration_c, and not in a string_type_declaration_c
+ * as would be expected!
+ */
+/*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
+SYM_REF4(string_type_declaration_c,	string_type_name,
+					elementary_string_type_name,
+					string_type_declaration_size,
+					string_type_declaration_init) /* may be == NULL! */
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+SYM_REF2(symbolic_variable_c, var_name, unused)
+
+/********************************************/
+/* B.1.4.1   Directly Represented Variables */
+/********************************************/
+SYM_TOKEN(direct_variable_c)
+
+/*************************************/
+/* B.1.4.2   Multi-element Variables */
+/*************************************/
+/*  subscripted_variable '[' subscript_list ']' */
+SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+
+/* subscript_list ',' subscript */
+SYM_LIST(subscript_list_c)
+
+/*  record_variable '.' field_selector */
+/*  WARNING: input and/or output variables of function blocks
+ *           may be accessed as fields of a tructured variable!
+ *           Code handling a structured_variable_c must take
+ *           this into account!
+ */
+SYM_REF2(structured_variable_c, record_variable, field_selector)
+
+/******************************************/
+/* B 1.4.3 - Declaration & Initialisation */
+/******************************************/
+SYM_REF0(constant_option_c)
+SYM_REF0(retain_option_c)
+SYM_REF0(non_retain_option_c)
+
+/* option -> the RETAIN/NON_RETAIN/<NULL> directive... */
+SYM_REF2(input_declarations_c, option, input_declaration_list)
+
+/* helper symbol for input_declarations */
+SYM_LIST(input_declaration_list_c)
+
+/* edge -> The F_EDGE or R_EDGE directive */
+SYM_REF2(edge_declaration_c, edge, var1_list)
+
+SYM_REF0(raising_edge_option_c)
+SYM_REF0(falling_edge_option_c)
+
+/* spec_init is one of the following...
+ *    simple_spec_init_c *
+ *    subrange_spec_init_c *
+ *    enumerated_spec_init_c *
+ */
+SYM_REF2(var1_init_decl_c, var1_list, spec_init)
+
+/* | var1_list ',' variable_name */
+SYM_LIST(var1_list_c)
+
+/* var1_list ':' array_spec_init */
+SYM_REF2(array_var_init_decl_c, var1_list, array_spec_init)
+
+/*  var1_list ':' initialized_structure */
+SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
+
+/* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
+/* structure_initialization -> may be NULL ! */
+SYM_REF4(fb_name_decl_c, fb_name_list, function_block_type_name, structure_initialization, unused)
+
+/* fb_name_list ',' fb_name */
+SYM_LIST(fb_name_list_c)
+
+/* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */
+/* option -> may be NULL ! */
+SYM_REF2(output_declarations_c, option, var_init_decl_list)
+
+/*  VAR_IN_OUT var_declaration_list END_VAR */
+SYM_REF2(input_output_declarations_c, var_declaration_list, unused)
+
+/* helper symbol for input_output_declarations */
+/* var_declaration_list var_declaration ';' */
+SYM_LIST(var_declaration_list_c)
+
+/*  var1_list ':' array_specification */
+SYM_REF2(array_var_declaration_c, var1_list, array_specification)
+
+/*  var1_list ':' structure_type_name */
+SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
+
+/* VAR [CONSTANT] var_init_decl_list END_VAR */
+/* option -> may be NULL ! */
+SYM_REF2(var_declarations_c, option, var_init_decl_list)
+
+/*  VAR RETAIN var_init_decl_list END_VAR */
+SYM_REF2(retentive_var_declarations_c, var_init_decl_list, unused)
+
+/*  VAR [CONSTANT|RETAIN|NON_RETAIN] located_var_decl_list END_VAR */
+/* option -> may be NULL ! */
+SYM_REF2(located_var_declarations_c, option, located_var_decl_list)
+
+/* helper symbol for located_var_declarations */
+/* located_var_decl_list located_var_decl ';' */
+SYM_LIST(located_var_decl_list_c)
+
+/*  [variable_name] location ':' located_var_spec_init */
+/* variable_name -> may be NULL ! */
+SYM_REF4(located_var_decl_c, variable_name, location, located_var_spec_init, unused)
+
+/*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */
+/* option -> may be NULL ! */
+SYM_REF2(external_var_declarations_c, option, external_declaration_list)
+
+/* helper symbol for external_var_declarations */
+/*| external_declaration_list external_declaration';' */
+SYM_LIST(external_declaration_list_c)
+
+/*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
+SYM_REF2(external_declaration_c, global_var_name, specification)
+
+/*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */
+/* option -> may be NULL ! */
+SYM_REF2(global_var_declarations_c, option, global_var_decl_list)
+
+/* helper symbol for global_var_declarations */
+/*| global_var_decl_list global_var_decl ';' */
+SYM_LIST(global_var_decl_list_c)
+
+/*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
+/* type_specification ->may be NULL ! */
+SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
+
+/*| global_var_name location */
+SYM_REF2(global_var_spec_c, global_var_name, location)
+
+/*  AT direct_variable */
+SYM_REF2(location_c, direct_variable, unused)
+
+/*| global_var_list ',' global_var_name */
+SYM_LIST(global_var_list_c)
+
+/*  var1_list ':' single_byte_string_spec */
+SYM_REF2(single_byte_string_var_declaration_c, var1_list, single_byte_string_spec)
+
+/*  STRING ['[' integer ']'] [ASSIGN single_byte_character_string] */
+/* integer ->may be NULL ! */
+/* single_byte_character_string ->may be NULL ! */
+SYM_REF2(single_byte_string_spec_c, integer, single_byte_character_string)
+
+/*  var1_list ':' double_byte_string_spec */
+SYM_REF2(double_byte_string_var_declaration_c, var1_list, double_byte_string_spec)
+
+/*  WSTRING ['[' integer ']'] [ASSIGN double_byte_character_string] */
+/* integer ->may be NULL ! */
+/* double_byte_character_string ->may be NULL ! */
+SYM_REF2(double_byte_string_spec_c, integer, double_byte_character_string)
+
+/*| VAR [RETAIN|NON_RETAIN] incompl_located_var_decl_list END_VAR */
+/* option ->may be NULL ! */
+SYM_REF2(incompl_located_var_declarations_c, option, incompl_located_var_decl_list)
+
+/* helper symbol for incompl_located_var_declarations */
+/*| incompl_located_var_decl_list incompl_located_var_decl ';' */
+SYM_LIST(incompl_located_var_decl_list_c)
+
+/*  variable_name incompl_location ':' var_spec */
+SYM_REF4(incompl_located_var_decl_c, variable_name, incompl_location, var_spec, unused)
+
+/*  AT incompl_location_token */
+SYM_TOKEN(incompl_location_c)
+
+/* intermediate helper symbol for:
+ *  - non_retentive_var_decls
+ *  - output_declarations
+ */
+SYM_LIST(var_init_decl_list_c)
+
+
+
+
+/**************************************/
+/* B.1.5 - Program organization units */
+/**************************************/
+/***********************/
+/* B 1.5.1 - Functions */
+/***********************/
+SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body)
+
+/* intermediate helper symbol for
+ * - function_declaration
+ * - function_block_declaration
+ * - program_declaration
+ */
+SYM_LIST(var_declarations_list_c)
+
+/* option -> storage method, CONSTANT or <null> */
+SYM_REF2(function_var_decls_c, option, decl_list)
+
+/* intermediate helper symbol for function_var_decls */
+SYM_LIST(var2_init_decl_list_c)
+
+
+/*****************************/
+/* B 1.5.2 - Function Blocks */
+/*****************************/
+/*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
+SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
+
+/* intermediate helper symbol for function_declaration */
+/*  { io_var_declarations | other_var_declarations }   */
+/*
+ * NOTE: we re-use the var_declarations_list_c
+ */
+
+/*  VAR_TEMP temp_var_decl_list END_VAR */
+SYM_REF2(temp_var_decls_c, var_decl_list, unused)
+
+/* intermediate helper symbol for temp_var_decls */
+SYM_LIST(temp_var_decls_list_c)
+
+/*  VAR NON_RETAIN var_init_decl_list END_VAR */
+SYM_REF2(non_retentive_var_decls_c, var_decl_list, unused)
+
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+/*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
+SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
+
+/* intermediate helper symbol for program_declaration_c */
+/*  { io_var_declarations | other_var_declarations }   */
+/*
+ * NOTE: we re-use the var_declarations_list_c
+ */
+
+
+
+/*********************************************/
+/* B.1.6  Sequential function chart elements */
+/*********************************************/
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+
+/*
+CONFIGURATION configuration_name
+   optional_global_var_declarations
+   (resource_declaration_list | single_resource_declaration)
+   optional_access_declarations
+   optional_instance_specific_initializations
+END_CONFIGURATION
+*/
+SYM_REF6(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, unused)
+
+/* helper symbol for configuration_declaration */
+SYM_LIST(resource_declaration_list_c)
+
+/*
+RESOURCE resource_name ON resource_type_name
+   optional_global_var_declarations
+   single_resource_declaration
+END_RESOURCE
+*/
+SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration)
+
+/* task_configuration_list program_configuration_list */
+SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
+
+/* helper symbol for single_resource_declaration */
+SYM_LIST(task_configuration_list_c)
+
+/* helper symbol for single_resource_declaration */
+SYM_LIST(program_configuration_list_c)
+
+/* helper symbol for
+ *  - access_path
+ *  - instance_specific_init
+ */
+SYM_LIST(any_fb_name_list_c)
+
+/*  [resource_name '.'] global_var_name ['.' structure_element_name] */
+SYM_REF4(global_var_reference_c, resource_name, global_var_name, structure_element_name, unused)
+
+/*  prev_declared_program_name '.' symbolic_variable */
+SYM_REF2(program_output_reference_c, program_name, symbolic_variable)
+
+/*  TASK task_name task_initialization */
+SYM_REF2(task_configuration_c, task_name, task_initialization)
+
+/*  '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' */
+SYM_REF4(task_initialization_c, single_data_source, interval_data_source, priority_data_source, unused)
+
+/*  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
+SYM_REF6(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements, unused)
+
+/* prog_conf_elements ',' prog_conf_element */
+SYM_LIST(prog_conf_elements_c)
+
+/*  fb_name WITH task_name */
+SYM_REF2(fb_task_c, fb_name, task_name)
+
+/*  any_symbolic_variable ASSIGN prog_data_source */
+SYM_REF2(prog_cnxn_assign_c, symbolic_variable, prog_data_source)
+
+/* any_symbolic_variable SENDTO data_sink */
+SYM_REF2(prog_cnxn_sendto_c, symbolic_variable, prog_data_source)
+
+/* VAR_CONFIG instance_specific_init_list END_VAR */
+SYM_REF2(instance_specific_initializations_c, instance_specific_init_list, unused)
+
+/* helper symbol for instance_specific_initializations */
+SYM_LIST(instance_specific_init_list_c)
+
+/* resource_name '.' program_name '.' {fb_name '.'}
+    ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' fb_initialization))
+*/
+SYM_REF6(instance_specific_init_c, resource_name, program_name, any_fb_name_list, variable_name, location, initialization)
+
+/* helper symbol for instance_specific_init */
+/* function_block_type_name ':=' structure_initialization */
+SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization)
+
+
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+/*| instruction_list il_instruction */
+SYM_LIST(instruction_list_c)
+
+/* | label ':' [il_incomplete_instruction] eol_list */
+SYM_REF2(il_instruction_c, label, il_instruction)
+
+
+/* | il_simple_operator [il_operand] */
+SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
+
+/* | function_name [il_operand_list] */
+SYM_REF2(il_function_call_c, function_name, il_operand_list)
+
+
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+SYM_REF4(il_expression_c, il_expr_operator, il_operand, simple_instr_list, unused)
+
+/*  il_jump_operator label */
+SYM_REF2(il_jump_operation_c, il_jump_operator, label)
+
+/*   il_call_operator prev_declared_fb_name
+ * | il_call_operator prev_declared_fb_name '(' ')'
+ * | il_call_operator prev_declared_fb_name '(' eol_list ')'
+ * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
+ * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
+ */
+SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list)
+
+
+/* | function_name '(' eol_list [il_param_list] ')' */
+SYM_REF2(il_formal_funct_call_c, function_name, il_param_list)
+
+/* | il_operand_list ',' il_operand */
+SYM_LIST(il_operand_list_c)
+
+/* | simple_instr_list il_simple_instruction */
+SYM_LIST(simple_instr_list_c)
+
+/* | il_initial_param_list il_param_instruction */
+SYM_LIST(il_param_list_c)
+
+/*  il_assign_operator il_operand
+ * | il_assign_operator '(' eol_list simple_instr_list ')'
+ */
+SYM_REF4(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list, unused)
+
+/*  il_assign_out_operator variable */
+SYM_REF2(il_param_out_assignment_c, il_assign_out_operator, variable)
+
+
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+SYM_REF0(LD_operator_c)
+SYM_REF0(LDN_operator_c)
+SYM_REF0(ST_operator_c)
+SYM_REF0(STN_operator_c)
+SYM_REF0(NOT_operator_c)
+SYM_REF0(S_operator_c)
+SYM_REF0(R_operator_c)
+SYM_REF0(S1_operator_c)
+SYM_REF0(R1_operator_c)
+SYM_REF0(CLK_operator_c)
+SYM_REF0(CU_operator_c)
+SYM_REF0(CD_operator_c)
+SYM_REF0(PV_operator_c)
+SYM_REF0(IN_operator_c)
+SYM_REF0(PT_operator_c)
+SYM_REF0(AND_operator_c)
+SYM_REF0(OR_operator_c)
+SYM_REF0(XOR_operator_c)
+SYM_REF0(ANDN_operator_c)
+SYM_REF0(ORN_operator_c)
+SYM_REF0(XORN_operator_c)
+SYM_REF0(ADD_operator_c)
+SYM_REF0(SUB_operator_c)
+SYM_REF0(MUL_operator_c)
+SYM_REF0(DIV_operator_c)
+SYM_REF0(MOD_operator_c)
+SYM_REF0(GT_operator_c)
+SYM_REF0(GE_operator_c)
+SYM_REF0(EQ_operator_c)
+SYM_REF0(LT_operator_c)
+SYM_REF0(LE_operator_c)
+SYM_REF0(NE_operator_c)
+SYM_REF0(CAL_operator_c)
+SYM_REF0(CALC_operator_c)
+SYM_REF0(CALCN_operator_c)
+SYM_REF0(RET_operator_c)
+SYM_REF0(RETC_operator_c)
+SYM_REF0(RETCN_operator_c)
+SYM_REF0(JMP_operator_c)
+SYM_REF0(JMPC_operator_c)
+SYM_REF0(JMPCN_operator_c)
+
+/*| [NOT] any_identifier SENDTO */
+SYM_REF2(il_assign_out_operator_c, option, variable_name)
+
+
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+SYM_REF2(or_expression_c, l_exp, r_exp)
+SYM_REF2(xor_expression_c, l_exp, r_exp)
+SYM_REF2(and_expression_c, l_exp, r_exp)
+SYM_REF2(equ_expression_c, l_exp, r_exp)
+SYM_REF2(notequ_expression_c, l_exp, r_exp)
+SYM_REF2(lt_expression_c, l_exp, r_exp)
+SYM_REF2(gt_expression_c, l_exp, r_exp)
+SYM_REF2(le_expression_c, l_exp, r_exp)
+SYM_REF2(ge_expression_c, l_exp, r_exp)
+SYM_REF2(add_expression_c, l_exp, r_exp)
+SYM_REF2(sub_expression_c, l_exp, r_exp)
+SYM_REF2(mul_expression_c, l_exp, r_exp)
+SYM_REF2(div_expression_c, l_exp, r_exp)
+SYM_REF2(mod_expression_c, l_exp, r_exp)
+SYM_REF2(power_expression_c, l_exp, r_exp)
+SYM_REF2(neg_expression_c, exp, unused)
+SYM_REF2(not_expression_c, exp, unused)
+
+SYM_REF2(function_invocation_c, function_name, parameter_assignment_list)
+
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+SYM_LIST(statement_list_c)
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+SYM_REF2(assignment_statement_c, l_exp, r_exp)
+
+
+/*****************************************/
+/* B 3.2.2 Subprogram Control Statements */
+/*****************************************/
+/*  RETURN */
+SYM_REF0(return_statement_c)
+
+/* fb_name '(' [param_assignment_list] ')' */
+/* param_assignment_list -> may be NULL ! */
+SYM_REF2(fb_invocation_c, fb_name, param_assignment_list)
+
+/* helper symbol for fb_invocation */
+/* param_assignment_list ',' param_assignment */
+SYM_LIST(param_assignment_list_c)
+
+/*  variable_name ASSIGN expression */
+SYM_REF2(input_variable_param_assignment_c, variable_name, expression)
+
+/* [NOT] variable_name '=>' variable */
+SYM_REF4(output_variable_param_assignment_c, not_param, variable_name, variable, unused)
+
+/* helper CLASS for output_variable_param_assignment */
+SYM_REF0(not_paramassign_c)
+
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+/* IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF */
+SYM_REF4(if_statement_c, expression, statement_list, elseif_statement_list, else_statement_list)
+
+/* helper symbol for if_statement */
+SYM_LIST(elseif_statement_list_c)
+
+/* helper symbol for elseif_statement_list */
+/* ELSIF expression THEN statement_list    */
+SYM_REF2(elseif_statement_c, expression, statement_list)
+
+/* CASE expression OF case_element_list ELSE statement_list END_CASE */
+SYM_REF4(case_statement_c, expression, case_element_list, statement_list, unused)
+
+/* helper symbol for case_statement */
+SYM_LIST(case_element_list_c)
+
+/*  case_list ':' statement_list */
+SYM_REF2(case_element_c, case_list, statement_list)
+
+SYM_LIST(case_list_c)
+
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+/*  FOR control_variable ASSIGN expression TO expression [BY expression] DO statement_list END_FOR */
+SYM_REF6(for_statement_c, control_variable, beg_expression, end_expression, by_expression, statement_list, unused)
+
+/*  WHILE expression DO statement_list END_WHILE */
+SYM_REF2(while_statement_c, expression, statement_list)
+
+/*  REPEAT statement_list UNTIL expression END_REPEAT */
+SYM_REF2(repeat_statement_c, statement_list, expression)
+
+/*  EXIT */
+SYM_REF0(exit_statement_c)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax/absyntax.hh	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,189 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/*
+ * Declaration of the Abstract Syntax data structure components
+ */
+
+/*
+ * ABSYNTAX.H
+ *
+ * This generates the parse tree structure used to bind the components
+ * identified by Bison in the correct syntax order. At the end of the
+ * Bison analysis the tree is walked in a sequential fashion generating
+ * the relavent code.
+ */
+
+#ifndef _ABSYNTAX_HH
+#define _ABSYNTAX_HH
+
+
+#include <stdio.h> // required for NULL
+
+/* Forward declaration of the visitor interface
+ * dclared in the visitor.hh file
+ * We cannot include the visitor.hh file, as it will
+ * include this same file first, as it too requires references
+ * to the abstract syntax classes defined here.
+ */
+class visitor_c; // forward declaration
+
+
+class symbol_c; // forward declaration
+//extern symbol_c *tree_root;
+
+
+
+/* The base class of all symbols */
+class symbol_c {
+
+  public:
+    /*
+     * Line number for the purposes of error checking
+     */
+    long lineno;
+
+  public:
+    /* default constructor */
+    symbol_c(void);
+    symbol_c(long lineno);
+
+    /* default destructor */
+    /* must be virtual so compiler does not complain... */ 
+    virtual ~symbol_c(void) {return;};
+
+    virtual void *accept(visitor_c &visitor) {return NULL;};
+};
+
+
+class token_c: public symbol_c {
+  public:
+    /* the value of the symbol. */
+    const char *value;
+
+  public:
+    token_c(const char *value);
+};
+
+
+ /* a list of symbols... */
+class list_c: public symbol_c {
+  public:
+    int n;
+    symbol_c **elements;
+
+  public:
+    list_c(void);
+    list_c(symbol_c *elem);
+     /* insert a new element */
+    virtual void add_element(symbol_c *elem);
+};
+
+
+
+
+#define SYM_LIST(class_name_c)			\
+class class_name_c:	public list_c {		\
+  public:					\
+    virtual void *accept(visitor_c &visitor);	\
+};
+
+
+#define SYM_TOKEN(class_name_c)			\
+class class_name_c: 	public token_c {	\
+  public:					\
+    class_name_c(const char *value);			\
+    virtual void *accept(visitor_c &visitor);	\
+};
+
+
+#define SYM_REF0(class_name_c)			\
+class class_name_c: public symbol_c {		\
+  public:					\
+    virtual void *accept(visitor_c &visitor);	\
+};
+
+
+#define SYM_REF2(class_name_c, ref1, ref2)	\
+class class_name_c: public symbol_c {		\
+  public:					\
+    symbol_c *ref1;				\
+    symbol_c *ref2;				\
+  public:					\
+    class_name_c(symbol_c *ref1,		\
+		 symbol_c *ref2 = NULL);	\
+    virtual void *accept(visitor_c &visitor);	\
+};
+
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
+class class_name_c: public symbol_c {			\
+  public:						\
+    symbol_c *ref1;					\
+    symbol_c *ref2;					\
+    symbol_c *ref3;					\
+    symbol_c *ref4;					\
+  public:						\
+    class_name_c(symbol_c *ref1,			\
+		 symbol_c *ref2,			\
+		 symbol_c *ref3,			\
+		 symbol_c *ref4 = NULL);		\
+    virtual void *accept(visitor_c &visitor);		\
+};
+
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+class class_name_c: public symbol_c {					\
+  public:								\
+    symbol_c *ref1;							\
+    symbol_c *ref2;							\
+    symbol_c *ref3;							\
+    symbol_c *ref4;							\
+    symbol_c *ref5;							\
+    symbol_c *ref6;							\
+  public:								\
+    class_name_c(symbol_c *ref1,					\
+		 symbol_c *ref2,					\
+		 symbol_c *ref3,					\
+		 symbol_c *ref4,					\
+		 symbol_c *ref5,					\
+		 symbol_c *ref6 = NULL);		\
+    virtual void *accept(visitor_c &visitor);				\
+};
+
+
+#include "absyntax.def"
+
+
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+
+
+#endif /*  _ABSYNTAX_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax/visitor.cc	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,265 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * VISITOR.CC
+ *
+ * Three base implementations of the visitor interface,
+ * that may be later extended to execute a particular algorithm.
+ *
+ * The null (class null_visitor_c) does nothing.
+ *
+ * The iterator (class iterator_visitor_c) iterates through
+ * every object in the syntax tree.
+ *
+ * The search class (class search_visitor_c) iterates through
+ * every object, until one returns a value != NULL.
+ */
+
+
+
+
+
+#include <unistd.h>
+
+#include <stdio.h>  /* required for NULL */
+#include "visitor.hh"
+
+#include <iostream>
+
+
+/******************/
+/* visitor_c      */
+/******************/
+
+visitor_c::~visitor_c(void) {return;}
+
+
+/******************/
+/* null_visitor_c */
+/******************/
+
+null_visitor_c::~null_visitor_c(void) {return;}
+
+#define SYM_LIST(class_name_c)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_TOKEN(class_name_c)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF0(class_name_c)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF2(class_name_c, ref1, ref2)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+
+#include "absyntax.def"
+
+
+
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+
+
+
+
+
+/**********************/
+/* iterator_visitor_c */
+/**********************/
+
+iterator_visitor_c::~iterator_visitor_c(void) {return;}
+
+
+void *iterator_visitor_c::visit_list(list_c *list) {
+  for(int i = 0; i < list->n; i++) {
+    list->elements[i]->accept(*this);
+  }
+  return NULL;
+}
+
+
+#define SYM_LIST(class_name_c)	\
+  void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
+
+#define SYM_TOKEN(class_name_c)	\
+  void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF0(class_name_c)	\
+  void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF2(class_name_c, ref1, ref2)		\
+void *iterator_visitor_c::visit(class_name_c *symbol) {	\
+  if (symbol->ref1!=NULL) symbol->ref1->accept(*this);	\
+  if (symbol->ref2!=NULL) symbol->ref2->accept(*this);	\
+  return NULL;						\
+}
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
+void *iterator_visitor_c::visit(class_name_c *symbol) {	\
+  if (symbol->ref1) symbol->ref1->accept(*this);	\
+  if (symbol->ref2) symbol->ref2->accept(*this);	\
+  if (symbol->ref3) symbol->ref3->accept(*this);	\
+  if (symbol->ref4) symbol->ref4->accept(*this);	\
+  return NULL;						\
+}
+
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+void *iterator_visitor_c::visit(class_name_c *symbol) {			\
+  if (symbol->ref1) symbol->ref1->accept(*this);			\
+  if (symbol->ref2) symbol->ref2->accept(*this);			\
+  if (symbol->ref3) symbol->ref3->accept(*this);			\
+  if (symbol->ref4) symbol->ref4->accept(*this);			\
+  if (symbol->ref5) symbol->ref5->accept(*this);			\
+  if (symbol->ref6) symbol->ref6->accept(*this);			\
+  return NULL;								\
+}
+
+
+
+#include "absyntax.def"
+
+
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+
+
+
+
+
+
+
+
+
+/********************/
+/* search_visitor_c */
+/********************/
+
+search_visitor_c::~search_visitor_c(void) {return;}
+
+
+void *search_visitor_c::visit_list(list_c *list) {
+  for(int i = 0; i < list->n; i++) {
+    void *res = list->elements[i]->accept(*this);
+    if (res != NULL)
+      return res;
+  }
+  return NULL;
+}
+
+
+#define SYM_LIST(class_name_c)	\
+  void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
+
+#define SYM_TOKEN(class_name_c)	\
+  void *search_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF0(class_name_c)	\
+  void *search_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF2(class_name_c, ref1, ref2)			\
+void *search_visitor_c::visit(class_name_c *symbol) {		\
+  void *res = NULL;						\
+  if (symbol->ref1) res =  symbol->ref1->accept(*this);		\
+  if (res != NULL)  return res;					\
+  if (symbol->ref2) return symbol->ref2->accept(*this);		\
+  return NULL;							\
+}
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)		\
+void *search_visitor_c::visit(class_name_c *symbol) {		\
+  void *res = NULL;						\
+  if (symbol->ref1) res =  symbol->ref1->accept(*this);		\
+  if (res != NULL)  return res;					\
+  if (symbol->ref2) res =  symbol->ref2->accept(*this);		\
+  if (res != NULL)  return res;					\
+  if (symbol->ref3) res =  symbol->ref3->accept(*this);		\
+  if (res != NULL)  return res;					\
+  if (symbol->ref4) return symbol->ref4->accept(*this);		\
+  return NULL;							\
+}
+
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+void *search_visitor_c::visit(class_name_c *symbol) {			\
+  void *res = NULL;							\
+  if (symbol->ref1) res =  symbol->ref1->accept(*this);			\
+  if (res != NULL)  return res;						\
+  if (symbol->ref2) res =  symbol->ref2->accept(*this);			\
+  if (res != NULL)  return res;						\
+  if (symbol->ref3) res =  symbol->ref3->accept(*this);			\
+  if (res != NULL)  return res;						\
+  if (symbol->ref4) res =  symbol->ref4->accept(*this);			\
+  if (res != NULL)  return res;						\
+  if (symbol->ref5) res =  symbol->ref5->accept(*this);			\
+  if (res != NULL)  return res;						\
+  if (symbol->ref6) return symbol->ref6->accept(*this);			\
+  return NULL;								\
+}
+
+
+
+#include "absyntax.def"
+
+
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/absyntax/visitor.hh	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,171 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * VISITOR.HH
+ *
+ *
+ * The asbract syntax tree is scaned several times
+ * during the whole compilation process. For e.g., stage 3 verifies
+ * semantics, and stage 4 produces output.
+ *
+ * Since the number of functions that need to scan through
+ * the abtract syntax tree may increase in time, (e.g. new
+ * output formats, new semantic checks, etc...) while the
+ * abstract syntax tree class structure is pretty stable
+ * (i.e. the ST and IL languages will not be changing much...),
+ * we use the 'visitor' design patern.
+ *
+ * It is not strictly necessary to use this pattern, but it does
+ * have the advantage of bringing together the functions
+ * that implement the same algorithm, each on a different
+ * class of object in the abstract syntax tree.
+ *
+ *
+ * This file contains the interface that each visitor class
+ * must implement in order to be able to visit the abstract
+ * syntax tree (class visitor_c)
+ *
+ * Three implementations of this interface are also provided,
+ * that may be later extended to execute a particular algorithm.
+ *
+ * The null (class null_visitor_c) does nothing.
+ *
+ * The iterator (class iterator_visitor_c) iterates through
+ * every object in the syntax tree.
+ *
+ * The search class (class search_visitor_c) iterates through
+ * every object, until one returns a value != NULL.
+ */
+
+
+#ifndef _VISITOR_HH
+#define _VISITOR_HH
+
+
+
+
+#include "absyntax.hh"
+
+
+
+#define SYM_LIST(class_name_c)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_TOKEN(class_name_c)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF0(class_name_c)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF2(class_name_c, ref1, ref2)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+  virtual void *visit(class_name_c *symbol) = 0;
+
+class visitor_c {
+  public:
+  #include "absyntax.def"
+
+  virtual ~visitor_c(void);
+};
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+
+
+
+
+
+#define SYM_LIST(class_name_c)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_TOKEN(class_name_c)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF0(class_name_c)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF2(class_name_c, ref1, ref2)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF4(class_name_c, ref1, ref2, ref3, ref4)	\
+  virtual void *visit(class_name_c *symbol);
+
+#define SYM_REF6(class_name_c, ref1, ref2, ref3, ref4, ref5, ref6)	\
+  virtual void *visit(class_name_c *symbol);
+
+
+
+
+
+class null_visitor_c: public visitor_c {
+  public:
+  #include "absyntax.def"
+
+  virtual ~null_visitor_c(void);
+};
+
+
+
+class iterator_visitor_c: public visitor_c {
+  protected:
+  void *visit_list(list_c *list);
+
+  public:
+  #include "absyntax.def"
+
+  virtual ~iterator_visitor_c(void);
+};
+
+
+class search_visitor_c: public visitor_c {
+  protected:
+  void *visit_list(list_c *list);
+
+  public:
+  #include "absyntax.def"
+
+  virtual ~search_visitor_c(void);
+};
+
+
+#undef SYM_LIST
+#undef SYM_TOKEN
+#undef SYM_REF0
+#undef SYM_REF2
+#undef SYM_REF4
+#undef SYM_REF6
+
+#endif /*  _VISITOR_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/bcd_to_int.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,98 @@
+(*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * Conversion from BCD
+ * -------------------
+ *)
+
+
+
+FUNCTION BYTE_BCD_TO_USINT: USINT
+  VAR_INPUT
+    BCD : BYTE;
+  END_VAR
+
+  BYTE_BCD_TO_USINT := BCD MOD 16;
+  BCD := BCD / 16;
+  BYTE_BCD_TO_USINT := BYTE_BCD_TO_USINT + 10*BCD;
+END_FUNCTION
+
+
+
+
+FUNCTION WORD_BCD_TO_UINT: UINT
+  VAR_INPUT
+    BCD : WORD;
+  END_VAR
+
+  WORD_BCD_TO_UINT := BCD MOD 16;
+  BCD := BCD / 16;
+  WORD_BCD_TO_UINT := WORD_BCD_TO_UINT + 10*(BCD MOD 16);
+  BCD := BCD / 16;
+  WORD_BCD_TO_UINT := WORD_BCD_TO_UINT + 100*(BCD MOD 16);
+  BCD := BCD / 16;
+  WORD_BCD_TO_UINT := WORD_BCD_TO_UINT + 1000*BCD;
+END_FUNCTION
+
+
+
+
+FUNCTION DWORD_BCD_TO_UDINT: UDINT
+  VAR_INPUT
+    BCD : DWORD;
+  END_VAR
+
+  DWORD_BCD_TO_UDINT := BCD MOD 16;
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 10*(BCD MOD 16);
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 100*(BCD MOD 16);
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 1000*(BCD MOD 16);
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 1_0000*(BCD MOD 16);
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 10_0000*(BCD MOD 16);
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 100_0000*(BCD MOD 16);
+  BCD := BCD / 16;
+  DWORD_BCD_TO_UDINT := DWORD_BCD_TO_UDINT + 1000_0000*BCD;
+END_FUNCTION
+
+
+
+
+FUNCTION LWORD_BCD_TO_ULINT: ULINT
+  VAR_INPUT
+    BCD : LWORD;
+  END_VAR
+
+  LWORD_BCD_TO_ULINT := DWORD_BCD_TO_UDINT(BCD MOD (256*256*256*256));
+  BCD := BCD / (256*256*256*256);
+  LWORD_BCD_TO_ULINT := LWORD_BCD_TO_ULINT + 1_0000_0000*DWORD_BCD_TO_UDINT(BCD);
+END_FUNCTION
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/bistable.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,65 @@
+(*
+ * (c) 26 Feb 2001 David Campbell
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * SR and RS function blocks
+ * -------------------------
+ *)
+
+
+FUNCTION_BLOCK SR
+  VAR_INPUT
+    S1 : BOOL;
+    R  : BOOL;
+  END_VAR
+  VAR_OUTPUT
+    Q1 : BOOL;
+  END_VAR
+  VAR
+    Q_INTERNAL : BOOL;
+  END_VAR
+
+  Q_INTERNAL := S1 OR ( Q_INTERNAL AND (NOT R));
+  Q1 := Q_INTERNAL;
+END_FUNCTION_BLOCK
+
+FUNCTION_BLOCK RS
+  VAR_INPUT
+    S : BOOL;
+    R1 : BOOL;
+  END_VAR
+  VAR_OUTPUT
+    Q1 : BOOL;
+  END_VAR
+  VAR
+    Q_INTERNAL : BOOL;
+  END_VAR
+
+  Q_INTERNAL := (NOT R1) AND (S OR Q_INTERNAL);
+  Q1 := Q_INTERNAL;
+END_FUNCTION_BLOCK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/counter.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,94 @@
+(* Following taken directly from the IEC 61131.3 draft standard *)
+
+(*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * Counter function blocks
+ * -----------------------
+ *)
+
+
+FUNCTION_BLOCK CTU
+  VAR_INPUT
+    CU : BOOL;
+    R : BOOL;
+    PV : INT;
+  END_VAR
+  VAR_OUTPUT
+    Q : BOOL;
+    CV : INT;
+  END_VAR
+  VAR RETAIN
+    PVmax : INT;
+  END_VAR
+  IF R THEN CV := 0 ;
+  ELSIF CU AND (CV < PVmax)
+       THEN CV := CV+1;
+  END_IF ;
+  Q := (CV >= PV) ;
+END_FUNCTION_BLOCK
+
+
+FUNCTION_BLOCK CTD
+  VAR_INPUT
+    CD : BOOL;
+    LD : BOOL;
+    PV : INT;
+  END_VAR
+  VAR_OUTPUT
+    Q : BOOL;
+    CV : INT;
+  END_VAR
+  VAR RETAIN
+    PVmin : INT;
+  END_VAR
+  IF LD THEN CV := PV ;
+  ELSIF CD AND (CV > PVmin)
+      THEN CV := CV-1;
+  END_IF ;
+  Q := (CV <= 0) ;
+END_FUNCTION_BLOCK
+
+
+FUNCTION_BLOCK CTUD
+  VAR_INPUT
+    CU : BOOL;
+    CD : BOOL;
+    R  : BOOL;
+    LD : BOOL;
+    PV : INT;
+  END_VAR
+  VAR_OUTPUT
+    QU : BOOL;
+    QD : BOOL;
+    CV : INT;
+  END_VAR
+  VAR RETAIN
+    PVmax : INT;
+    PVmin : INT;
+  END_VAR
+  IF R THEN CV := 0 ;
+  ELSIF LD THEN CV := PV ;
+  ELSE
+    IF NOT (CU AND CD) THEN
+      IF CU AND (CV < PVmax)
+      THEN CV := CV+1;
+      ELSIF CD AND (CV > PVmin)
+      THEN CV := CV-1;
+      END_IF;
+    END_IF;
+  END_IF ;
+  QU := (CV >= PV) ;
+  QD := (CV <= 0) ;
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/edge_detection.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,35 @@
+(* Following taken directly from the IEC 61131.3 draft standard *)
+
+(*
+ * An IEC 61131-3 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * Edge detection function blocks
+ * ------------------------------
+ *)
+
+FUNCTION_BLOCK R_TRIG
+     VAR_INPUT  CLK: BOOL; END_VAR
+     VAR_OUTPUT  Q: BOOL; END_VAR
+     VAR RETAIN M: BOOL; END_VAR
+Q := CLK AND NOT M;
+M := CLK;
+END_FUNCTION_BLOCK
+
+FUNCTION_BLOCK F_TRIG
+     VAR_INPUT  CLK: BOOL; END_VAR
+     VAR_OUTPUT   Q: BOOL; END_VAR
+     VAR RETAIN M: BOOL; END_VAR
+Q := NOT CLK AND NOT M;
+M := NOT CLK;
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/ieclib.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,36 @@
+(*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+(*
+ * This is the library conatining the functions
+ * and function blocks defined in the standard.
+ *)
+
+{#include "bcd_to_int.txt" }
+{#include "int_to_bcd.txt" }
+{#include "edge_detection.txt" }
+{#include "bistable.txt" }
+{#include "counter.txt" }
+{#include "timer.txt" }
+{#include "time_math.txt" }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/int_to_bcd.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,117 @@
+(*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * Conversion to BCD
+ * -----------------
+ *)
+
+
+
+
+FUNCTION USINT_TO_BCD_BYTE: BYTE
+  VAR_INPUT
+    VALUE : USINT;
+  END_VAR
+
+  USINT_TO_BCD_BYTE := VALUE MOD 10;
+  VALUE := VALUE / 10;
+  USINT_TO_BCD_BYTE := USINT_TO_BCD_BYTE + 16*VALUE;
+  IF VALUE > 9
+  THEN
+    (* The standard is silent on how to handle overflows!! *)
+    (* We simply set it to the highets value!              *)
+    USINT_TO_BCD_BYTE := 16#99;
+  END_IF;
+END_FUNCTION
+
+
+
+
+FUNCTION UINT_TO_BCD_WORD: WORD
+  VAR_INPUT
+    VALUE : UINT;
+  END_VAR
+
+  UINT_TO_BCD_WORD := VALUE MOD 10;
+  VALUE := VALUE / 10;
+  UINT_TO_BCD_WORD := UINT_TO_BCD_WORD + 16*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UINT_TO_BCD_WORD := UINT_TO_BCD_WORD + 16*16*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UINT_TO_BCD_WORD := UINT_TO_BCD_WORD + 16*16*16*VALUE;
+  IF VALUE > 9
+  THEN
+    (* The standard is silent on how to handle overflows!! *)
+    (* We simply set it to the highets value!              *)
+    UINT_TO_BCD_WORD := 16#9999;
+  END_IF;
+END_FUNCTION
+
+
+
+
+FUNCTION UDINT_TO_BCD_DWORD: DWORD
+  VAR_INPUT
+    VALUE : UINT;
+  END_VAR
+
+  UDINT_TO_BCD_DWORD := VALUE MOD 16;
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 16*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 256*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 16*256*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 256*256*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 16*256*256*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 256*256*256*(VALUE MOD 10);
+  VALUE := VALUE / 10;
+  UDINT_TO_BCD_DWORD := UDINT_TO_BCD_DWORD + 16*256*256*256*VALUE;
+  IF VALUE > 9
+  THEN
+    (* The standard is silent on how to handle overflows!! *)
+    (* We simply set it to the highest value!              *)
+    UDINT_TO_BCD_DWORD := 16#9999_9999;
+  END_IF;
+END_FUNCTION
+
+
+
+
+FUNCTION ULINT_TO_BCD_LWORD: LWORD
+  VAR_INPUT
+    VALUE : UINT;
+  END_VAR
+
+  ULINT_TO_BCD_LWORD := UDINT_TO_BCD_DWORD(VALUE MOD 1_0000_0000);
+  VALUE := VALUE / 1_0000_0000;
+  ULINT_TO_BCD_LWORD := ULINT_TO_BCD_LWORD + 256*256*256*256*UDINT_TO_BCD_DWORD(VALUE);
+END_FUNCTION
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/ramp_st.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,25 @@
+ FUNCTION_BLOCK RAMP
+   VAR_INPUT
+     RUN : BOOL ;      (* 0 - track X0, 1 - ramp to/track X1 *)     
+     X0,X1 : REAL ;
+     TR : TIME ;       (* Ramp duration *)
+     CYCLE : TIME ;    (* Sampling period *)
+   END_VAR
+   VAR_OUTPUT
+     BUSY : BOOL ; (* BUSY = 1 during ramping period *)
+     XOUT : REAL := 0.0 ;
+   END_VAR
+   VAR XI : REAL ;       (* Initial value *)
+       T : TIME := T#0s; (* Elapsed time of ramp *)
+   END_VAR
+   BUSY := RUN ;
+   IF RUN THEN
+      IF T >= TR THEN BUSY := 0 ; XOUT := X1 ;
+      ELSE XOUT := XI + (X1-XI) * TIME_TO_REAL(T)
+                                / TIME_TO_REAL(TR) ;
+           T := T + CYCLE ;
+      END_IF ;
+   ELSE XOUT := X0 ; XI := X0 ; T := t#0s ;
+   END_IF ;
+ END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/time_math.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,360 @@
+(*
+ * (c) 2005 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * Math functions on Time and Date data types.
+ * -------------------------------------------
+ *
+ * We also include the two data type conversions defined in table 30 of the IEC 61131-3 standard (version
+ *)
+
+
+(* NOTE: The IEC 61131-3 standard library includes overloaded functions, which are not
+ * allowed in user code. Since our compiler does not yet support overloaded functions, these
+ * are commented out in the following library for the moment...
+ *)
+
+(***************)
+(* TIME + TIME *)
+(***************)
+
+FUNCTION ADD : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : TIME;
+  END_VAR
+
+  ADD := IN1 + IN2;
+END_FUNCTION
+
+
+FUNCTION ADD_TIME : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : TIME;
+  END_VAR
+
+  ADD_TIME := IN1 + IN2;
+END_FUNCTION
+
+
+FUNCTION SUB : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : TIME;
+  END_VAR
+
+  SUB := IN1 - IN2;
+END_FUNCTION
+
+
+FUNCTION SUB_TIME : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : TIME;
+  END_VAR
+
+  SUB_TIME := IN1 - IN2;
+END_FUNCTION
+
+
+
+(**************)
+(* TIME + TOD *)
+(**************)
+
+FUNCTION ADD : TOD
+  VAR_INPUT
+    IN1 : TOD;
+    IN2 : TIME;
+  END_VAR
+
+  ADD := IN1 + IN2;
+END_FUNCTION
+
+
+(* The following function is not defined in the standard, but its existance makes sense. *)
+FUNCTION ADD : TOD
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : TOD;
+  END_VAR
+
+  ADD := IN1 + IN2;
+END_FUNCTION
+
+
+FUNCTION ADD_TOD_TIME : TOD
+  VAR_INPUT
+    IN1 : TOD;
+    IN2 : TIME;
+  END_VAR
+
+  ADD_TOD_TIME := IN1 + IN2;
+END_FUNCTION
+
+
+FUNCTION SUB : TOD
+  VAR_INPUT
+    IN1 : TOD;
+    IN2 : TIME;
+  END_VAR
+
+  SUB := IN1 - IN2;
+END_FUNCTION
+
+
+FUNCTION SUB_TOD_TIME : TOD
+  VAR_INPUT
+    IN1 : TOD;
+    IN2 : TIME;
+  END_VAR
+
+  SUB_TOD_TIME := IN1 - IN2;
+END_FUNCTION
+
+
+
+(*************)
+(* TIME + DT *)
+(*************)
+
+FUNCTION ADD : DT
+  VAR_INPUT
+    IN1 : DT;
+    IN2 : TIME;
+  END_VAR
+
+  ADD := IN1 + IN2;
+END_FUNCTION
+
+
+(* The following function is not defined in the standard, but its existance makes sense. *)
+FUNCTION ADD : DT
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : DT;
+  END_VAR
+
+  ADD := IN1 + IN2;
+END_FUNCTION
+
+
+FUNCTION ADD_DT_TIME : DT
+  VAR_INPUT
+    IN1 : DT;
+    IN2 : TIME;
+  END_VAR
+
+  ADD_DT_TIME := IN1 + IN2;
+END_FUNCTION
+
+
+
+(***************)
+(* DATE + DATE *)
+(***************)
+
+FUNCTION SUB : TIME
+  VAR_INPUT
+    IN1 : DATE;
+    IN2 : DATE;
+  END_VAR
+
+  SUB := IN1 - IN2;
+END_FUNCTION
+
+
+FUNCTION SUB_DATE_DATE : TIME
+  VAR_INPUT
+    IN1 : DATE;
+    IN2 : DATE;
+  END_VAR
+
+  SUB_DATE_DATE := IN1 - IN2;
+END_FUNCTION
+
+
+
+(*************)
+(* TOD + TOD *)
+(*************)
+
+FUNCTION SUB : TIME
+  VAR_INPUT
+    IN1 : TOD;
+    IN2 : TOD;
+  END_VAR
+
+  SUB := IN1 - IN2;
+END_FUNCTION
+
+
+FUNCTION SUB_TOD_TOD : TIME
+  VAR_INPUT
+    IN1 : TOD;
+    IN2 : TOD;
+  END_VAR
+
+  SUB_TOD_TOD := IN1 - IN2;
+END_FUNCTION
+
+
+
+(*************)
+(* TIME + DT *)
+(*************)
+
+FUNCTION SUB : DT
+  VAR_INPUT
+    IN1 : DT;
+    IN2 : TIME;
+  END_VAR
+
+  SUB := IN1 - IN2;
+END_FUNCTION
+
+
+FUNCTION SUB_DT_TIME : DT
+  VAR_INPUT
+    IN1 : DT;
+    IN2 : TIME;
+  END_VAR
+
+  SUB_DT_TIME := IN1 - IN2;
+END_FUNCTION
+
+
+
+(***********)
+(* DT + DT *)
+(***********)
+
+FUNCTION SUB : TIME
+  VAR_INPUT
+    IN1 : DT;
+    IN2 : DT;
+  END_VAR
+
+  SUB := IN1 - IN2;
+END_FUNCTION
+
+
+FUNCTION SUB_DT_DT : TIME
+  VAR_INPUT
+    IN1 : DT;
+    IN2 : DT;
+  END_VAR
+
+  SUB_DT_DT := IN1 - IN2;
+END_FUNCTION
+
+
+
+(******************)
+(* TIME * ANY_NUM *)
+(******************)
+
+FUNCTION MUL : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : LREAL;
+  END_VAR
+
+  MUL := IN1 * IN2;
+END_FUNCTION
+
+
+FUNCTION MULTIME : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : LREAL;
+  END_VAR
+
+  MULTIME := IN1 * IN2;
+END_FUNCTION
+
+
+FUNCTION DIV : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : LREAL;
+  END_VAR
+
+  DIV := IN1 / IN2;
+END_FUNCTION
+
+
+FUNCTION DIVTIME : TIME
+  VAR_INPUT
+    IN1 : TIME;
+    IN2 : LREAL;
+  END_VAR
+
+  DIVTIME := IN1 / IN2;
+END_FUNCTION
+
+
+
+(*************)
+(* DATE + DT *)
+(*************)
+
+FUNCTION CONCAT_DATE_TOD : DT
+  VAR_INPUT
+    IN1 : DATE;
+    IN2 : TOD;
+  END_VAR
+
+  CONCAT_DATE_TOD := IN1 + IN2;
+END_FUNCTION
+
+
+
+(*************************)
+(* Data Type Conversions *)
+(*************************)
+
+FUNCTION DT_TO_DATE : DATE
+  VAR_INPUT
+    IN1 : DT;
+  END_VAR
+
+  {DT_TO_DATE = IN1.__to_DATE();}
+END_FUNCTION
+
+
+
+FUNCTION DT_TO_TOD : TOD
+  VAR_INPUT
+    IN1 : DT;
+  END_VAR
+
+  {DT_TO_TOD = IN1.__to_TOD();}
+END_FUNCTION
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/timer.txt	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,280 @@
+(*
+ * (c) 2005 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ *)
+
+(*
+ * This is part of the library conatining the functions
+ * and function blocks defined in the standard.
+ *
+ * Timer Function Blocks
+ * ---------------------
+ *
+ * NOTE: The timing diagrams in the comments were taken from the 
+ *       IEC 61131-3 standard.
+ *)
+
+
+
+(****************************************************************
+
+                  TP - pulse timing - state machine
+
+
+            +--------+     ++ ++   +--------+
+       IN   |        |     || ||   |        |
+          --+        +-----++-++---+        +---------
+            t0       t1    t2 t3    t4       t5
+            +----+         +----+  +----+
+       Q    |    |         |    |  |    |
+          --+    +---------+    +--+    +-------------
+            t0   t0+PT    t2 t2+PT t4  t4+PT
+         PT      +---+          +       +---+
+          :     /    |         /|      /    |
+       ET :    /     |        / |     /     |
+          :   /      |       /  |    /      |
+          :  /       |      /   |   /       |
+          0-+        +-----+    +--+        +---------
+            t0       t1    t2      t4       t5
+
+
+        2        +---+          +       +---+
+STATE   1   +----+   |     +----|  +----+   | 
+        0 --+        +-----+    +--+        +---------
+
+
+****************************************************************)
+
+FUNCTION_BLOCK TP
+  VAR_INPUT
+    IN : BOOL;  (* first input parameter *)
+    PT : TIME;  (* second input parameter *)
+  END_VAR
+  VAR_OUTPUT
+    Q : BOOL := FALSE;  (* first output parameter *)
+    ET : TIME := T#0s;  (* second output parameter *)
+  END_VAR
+
+  VAR
+    STATE : SINT := 0;  (* internal state: 0-reset, 1-counting, 2-set *)
+    PREV_IN : BOOL := FALSE;
+    CURRENT_TIME, START_TIME : TIME;
+  END_VAR
+
+  {data__->CURRENT_TIME = __CURRENT_TIME;}
+
+  IF ((STATE = 0) AND NOT(PREV_IN) AND IN)   (* found rising edge on IN *)
+  THEN
+    (* start timer... *)
+    STATE := 1;
+    Q := TRUE;
+    START_TIME := CURRENT_TIME;
+
+  ELSIF (STATE = 1)
+  THEN
+    IF ((START_TIME + PT) <= CURRENT_TIME)
+    THEN
+      STATE := 2;
+      Q := FALSE;
+      ET := PT;
+    ELSE
+      ET := CURRENT_TIME - START_TIME;
+    END_IF;
+  END_IF;
+
+  IF ((STATE = 2) AND NOT(IN))
+  THEN
+    ET := T#0s;
+    STATE := 0;
+  END_IF;
+
+
+  PREV_IN := IN;
+
+END_FUNCTION_BLOCK
+
+
+
+
+(****************************************************************
+
+             TON - On-delay timing - state machine
+
+
+            +--------+        +---+   +--------+
+       IN   |        |        |   |   |        |
+          --+        +--------+   +---+        +-------------
+            t0       t1       t2  t3  t4       t5
+                 +---+                     +---+
+       Q         |   |                     |   |
+          -------+   +---------------------+   +-------------
+              t0+PT  t1                t4+PT   t5
+         PT      +---+                     +---+
+          :     /    |            +       /    |
+       ET :    /     |           /|      /     |
+          :   /      |          / |     /      |
+          :  /       |         /  |    /       |
+          0-+        +--------+   +---+        +-------------
+            t0       t1       t2  t3  t4       t5
+
+
+        2        +---+                     +---+
+STATE   1   +----+   |        +---+   +----+   |
+        0 --+        +--------+   +---+        +------
+
+
+****************************************************************)
+
+
+FUNCTION_BLOCK TON
+  VAR_INPUT
+    IN : BOOL;  (* first input parameter *)
+    PT : TIME;  (* second input parameter *)
+  END_VAR
+  VAR_OUTPUT
+    Q : BOOL := FALSE;  (* first output parameter *)
+    ET : TIME := T#0s;  (* second output parameter *)
+  END_VAR
+
+  VAR
+    STATE : SINT := 0;  (* internal state: 0-reset, 1-counting, 2-set *)
+    PREV_IN : BOOL := FALSE;
+    CURRENT_TIME, START_TIME : TIME;
+  END_VAR
+
+  {data__->CURRENT_TIME = __CURRENT_TIME;}
+
+  IF ((STATE = 0) AND NOT(PREV_IN) AND IN)   (* found rising edge on IN *)
+  THEN
+    (* start timer... *)
+    STATE := 1;
+    Q := FALSE;
+    START_TIME := CURRENT_TIME;
+
+  ELSE
+    (* STATE is 1 or 2 !! *)
+    IF (NOT(IN))
+    THEN
+      ET := T#0s;
+      Q := FALSE;
+      STATE := 0;
+
+    ELSIF (STATE = 1)
+    THEN
+      IF ((START_TIME + PT) <= CURRENT_TIME)
+      THEN
+        STATE := 2;
+        Q := TRUE;
+        ET := PT;
+      ELSE
+        ET := CURRENT_TIME - START_TIME;
+      END_IF;
+    END_IF;
+
+  END_IF;
+
+  PREV_IN := IN;
+
+END_FUNCTION_BLOCK
+
+
+
+
+
+(****************************************************************
+
+             TOFF - Off-delay timing - state machine
+
+
+              +--------+        +---+   +--------+
+       IN     |        |        |   |   |        |
+           ---+        +--------+   +---+        +-----------
+              t0       t1       t2  t3  t4       t5
+              +-------------+   +---------------------+
+       Q      |             |   |                     |
+           ---+             +---+                     +------
+              t0          t1+PT t2                  t5+PT
+         PT                 +---+                     +------
+          :                /    |       +            /
+       ET :               /     |      /|           /
+          :              /      |     / |          /
+          :             /       |    /  |         /
+          0------------+        +---+   +--------+
+                       t1           t3           t5
+
+
+        2                   +---+                     +------
+STATE   1              +----+   |   +---+        +----+
+        0 -------------+        +---+   +--------+
+
+
+****************************************************************)
+
+FUNCTION_BLOCK TOFF
+  VAR_INPUT
+    IN : BOOL;  (* first input parameter *)
+    PT : TIME;  (* second input parameter *)
+  END_VAR
+  VAR_OUTPUT
+    Q : BOOL := FALSE;  (* first output parameter *)
+    ET : TIME := T#0s;  (* second output parameter *)
+  END_VAR
+
+  VAR
+    STATE : SINT := 0;  (* internal state: 0-reset, 1-counting, 2-set *)
+    PREV_IN : BOOL := FALSE;
+    CURRENT_TIME, START_TIME : TIME;
+  END_VAR
+
+  {data__->CURRENT_TIME = __CURRENT_TIME;}
+
+  IF ((STATE = 0) AND PREV_IN AND NOT(IN))   (* found falling edge on IN *)
+  THEN
+    (* start timer... *)
+    STATE := 1;
+    START_TIME := CURRENT_TIME;
+
+  ELSE
+    (* STATE is 1 or 2 !! *)
+    IF (IN)
+    THEN
+      ET := T#0s;
+      STATE := 0;
+
+    ELSIF (STATE = 1)
+    THEN
+      IF ((START_TIME + PT) <= CURRENT_TIME)
+      THEN
+        STATE := 2;
+        ET := PT;
+      ELSE
+        ET := CURRENT_TIME - START_TIME;
+      END_IF;
+    END_IF;
+
+  END_IF;
+
+  Q := IN OR (STATE = 1);
+  PREV_IN := IN;
+
+END_FUNCTION_BLOCK
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cc	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,133 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/*
+ ****************************************************************
+ ****************************************************************
+ ****************************************************************
+ *********                                              *********
+ *********                                              *********
+ *********   O V E R A L L    A R C H I T E C T U R E   *********
+ *********                                              *********
+ *********                                              *********
+ ****************************************************************
+ ****************************************************************
+ ****************************************************************
+
+ The compiler works in 4(+1) stages:
+ Stage 1   - Lexical analyser      - implemented with flex (iec.flex)
+ Stage 2   - Syntax parser         - implemented with bison (iec.y)
+ Stage 3   - Semantics analyser    - not yet implemented
+ Stage 4   - Code generator        - implemented in C++
+ Stage 4+1 - Binary code generator - gcc, javac, etc...
+
+
+ Data structures passed between stages, in global variables:
+ 1->2   : tokens (int), and token values (char *)
+ 2->1   : symbol tables (defined in symtable.hh)
+ 2->3   : abstract syntax tree (tree of C++ classes, in absyntax.hh file)
+ 3->4   : Same as 2->3
+ 4->4+1 : file with program in c, java, etc...
+
+
+ The compiler works in several passes:
+ Pass 1: executes stages 1 and 2 simultaneously
+ Pass 2: executes stage 3
+ Pass 3: executes stage 4
+ Pass 4: executes stage 4+1
+*/
+
+
+
+//#include <stdio.h>   // printf()
+
+#include <stdlib.h>  // EXIT_FAILURE
+#include "absyntax/absyntax.hh"  // symbol_c type
+
+
+
+
+/* A macro for printing out internal parser errors... */
+#include <iostream> // required for std::cerr
+#define ERROR error_exit(__FILE__,__LINE__)
+void error_exit(const char *file_name, int line_no) {
+  std::cerr << "\nInternal program error in file " << file_name
+            << " at line " << line_no << "\n\n\n";
+  exit(EXIT_FAILURE);
+}
+
+
+
+/* forward declarations... */
+int stage1_2(const char *filename, const char *includedir, symbol_c **tree_root);
+//int stage3(symbol_c *tree_root);
+int stage4(symbol_c *tree_root);
+
+
+static void printusage(const char *cmd) {
+  printf("%s [<input_file>] [-I <include_directory>]\n", cmd);
+}
+
+
+
+int main(int argc, char **argv) {
+  symbol_c *tree_root;
+  char * includedir = NULL;
+
+  if (argc == 4) {
+    if (strcmp(argv[2], "-I") != 0) {
+      printusage(argv[0]);
+      return EXIT_FAILURE;
+    }
+    includedir = argv[3];
+    argc = 2;
+  }
+
+  if (argc != 2) {
+    printusage(argv[0]);
+    return EXIT_FAILURE;
+  }
+
+  /* 1st Pass */
+  if (stage1_2(argv[1], includedir, &tree_root) < 0)
+    return EXIT_FAILURE;
+
+  /* 2nd Pass */
+  /* not yet implemented... */
+  /*
+  if (stage3(tree_root) < 0)
+    return EXIT_FAILURE;
+  */
+
+  /* 3rd Pass */
+  if (stage4(tree_root) < 0)
+    return EXIT_FAILURE;
+
+  /* 4th Pass */
+  /* Currently implemented in the Makefile! */
+
+  return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,407 @@
+
+
+
+  IEC 61131-3 IL and ST compiler
+
+
+  The following compiler has been based on the
+  FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+
+
+  (c) 2003 Mario de Sousa
+
+
+
+****************************************************************
+****************************************************************
+****************************************************************
+*********                                              *********
+*********                                              *********
+*********   O V E R A L L    A R C H I T E C T U R E   *********
+*********                                              *********
+*********                                              *********
+****************************************************************
+****************************************************************
+****************************************************************
+
+ The compiler works in 4(+1) stages:
+ Stage 1   - Lexical analyser      - implemented with flex (iec.flex)
+ Stage 2   - Syntax parser         - implemented with bison (iec.y)
+ Stage 3   - Semantics analyser    - not yet implemented
+ Stage 4   - Code generator        - implemented in C++
+ Stage 4+1 - Binary code generator - gcc, javac, etc...
+
+
+ Data structures passed between stages, in global variables:
+ 1->2   : tokens (int), and token values (char *)
+ 2->1   : symbol tables (defined in symtable.hh)
+ 2->3   : abstract syntax tree (tree of C++ classes, in absyntax.hh file)
+ 3->4   : Same as 2->3
+ 4->4+1 : file with program in c, java, etc...
+
+
+ The compiler works in several passes:
+ Pass 1: executes stages 1 and 2 simultaneously
+ Pass 2: executes stage 3
+ Pass 3: executes stage 4
+ Pass 4: executes stage 4+1
+
+
+ NOTE 1
+ ======
+ Note that stage 2 passes data back to stage 1. This is only
+possible because both stages are executed in the same pass.
+
+
+
+ NOTE 2
+ ======
+  I (Mario) have a feeling that the abstract syntax may be
+considerably simplified without any drawbacks to semantic checking
+and code generation. I have nevertheless opted to keep as much 
+info as possible in the abstract syntax tree, in case it may become
+necessary further on.
+ Once we start coding the next stages (semantic checking and code
+generation) I will get a better understanding of what is required
+of the abstract syntax tree. At that stage I will be better
+positioned to make a more informed decision on how best to structure
+the abstract syntax tree.
+ For now, we play conservative and keep as much info as possible.
+
+ 
+
+ NOTE 3
+ ======
+ It would be nice to get this parser integrated into the gcc
+group of compilers. We would then be able to compile our st/il
+programs directly into executable binaries, for all the processor
+architectures gcc currently supports.
+ The gcc compilers are divided into a frontend and backend. The
+data structure between these two stages is called the syntax
+tree. In essence, we would need to create a new frontend that
+would parse the st/il program and build the syntax tree.
+Unfortunately the gcc syntax tree is not very well documented,
+and doing semantic checking on this tree would probably be a
+nightmare.
+ We therefore chose to follow the same route as the gnat (ada 95)
+and cobol compilers, i.e. generate our own abstract syntax tree,
+do semantic checking on our tree, do whatever optimisation
+we can at this level on our own tree, and only then build
+the gcc syntax tree from our abstract syntax tree.
+ All this may still be integrated with the gcc backend to generate
+a new gnu compiler for the st and il programming languages.
+Since generating the gcc syntax tree will probably envolve some
+trial and error effort due to the sparseness of documentation,
+we chose to start off by coding a C++ code generator for
+our stage 4. We may later implement a gcc syntax tree generator
+as an alternative stage 4 process, and then integrate it with
+the gcc toplevel.c file (command line parsing, etc...).
+
+
+
+****************************************************************
+****************************************************************
+****************************************************************
+*********                                              *********
+*********                                              *********
+*********               S T A G E      1               *********
+*********                                              *********
+*********                                              *********
+****************************************************************
+****************************************************************
+****************************************************************
+
+
+
+Issue 1
+=======
+
+ The syntax defines the common_character_representation as:
+<any printable character except '$', '"' or "'"> | <escape sequences>
+
+ Flex includes the function print_char() that defines
+all printable characters portably (i.e. whatever character
+encoding is currently being used , ASCII, EBCDIC, etc...)
+Unfortunately, we cannot generate the definition of
+common_character_representation portably, since flex
+does not allow definition of sets by subtracting
+elements in one set from another set (Note how
+common_character_representation could be defined by
+subtracting '$' '"' and "'" from print_char() ).
+This means we must build up the defintion of
+common_character_representation using only set addition,
+which leaves us with the only choice of defining the
+characters non-portably...
+
+ In short, the definition we use for common_character_representation
+only works for ASCII character encoding!
+
+
+
+
+Issue 2
+=======
+
+We extend the IEC 61131-3 standard syntax to allow inclusion of 
+other files. The accepted syntax is:
+
+   (*#include "<filename>" *)
+
+Note how this would be ignored by other standard complient compilers 
+as a simple comment!
+
+
+
+****************************************************************
+****************************************************************
+****************************************************************
+*********                                              *********
+*********                                              *********
+*********               S T A G E      2               *********
+*********                                              *********
+*********                                              *********
+****************************************************************
+****************************************************************
+****************************************************************
+
+ Overall Comments
+ ================
+
+ 
+ Comment 1
+ ---------
+ We have augmented the syntax the specification defines to include
+restrictions defined in the semantics of the languages.
+
+ This is required because the syntax cannot be parsed by a LALR(1)
+parser as it is presented in the specification. Many reduce/reduce
+and shift/reduce conflicts arise. This is mainly because the parser
+cannot discern how to reduce an identifier. Identifiers show up in
+many places in the syntax, and it is not entirely possible to
+figure out if the identifier is a variable_name, enumeration
+value, function block name, etc... only from the context in
+which it appears.
+
+ A more detailed example of why we need symbol tables are
+the type definitions...  In definition of new types
+(section B 1.3.3) the parser needs to figure out the class of
+the new type being defined (enumerated, structure, array, etc...).
+This works well when the base classes are elementary types
+(or structures, enumeration, arrays, etc. thereof). It becomes
+confusing to the parser when the new_type is based on a previously
+user defined type.
+
+TYPE
+  new_type_1 : INT := 99;
+  new_type_2 : new_type_1 := 100;
+END_TYPE
+
+ When parsing new_type_1, the parser can figure out that the
+identifier new_type_1 is a simple_type_name, because it is
+based on a elementary type without structure, arrays, etc...
+ While parsing new_type_2, it becomes confused how to reduce
+the new_type_2 identifier, as it is based on the identifier
+new_type_1, of which it does not know the class (remember, at this
+stage new_type_1 is a simple identifier!).
+ We therefore need to keep track of the class of the user
+defined types as they are declared, so that the lexical analyser
+can tell the syntax parser what class the type belongs to. We
+cannot use the abstract syntax tree itself to search for the
+declaration of new_type_1 as we only get a handle to the root
+of the tree at the end of the parsing.
+
+ We therefore maintain an independent and parallel table of symbols,
+that is filled as we come across the type delcarations in the code.
+Actually, we ended up also needing to store variable names in
+the symbol table. Since variable names come and go out of scope
+depending on what portion of code we are parsing, we sometimes
+need to remove the variable names from the symbol table.
+Since the ST and IL languages only have a single level of scope,
+I (Mario) found it easier to simply use a second symbol table for
+the variable names that is completely cleared when the parser
+reaches the end of a function (function block or program).
+
+What I mean when I say that these languages have a single level
+of scope is that all variables used in a function (function block
+or program) must be declared inside that function (function block
+or program). Even global variables must be re-declared as EXTERN
+before a function may access them! This means that it is easy
+to simply load up the variable name symbol table when we start
+parsing a function (function block or program), and to clear it
+when we reach the end. Checking whether variables declared
+as EXTERN really exist inside a RESOURCE or a CONFIGURATION
+is left to stage 3 (semantic checking) where we can use the
+abstract tree itself to search for the variables (NOTE: semantic
+cheching at stage 3 has not yet been implemented, so we may yet
+end up using a symbol table too at that stage!).
+
+ Due to the use of the symbol tables, and special identifier
+tokens depending on the type of identifier it had previously
+been declared in the code being parsed, the syntax was slightly
+changed regarding the definition of variable names, derived
+function names, etc... FROM for e.g.:
+variable_name: identifier;
+TO
+variable_name: variable_name_token;
+
+ Flex first looks at the symbol tables when it finds an identifier,
+and returns the correct token corresponding to the identifier
+type in question. Only if the identifier is not currently stored
+in any symbol table, does flex return a simple identifier_token.
+
+ This means that the declarations of variables, functions etc...
+were changed FROM:
+function_declaration: FUNCTION derived_function_name ...
+TO
+function_declaration: FUNCTION identifier ...
+since the initial definition of derived_function_name had been
+changed FROM
+derived_function_name: identifier;
+TO
+derived_function_name: derived_function_name_token;
+
+
+
+
+ Comment 2
+ ---------
+ Since the ST and IL languages share a lot of common syntax,
+I have decided to write a single parser to handle both languages
+simultaneously. This approach has the advantage that the user
+may mix the language used in the same file, as long as each function
+is written in a single lanuage.
+
+ This approach also assumes that all the IL language operators are
+keywords, which means that it is not possible to define variables
+using names such as "LD", "ST", etc...
+Note that the spec does not consider these operators to be keywords,
+so it means that they should be available for variable names! On the
+other hand, all implementations of the ST and IL languages seems to
+treat them as keywords, so there is not much harm in doing the same.
+
+ If it ever becomes necessary to allow variables with names of IL 
+operators, either the syntax will have to be augmented, or we can 
+brake up the parser in two: one for ST and another for IL.
+
+
+
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+
+Issue 1
+=======
+
+According to the spec, the valid construct
+TYPE new_str_type : STRING := "hello!"; END_TYPE
+has two possible routes to type_declaration...
+
+Route 1:
+type_declaration: single_element_type_declaration
+single_element_type_declaration: simple_type_declaration
+simple_type_declaration: identifier ':' simple_spec_init
+simple_spec_init: simple_specification ASSIGN constant
+(shift:  identifier <- 'new_str_type')
+simple_specification: elementary_type_name
+elementary_type_name: STRING
+(shift: elementary_type_name <- STRING)
+(reduce: simple_specification <- elementary_type_name)
+(shift: constant <- "hello!")
+(reduce: simple_spec_init: simple_specification ASSIGN constant)
+(reduce: ...)
+
+
+Route 2:
+type_declaration: string_type_declaration
+string_type_declaration: identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init
+(shift:  identifier <- 'new_str_type')
+elementary_string_type_name: STRING
+(shift: elementary_string_type_name <- STRING)
+(shift: string_type_declaration_size <- /* empty */)
+string_type_declaration_init: ASSIGN character_string
+(shift: character_string <- "hello!")
+(reduce: string_type_declaration_init <- ASSIGN character_string)
+(reduce: string_type_declaration <- identifier ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init )
+(reduce: type_declaration <- string_type_declaration)
+
+
+ At first glance it seems that removing route 1 would make
+the most sense. Unfortunately the construct 'simple_spec_init'
+shows up multiple times in other rules, so changing this construct
+would mean changing all the rules in which it appears.
+I (Mario) therefore chose to remove route 2 instead. This means
+that the above declaration gets stored in a
+simple_type_declaration_c, and not in a string_type_declaration_c
+as would be expected!
+
+
+/***********************/
+/* B 1.5.1 - Functions */
+/***********************/
+
+
+Issue 1
+=======
+
+ 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
+variable_name_token.
+
+ BUT, in functions the function name may be used as
+a variable! In order to be able to parse this correctly,
+the token parser (flex) must return a 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 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 the extra
+construct 'function_name_declaration', i.e. to force
+the parser to reduce it, before parsing the function body,
+and therefore get an oportunity to insert the function name
+into the variable name symbol table!
+
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+
+Issue 1
+=======
+
+For the 'FOR' iteration loop
+
+  FOR control_variable ASSIGN expression TO expression BY expression DO statement_list END_FOR
+
+The spec declares the control variable in the syntax as
+
+  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 .. VAR_END' construct, so I (Mario) changed
+the syntax to read
+
+  control_variable: variable_name;
+
+
+
+
+
+**************************************************************************
+
+  (c) 2003 Mario de Sousa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage1_2/Makefile	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,49 @@
+# include the system specific Makefile
+#include ../../../Makefile.$(shell uname)
+
+
+
+default:	all
+
+.PHONY: iec.flex
+
+all: iec.flex.o iec.y.o
+
+clean:
+	-rm -f *.o Makefile.depend
+	-rm -f iec.flex.c iec.y.cc iec.y.hh iec.y.output
+	-rm -f test_flex
+
+#get warnings, debugging information and optimization
+CFLAGS  = -Wall -pedantic -Wpointer-arith -Wwrite-strings
+# CFLAGS += -Werror
+
+CFLAGS += -ggdb -O3 -funroll-loops
+# Note: if the optimizer crashes, we'll leave out the -O3 for those files
+
+CFLAGS += -I. -I../* -I../../absyntax
+
+test_flex: iec.flex.c iec.y.hh
+	$(CXX) -o test_flex.o -c iec.flex.c -DTEST_MAIN $(CFLAGS)
+	$(CXX) -o test_flex test_flex.o
+#	$(CXX) -o test_flex test_flex.o ../util/symtable.o -DTEST_MAIN
+
+iec.flex.c: iec.flex
+	flex -oiec.flex.c iec.flex
+
+iec.flex.o: iec.y.hh iec.flex.c
+	$(CXX) -c iec.flex.c -D LIBDIRECTORY='"$(IECLIBDIR)"' $(CFLAGS)
+
+iec.y.hh iec.y.cc: iec.y
+	bison -d -v -o iec.y.cc iec.y
+
+iec.y.o: iec.y.cc iec.y.hh
+	$(CXX) -c iec.y.cc -D LIBDIRECTORY='"$(IECLIBDIR)"' $(CFLAGS)
+
+
+
+
+
+#how to make things from other directories if they are missing
+../% /%:
+	$(MAKE) -C $(@D) $(@F)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage1_2/iec.flex	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,1384 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/*
+ * Stage 1
+ * =======
+ *
+ * This file contains the lexical tokens definitions, from which
+ * the flex utility will generate a lexical parser function.
+ */
+
+
+
+
+/*****************************/
+/* Lexical Parser Options... */
+/*****************************/
+
+/* The lexical analyser will never work in interactive mode,
+ * i.e., it will only process programs saved to files, and never
+ * programs being written inter-actively by the user.
+ * This option saves the resulting parser from calling the
+ * isatty() function, that seems to be generating some compile
+ * errors under some (older?) versions of flex.
+ */
+%option never-interactive
+
+/* Have the lexical analyser use a 'char *yytext' instead of an
+ * array of char 'char yytext[??]' to store the lexical token.
+ */
+%pointer
+
+
+/* Have the lexical analyser ignore the case of letters.
+ * This will occur for all the tokens and keywords, but
+ * the resulting text handed up to the syntax parser
+ * will not be changed, and keep the original case
+ * of the letters in the input file.
+ */
+%option case-insensitive
+
+/* Have the generated lexical analyser keep track of the
+ * line number it is currently analysing.
+ * This is used to pass up to the syntax parser
+ * the number of the line on which the current
+ * token was found. It will enable the syntax parser
+ * to generate more informatve error messages...
+ */
+%option yylineno
+
+/* required for the use of the yy_pop_state() and
+ * yy_push_state() functions
+ */
+%option stack
+
+/* The '%option stack' also requests the inclusion of 
+ * the yy_top_state(), however this function is not
+ * currently being used. This means that the compiler
+ * is complaining about the existance of this function.
+ * The following option removes the yy_top_state()
+ * function from the resulting c code, so the compiler 
+ * no longer complains.
+ */
+%option noyy_top_state
+
+/**************************************************/
+/* External Variable and Function declarations... */
+/**************************************************/
+
+
+%{
+/* Define TEST_MAIN to include a main() function.
+ * Useful for testing the parser generated by flex.
+ */
+/*
+#define TEST_MAIN
+*/
+/* If lexical parser is compiled by itself, we need to define the following
+ * constant to some string. Under normal circumstances LIBDIRECTORY is set
+ * in the syntax parser header file...
+ */
+#ifdef TEST_MAIN
+#define LIBDIRECTORY "just_testing"
+#endif
+
+
+
+/* Required for strdup() */
+#include <string.h>
+
+/* Required only for the declaration of abstract syntax classes
+ * (class symbol_c; class token_c; class list_c;)
+ * These will not be used in flex, but the token type union defined
+ * in iec.hh contains pointers to these classes, so we must include
+ * it here.
+ */
+#include "../absyntax/absyntax.hh"
+
+/* generated by bison.
+ * Contains the definition of the token constants, and the
+ * token value type YYSTYPE (in our case, a 'const char *')
+ */
+#include "iec.y.hh"
+
+/* Variable defined by the bison parser,
+ * where the value of the tokens will be stored
+ */
+extern YYSTYPE yylval;
+
+/* The name of the file currently being parsed...
+ * This variable is declared and read from the code generated by bison!
+ * Note that flex accesses and updates this global variable
+ * apropriately whenever it comes across an (*#include <filename> *)
+ * directive...
+ */
+extern const char *current_filename;
+
+/* We will not be using unput() in our flex code... */
+#define YY_NO_UNPUT
+
+/* Variable defined by the bison parser.
+ * It must be initialised with the location
+ * of the token being parsed.
+ * This is only needed if we want to keep
+ * track of the locations, in order to give
+ * more meaningful error messages!
+ */
+extern YYLTYPE yylloc;
+
+/* Macro that is executed for every action.
+ * We use it to pass the location of the token
+ * back to the bison parser...
+ */
+#define YY_USER_ACTION { 					\
+	yylloc.first_line = yylloc.last_line = yylineno;	\
+	yylloc.first_column = yylloc.last_column = 0;		\
+	}
+
+
+/* Since this lexical parser we defined only works in ASCII based
+ * systems, we might as well make sure it is being compiled on
+ * one...
+ * Lets check a few random characters...
+ */
+#if (('a' != 0x61) || ('A' != 0x41) || ('z' != 0x7A) || ('Z' != 0x5A) || \
+     ('0' != 0x30) || ('9' != 0x39) || ('(' != 0x28) || ('[' != 0x5B))
+#error This lexical analyser is not portable to a non ASCII based system.
+#endif
+
+
+/* Function only called from within flex, but defined
+ * in iec.y!
+ * We delcare it here...
+ *
+ * Search for a symbol in either of the two symbol tables
+ * and return the token id of the first symbol found.
+ * Searches first in the variables, and only if not found
+ * does it continue searching in the library elements
+ */
+//token_id_t get_identifier_token(const char *identifier_str);
+int get_identifier_token(const char *identifier_str);
+%}
+
+
+/***************************************************/
+/* Forward Declaration of functions defined later. */
+/***************************************************/
+
+%{
+/* return all the text in the current token back to the input stream. */
+void unput_text(unsigned int n);
+%}
+
+
+
+/****************************/
+/* Lexical Parser States... */
+/****************************/
+
+/* NOTE: Our psrser can parse st or il code, intermixed
+ *       within the same file.
+ *       With IL we come across the issue of the EOL (end of line) token.
+ *       ST, and the declaration parts of IL do not use this token!
+ *       If the lexical analyser were to issue this token during ST
+ *       language parsing, or during the declaration of data types,
+ *       function headers, etc. in IL, the syntax parser would crash.
+ *
+ *       We can solve this issue using one of three methods:
+ *        (1) Augment all the syntax that does not accept the EOL
+ *            token to simply ignore it. This makes the syntax
+ *            definition (in iec.y) very cluttered!
+ *        (2) Let the lexical parser figure out which language
+ *            it is parsing, and decide whether or not to issue
+ *            the EOL token. This requires the lexical parser
+ *            to have knowledge of the syntax!, making for a poor
+ *            overall organisation of the code. It would also make it
+ *            very difficult to understand the lexical parser as it
+ *            would use several states, and a state machine to transition
+ *            between the states. The state transitions would be
+ *            intermingled with the lexical parser defintion!
+ *        (3) Use a mixture of (1) and (2). The lexical analyser
+ *            merely distinguishes between function headers and function
+ *            bodies, but no longer makes a distinction between il and
+ *            st language bodies. When parsing a body, it will return
+ *            the EOL token. In other states '\n' will be ignored as
+ *            whitespace.
+ *            The ST language syntax has been augmented in the syntax
+ *            parser configuration to ignore any EOL tokens that it may
+ *            come across!
+ *            This option has both drawbacks of option (1) and (2), but
+ *            much less intensely.
+ *            The syntax that gets cluttered is limited to the ST statements
+ *            (which is rather limited, compared to the function headers and
+ *            data type declarations, etc...), while the state machine in
+ *            the lexical parser becomes very simple. All state transitions
+ *            can be handled within the lexical parser by itself, and can be
+ *            easily identified. Thus knowledge of the syntax required by
+ *            the lexical parser is very limited!
+ *
+ * Amazingly enough, I (Mario) got to implement option (3)
+ * at first, requiring two basic states, decl and body.
+ * The lexical parser will enter the body state when
+ * it is parsing the body of a function/program/function block. The
+ * state transition is done when we find a VAR_END that is not followed
+ * by a VAR! This is the syntax knowledge that gets included in the
+ * lexical analyser with this option!
+ * Unfortunately, getting the st syntax parser to ignore EOL anywhere
+ * where they might appear leads to conflicts. This is due to the fact
+ * that the syntax parser uses the single look-ahead token to remove
+ * possible conflicts. When we insert a possible EOL, the single
+ * look ahead token becomes the EOL, which means the potential conflicts
+ * could no longer be resolved.
+ * Removing these conflicts would make the st syntax parser very convoluted,
+ * and adding the extraneous EOL would make it very cluttered.
+ * This option was therefore dropped in favour of another!
+ *
+ * I ended up implementing (2). Unfortunately the lexical analyser can
+ * not easily distinguish between il and st code, since function
+ * calls in il are very similar to function block calls in st.
+ * We therefore use an extra 'body' state. When the lexical parser
+ * finds that last END_VAR, it enters the body state. This state
+ * must figure out what language is being parsed from the first few
+ * tokens, and switch to the correct state (st or il) according to the
+ * language. This means that we insert quite a bit of knowledge of the
+ * syntax of the languages into the lexical parser. This is ugly, but it
+ * works, and at least it is possible to keep all the state changes together
+ * to make it easier to remove them later on if need be.
+ * The body state returns any matched text back to the buffer with unput(),
+ * to be later matched correctly by the apropriate language parser (st or il).
+ * The state machine has 6 possible states (INITIAL, config, decl, body, st, il)
+ * Possible state changes are:
+ *   INITIAL -> decl (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
+ *                    and followed by a VAR declaration)
+ *   INITIAL -> body (when a FUNCTION, FUNCTION_BLOCK, or PROGRAM is found,
+ *                    and _not_ followed by a VAR declaration)
+ *   INITIAL -> config (when a CONFIGURATION is found)
+ *   decl    -> body (when the last END_VAR is found, i.e. the function body starts)
+ *   body    -> st (when it figures out it is parsing st language)
+ *   body    -> il (when it figures out it is parsing il language)
+ *   decl    -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
+ *   st      -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
+ *   il      -> INITIAL (when a END_FUNCTION, END_FUNCTION_BLOCK, or END_PROGRAM is found)
+ *   config  -> INITIAL (when a END_CONFIGURATION is found)
+ */
+/* we are parsing a configuration. */
+%s config
+
+/* we are parsing a function, program or function block declaration */
+%s decl
+
+/* we will be parsing a function body. Whether il/st is remains unknown */
+%x body
+
+/* we are parsing il code -> flex must return the EOL tokens!       */
+%s il
+
+/* we are parsing st code -> flex must not return the EOL tokens!   */
+%s st
+
+
+
+
+/*******************/
+/* File #include's */
+/*******************/
+
+/* We extend the IEC 61131-3 standard syntax to allow inclusion
+ * of other files, using the IEC 61131-3 pragma directive...
+ * The accepted syntax is:
+ *  {#include "<filename>"}
+ */
+
+/* the "include" states are used for picking up the name of an include file */
+%x include_beg
+%x include_filename
+%x include_end
+
+
+file_include_pragma_filename	[^\"]*
+file_include_pragma_beg		"{#include"{st_whitespace_only}\"
+file_include_pragma_end		\"{st_whitespace_only}"}"
+file_include_pragma			{file_include_pragma_beg}{file_include_pragma_filename}{file_include_pragma_end}
+
+
+%{
+#define MAX_INCLUDE_DEPTH 16
+
+typedef struct {
+	  YY_BUFFER_STATE buffer_state;
+	  int lineno;
+	  const char *filename;
+	} include_stack_t;
+
+include_stack_t include_stack[MAX_INCLUDE_DEPTH];
+int include_stack_ptr = 0;
+
+const char *INCLUDE_DIRECTORIES[] = {
+	"",
+	"lib/",
+	"/lib/",
+	"/usr/lib/",
+	"/usr/lib/iec/",
+	LIBDIRECTORY "/",
+	NULL /* must end with NULL!! */
+	};
+
+
+/*
+ * Join two strings together. Allocate space with malloc(3).
+ */
+static char *strdup2(const char *a, const char *b) {
+  char *res = (char *)malloc(strlen(a) + strlen(b) + 1);
+
+  if (!res)
+    return NULL;
+  return strcat(strcpy(res, a), b);  /* safe, actually */
+}
+%}
+
+
+
+/*****************************/
+/* Prelimenary constructs... */
+/*****************************/
+
+
+/* A pragma... */
+
+pragma "{"[^}]*"}"
+
+/* NOTE: this seemingly unnecessary complex definition is required
+ *       to be able to eat up comments such as:
+ *          '(* Testing... ! ***** ******)'
+ *       without using the trailing context command in flex (/{context})
+ *       since {comment} itself will later be used with
+ *       trailing context ({comment}/{context})
+ */
+not_asterisk				[^*]
+not_close_parenthesis_nor_asterisk	[^*)]
+asterisk				"*"
+comment_text		{not_asterisk}|(({asterisk}+){not_close_parenthesis_nor_asterisk})
+
+comment		"(*"({comment_text}*)({asterisk}+)")"
+
+
+/*
+3.1 Whitespace
+ (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!)
+ No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.).
+ The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace.
+ On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple3.1 Whitespace
+ (NOTE: Whitespace IS clearly defined, to include newline!!! See section 2.1.4!!!)
+ No definition of whitespace is given, in other words, the characters that may be used to seperate language tokens are not pecisely defined. One may nevertheless make an inteligent guess of using the space (' '), and other characters also commonly considered whitespace in other programming languages (horizontal tab, vertical tab, form feed, etc.).
+ The main question is whether the newline character should be considered whitespace. IL language statements use an EOL token (End Of Line) to distinguish between some language constructs. The EOL token itself is openly defined as "normally consist[ing] of the 'paragraph separator' ", leaving the final choice open to each implemention. If we choose the newline character to represent the EOL token, it may then not be considered whitespace.
+ On the other hand, some examples that come in a non-normative annex of the specification allow function declarations to span multiple lines, which means that the newline character is being considered as whitespace.
+ Our implementation works around this issue by including the new line character in the whitespace while parsing function declarations and the ST language, and parsing it as the EOL token only while parsing IL language statements. This requires the use of a state machine in the lexical parser that needs at least some knowledge of the syntax itself.
+*/
+/* NOTE: Our definition of whitespace will only work in ASCII!
+ *
+ *       Since the IL language needs to know the location of newline
+ *       (token EOL -> '\n' ), we need one definition of whitespace
+ *       for each language...
+ */
+/*
+ * NOTE: we cannot use
+ *         st_whitespace	[:space:]*
+ *       since we use {st_whitespace} as trailing context. In our case
+ *       this would not constitute "dangerous trailing context", but the
+ *       lexical generator (i.e. flex) does not know this (since it does
+ *       not know which characters belong to the set [:space:]), and will
+ *       generate a "dangerous trailing context" warning!
+ *       We use this alternative just to stop the flex utility from
+ *       generating the invalid (in this case) warning...
+ */
+
+st_whitespace_only	[ \f\n\r\t\v]*
+il_whitespace_only	[ \f\r\t\v]*
+
+st_whitespace_text	{st_whitespace_only}|{comment}|{pragma}
+il_whitespace_text	{il_whitespace_only}|{comment}|{pragma}
+
+st_whitespace	{st_whitespace_text}*
+il_whitespace	{il_whitespace_text}*
+
+st_whitespace_text_no_pragma	{st_whitespace_only}|{comment}
+il_whitespace_text_no_pragma	{il_whitespace_only}|{comment}
+
+st_whitespace_no_pragma	{st_whitespace_text_no_pragma}*
+il_whitespace_no_pragma	{il_whitespace_text_no_pragma}*
+
+qualified_identifier	{identifier}(\.{identifier})?
+
+
+
+/*****************************************/
+/* B.1.1 Letters, digits and identifiers */
+/*****************************************/
+/* NOTE: The following definitions only work if the host computer
+ *       is using the ASCII maping. For e.g., with EBCDIC [A-Z]
+ *       contains non-alphabetic characters!
+ *       The correct way of doing it would be to use
+ *       the [:upper:] etc... definitions.
+ *
+ *       Unfortunately, further on we need all printable
+ *       characters (i.e. [:print:]), but excluding '$'.
+ *       Flex does not allow sets to be composed by excluding
+ *       elements. Sets may only be constructed by adding new
+ *       elements, which means that we have to revert to
+ *       [\x20\x21\x23\x25\x26\x28-x7E] for the definition
+ *       of the printable characters with the required exceptions.
+ *       The above also implies the use of ASCII, but now we have
+ *       no way to work around it|
+ *
+ *       The conclusion is that our parser is limited to ASCII
+ *       based host computers!!
+ */
+letter		[A-Za-z]
+digit		[0-9]
+octal_digit	[0-7]
+hex_digit	{digit}|[A-F]
+identifier	({letter}|(_({letter}|{digit})))((_?({letter}|{digit}))*)
+
+
+/*******************/
+/* B.1.2 Constants */
+/*******************/
+
+/******************************/
+/* B.1.2.1   Numeric literals */
+/******************************/
+integer         {digit}((_?{digit})*)
+binary_integer  2#{bit}((_?{bit})*)
+bit		[0-1]
+octal_integer   8#{octal_digit}((_?{octal_digit})*)
+hex_integer     16#{hex_digit}((_?{hex_digit})*)
+exponent        [Ee]([+-]?){integer}
+/* The correct definition for real would be:
+ * real		{integer}\.{integer}({exponent}?)
+ *
+ * Unfortunately, the spec also defines fixed_point (B 1.2.3.1) as:
+ * fixed_point		{integer}\.{integer}
+ *
+ * This means that {integer}\.{integer} could be interpreted
+ * as either a fixed_point or a real.
+ * I have opted to interpret {integer}\.{integer} as a fixed_point.
+ * In order to do this, the definition of real has been changed to:
+ * real		{integer}\.{integer}{exponent}
+ *
+ * This means that the syntax parser now needs to define a real to be
+ * either a real_token or a fixed_point_token!
+ */
+real		{integer}\.{integer}{exponent}
+
+
+/*******************************/
+/* B.1.2.2   Character Strings */
+/*******************************/
+/*
+common_character_representation :=
+<any printable character except '$', '"' or "'">
+|'$$'
+|'$L'|'$N'|'$P'|'$R'|'$T'
+|'$l'|'$n'|'$p'|'$r'|'$t'
+
+NOTE: 	$ = 0x24
+	" = 0x22
+	' = 0x27
+
+	printable chars in ASCII: 0x20-0x7E
+*/
+
+esc_char_u		$L|$N|$P|$R|$T
+esc_char_l		$l|$n|$p|$r|$t
+esc_char		$$|{esc_char_u}|{esc_char_l}
+double_byte_char	(${hex_digit}{hex_digit}{hex_digit}{hex_digit})
+single_byte_char	(${hex_digit}{hex_digit})
+
+/* WARNING:
+ * This definition is only valid in ASCII...
+ *
+ * Flex includes the function print_char() that defines
+ * all printable characters portably (i.e. whatever character
+ * encoding is currently being used , ASCII, EBCDIC, etc...)
+ * Unfortunately, we cannot generate the definition of
+ * common_character_representation portably, since flex
+ * does not allow definition of sets by subtracting
+ * elements in one set from another set.
+ * This means we must build up the defintion of
+ * common_character_representation using only set addition,
+ * which leaves us with the only choice of defining the
+ * characters non-portably...
+ */
+common_character_representation		[\x20\x21\x23\x25\x26\x28-\x7E]|{esc_char}
+double_byte_character_representation 	$\"|'|{double_byte_char}|{common_character_representation}
+single_byte_character_representation 	$'|\"|{single_byte_char}|{common_character_representation}
+
+
+double_byte_character_string	\"({double_byte_character_representation}*)\"
+single_byte_character_string	'({single_byte_character_representation}*)'
+
+
+/************************/
+/* B 1.2.3.1 - Duration */
+/************************/
+fixed_point		{integer}\.{integer}
+
+fixed_point_d		{fixed_point}d
+integer_d		{integer}d
+
+fixed_point_h		{fixed_point}h
+integer_h		{integer}h
+
+fixed_point_m		{fixed_point}m
+integer_m		{integer}m
+
+fixed_point_s		{fixed_point}s
+integer_s		{integer}s
+
+fixed_point_ms		{fixed_point}ms
+integer_ms		{integer}ms
+
+
+/********************************************/
+/* B.1.4.1   Directly Represented Variables */
+/********************************************/
+/* The correct definition, if the standard were to be followed... */
+/*
+location_prefix		[IQM]
+size_prefix		[XBWDL]
+direct_variable		%{location_prefix}({size_prefix}?){integer}((.{integer})*)
+*/
+
+/* For the MatPLC, we will accept %<identifier>
+ * as a direct variable, this being mapped onto the MatPLC point
+ * named <identifier>
+ */
+/* TODO: we should not restrict it to only the accepted syntax
+ * of <identifier> as specified by the standard. MatPLC point names
+ * have a more permissive syntax.
+ *
+ * e.g. "P__234"
+ *    Is a valid MatPLC point name, but not a valid <identifier> !!
+ *    The same happens with names such as "333", "349+23", etc...
+ *    How can we handle these more expressive names in our case?
+ *    Remember that some direct variable may remain anonymous, with
+ *    declarations such as:
+ *    VAR
+ *       AT %I3 : BYTE := 255;
+ *    END_VAR
+ *    in which case we are currently using "I3" as the variable
+ *    name. For the other names, this would create havoc!!!
+ */
+direct_variable		%{identifier}
+
+/******************************************/
+/* B 1.4.3 - Declaration & Initialisation */
+/******************************************/
+incompl_location	%[IQM]\*
+
+
+
+
+%%
+	/* fprintf(stderr, "flex: state %d\n", YY_START); */
+
+	/*****************************************************/
+	/*****************************************************/
+	/*****************************************************/
+	/*****                                           *****/
+	/*****                                           *****/
+	/*****   F I R S T    T H I N G S    F I R S T   *****/
+	/*****                                           *****/
+	/*****                                           *****/
+	/*****************************************************/
+	/*****************************************************/
+	/*****************************************************/
+
+	/*********************************/
+	/* Handle the pragmas!     */
+	/*********************************/
+
+	/* We start off by searching for the pragmas we handle in the lexical parser. */
+<INITIAL>{file_include_pragma}	unput_text(0); yy_push_state(include_beg);
+
+	/* Any other pragma we find, we just pass it up to the syntax parser...   */
+	/* Note that the <body> state is exclusive, so we have to include it here too. */
+{pragma}	{/* return the pragmma without the enclosing '{' and '}' */
+		 yytext[strlen(yytext)-2] = '\0';
+		 yylval.ID=strdup(yytext+1);
+		 return pragma_token;
+		}
+<body>{pragma} {/* return the pragmma without the enclosing '{' and '}' */
+		 yytext[strlen(yytext)-2] = '\0';
+		 yylval.ID=strdup(yytext+1);
+		 return pragma_token;
+		}
+
+
+	/*********************************/
+	/* Handle the file includes!     */
+	/*********************************/
+<include_beg>{file_include_pragma_beg}	BEGIN(include_filename);
+
+<include_filename>{file_include_pragma_filename}	{
+			  /* got the include file name */
+			  int i;
+
+			  if (include_stack_ptr >= MAX_INCLUDE_DEPTH) {
+			    fprintf(stderr, "Includes nested too deeply\n");
+			    exit( 1 );
+			  }
+
+			  (include_stack[include_stack_ptr]).buffer_state = YY_CURRENT_BUFFER;
+			  (include_stack[include_stack_ptr]).lineno = yylineno;
+			  (include_stack[include_stack_ptr]).filename = current_filename;
+			  include_stack_ptr++;
+			  yylineno = 1;
+			  current_filename = strdup(yytext);
+
+			  for (i = 0, yyin = NULL; (INCLUDE_DIRECTORIES[i] != NULL) && (yyin == NULL); i++) {
+			    char *full_name = strdup2(INCLUDE_DIRECTORIES[i], yytext);
+			    if (full_name == NULL) {
+			      fprintf(stderr, "Out of memory!\n");
+			      exit( 1 );
+			    }
+			    yyin = fopen(full_name, "r");
+			    free(full_name);
+			  }
+
+			  if (!yyin) {
+			    fprintf(stderr, "Error opening included file %s\n", yytext);
+			    exit( 1 );
+			  }
+
+			  /* switch input buffer to new file... */
+			  yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+			  /* switch to whatever state was active before the include file */
+			  yy_pop_state();
+			  /* now process the new file... */
+			}
+
+
+<<EOF>>			{
+			  if (--include_stack_ptr < 0) {
+			    yyterminate();
+			  } else {
+			    yy_delete_buffer(YY_CURRENT_BUFFER);
+			    yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state);
+			    yylineno = include_stack[include_stack_ptr].lineno;
+			      /* removing constness of char *. This is safe actually,
+			       * since the only real const char * that is stored on the stack is
+			       * the first one (i.e. the opne that gets stored in include_stack[0],
+			       * which is never free'd!
+			       */
+			    free((char *)current_filename);
+			    current_filename = include_stack[include_stack_ptr].filename;
+			    yy_push_state(include_end);
+			  }
+			}
+
+<include_end>{file_include_pragma_end}	yy_pop_state();
+
+
+	/*********************************/
+	/* Handle all the state changes! */
+	/*********************************/
+
+	/* INITIAL -> decl */
+<INITIAL>{
+	/* NOTE: how about functions that do not delcare variables, and go directly to the body???
+	 *      - According to Section 2.5.1.3 (Function Declaration), item 2 in the list, a FUNCTION
+	 *        must have at least one input argument, so a correct declaration will have at least
+	 *        one VAR_INPUT ... VAR_END construct!
+	 *      - According to Section 2.5.2.2 (Function Block Declaration), a FUNCTION_BLOCK
+	 *        must have at least one input argument, so a correct declaration will have at least
+	 *        one VAR_INPUT ... VAR_END construct!
+	 *      - According to Section 2.5.3 (Programs), a PROGRAM must have at least one input
+	 *        argument, so a correct declaration will have at least one VAR_INPUT ... VAR_END
+	 *        construct!
+	 *
+	 *       All the above means that we needn't worry about PROGRAMs, FUNCTIONs or
+	 *       FUNCTION_BLOCKs that do not have at least one VAR_END before the body.
+	 *       If the code has an error, and no VAR_END before the body, we will simply
+	 *       continue in the <decl> state, untill the end of the FUNCTION, FUNCTION_BLOCK
+	 *       or PROGAM.
+	 */
+FUNCTION				BEGIN(decl); return FUNCTION;
+FUNCTION_BLOCK				BEGIN(decl); return FUNCTION_BLOCK;
+PROGRAM					BEGIN(decl); return PROGRAM;
+CONFIGURATION				BEGIN(config); return CONFIGURATION;
+}
+
+	/* INITIAL -> body */
+	/* required if the function, program, etc.. has no VAR block! */
+<INITIAL>{
+FUNCTION	BEGIN(body); return FUNCTION;
+FUNCTION_BLOCK	BEGIN(body); return FUNCTION_BLOCK;
+PROGRAM		BEGIN(body); return PROGRAM;
+}
+
+	/* decl -> body */
+<decl>{
+END_VAR{st_whitespace}VAR			unput_text(strlen("END_VAR")); return END_VAR;
+END_VAR{st_whitespace}				unput_text(strlen("END_VAR")); BEGIN(body); return END_VAR;
+}
+
+	/* body -> (il | st) */
+<body>{
+{qualified_identifier}{st_whitespace}":="	unput_text(0); BEGIN(st);
+{qualified_identifier}"["			unput_text(0); BEGIN(st);
+
+RETURN						unput_text(0); BEGIN(st);
+IF						unput_text(0); BEGIN(st);
+CASE						unput_text(0); BEGIN(st);
+FOR						unput_text(0); BEGIN(st);
+WHILE						unput_text(0); BEGIN(st);
+REPEAT						unput_text(0); BEGIN(st);
+EXIT						unput_text(0); BEGIN(st);
+
+
+{identifier}	{int token = get_identifier_token(yytext);
+		 if (token == prev_declared_fb_name_token) {
+		   /* the code has a call to a function block */
+		   BEGIN(st);
+		 } else {
+		   BEGIN(il);
+		 }
+		 unput_text(0);
+		}
+.		unput_text(0); BEGIN(il);
+
+}	/* end of body lexical parser */
+
+	/* (decl | body | il | st) -> INITIAL */
+END_FUNCTION		BEGIN(INITIAL); return END_FUNCTION;
+END_FUNCTION_BLOCK	BEGIN(INITIAL); return END_FUNCTION_BLOCK;
+END_PROGRAM		BEGIN(INITIAL); return END_PROGRAM;
+
+	/* config -> INITIAL */
+END_CONFIGURATION	BEGIN(INITIAL); return END_CONFIGURATION;
+
+
+
+	/***************************************/
+	/* Next is to to remove all whitespace */
+	/***************************************/
+	/* NOTE: pragmas are handled right at the beginning... */
+
+<INITIAL,config,decl,st,body>{st_whitespace_no_pragma}	/* Eat any whitespace */
+<il,body>{il_whitespace_no_pragma}		/* Eat any whitespace */
+
+
+	/*****************************************/
+	/* B.1.1 Letters, digits and identifiers */
+	/*****************************************/
+	/* NOTE: 'R1', 'IN', etc... are IL operators, and therefore tokens
+	 *       On the other hand, the spec does not define them as keywords,
+	 *       which means they may be re-used for variable names, etc...!
+	 *       The syntax parser already caters for the possibility of these
+	 *       tokens being used for variable names in their declarations.
+	 *       When they are declared, they will be added to the variable symbol table!
+	 *       Further appearances of these tokens must no longer be parsed
+	 *       as R1_tokens etc..., but rather as variable_name_tokens!
+	 *
+	 *       That is why the first thing we do with identifiers, even before
+	 *       checking whether they may be a 'keyword', is to check whether
+	 *       they have been previously declared as a variable name,
+	 *
+	 *      TODO: how about function names?
+	 */
+{identifier} 	{int token = get_identifier_token(yytext);
+		 if ((token == prev_declared_variable_name_token) ||
+		     (token == prev_declared_fb_name_token)) {
+		 /*
+		 if (token != identifier_token)
+		 */
+		 /* NOTE: if we use the above line, then 'MOD' et al must be removed
+		  * from the library_symbol_table as a default function name!
+		  */
+		   yylval.ID=strdup(yytext);
+		   return token;
+		 }
+		 /* otherwise, leave it for the other lexical parser rules... */
+		 REJECT;
+		}
+
+
+	/******************************************************/
+	/******************************************************/
+	/******************************************************/
+	/*****                                            *****/
+	/*****                                            *****/
+	/*****   N O W    D O   T H E   K E Y W O R D S   *****/
+	/*****                                            *****/
+	/*****                                            *****/
+	/******************************************************/
+	/******************************************************/
+	/******************************************************/
+
+
+EN	return EN;
+ENO	return ENO;
+
+
+	/******************************/
+	/* B 1.2.1 - Numeric Literals */
+	/******************************/
+TRUE		return TRUE;
+BOOL#1  	return TRUE;
+FALSE		return FALSE;
+BOOL#0  	return FALSE;
+
+
+	/************************/
+	/* B 1.2.3.1 - Duration */
+	/************************/
+t#		return T_SHARP;
+T#		return T_SHARP;
+TIME		return TIME;
+
+
+	/************************************/
+	/* B 1.2.3.2 - Time of day and Date */
+	/************************************/
+TIME_OF_DAY	return TIME_OF_DAY;
+TOD		return TIME_OF_DAY;
+DATE		return DATE;
+d#		return D_SHARP;
+D#		return D_SHARP;
+DATE_AND_TIME	return DATE_AND_TIME;
+DT		return DATE_AND_TIME;
+
+
+	/***********************************/
+	/* B 1.3.1 - Elementary Data Types */
+	/***********************************/
+BYTE		return BYTE;
+WORD		return WORD;
+DWORD		return DWORD;
+LWORD		return LWORD;
+
+
+	/********************************/
+	/* B 1.3.2 - Generic data types */
+	/********************************/
+	/* Strangely, the following symbols do not seem to be required! */
+	/* But we include them so they become reserved words, and do not
+	 * get passed up to bison as an identifier...
+	 */
+ANY		return ANY;
+ANY_DERIVED	return ANY_DERIVED;
+ANY_ELEMENTARY	return ANY_ELEMENTARY;
+ANY_MAGNITUDE	return ANY_MAGNITUDE;
+ANY_NUM		return ANY_NUM;
+ANY_REAL	return ANY_REAL;
+ANY_INT		return ANY_INT;
+ANY_BIT		return ANY_BIT;
+ANY_STRING	return ANY_STRING;
+ANY_DATE	return ANY_DATE;
+
+
+	/********************************/
+	/* B 1.3.3 - Derived data types */
+	/********************************/
+":="		return ASSIGN;
+".."		return DOTDOT;
+TYPE		return TYPE;
+END_TYPE	return END_TYPE;
+ARRAY		return ARRAY;
+OF		return OF;
+STRUCT		return STRUCT;
+END_STRUCT	return END_STRUCT;
+
+
+	/*********************/
+	/* B 1.4 - Variables */
+	/*********************/
+REAL		return REAL;
+LREAL		return LREAL;
+
+SINT		return SINT;
+INT		return INT;
+DINT		return DINT;
+LINT		return LINT;
+
+USINT		return USINT;
+UINT		return UINT;
+UDINT		return UDINT;
+ULINT		return ULINT;
+
+
+WSTRING		return WSTRING;
+STRING		return STRING;
+BOOL		return BOOL;
+
+TIME		return TIME;
+DATE		return DATE;
+DT		return DT;
+TOD		return TOD;
+DATE_AND_TIME	return DATE_AND_TIME;
+TIME_OF_DAY	return TIME_OF_DAY;
+
+
+	/******************************************/
+	/* B 1.4.3 - Declaration & Initialisation */
+	/******************************************/
+VAR_INPUT	return VAR_INPUT;
+VAR_OUTPUT	return VAR_OUTPUT;
+VAR_IN_OUT	return VAR_IN_OUT;
+VAR_EXTERNAL	return VAR_EXTERNAL;
+VAR_GLOBAL	return VAR_GLOBAL;
+END_VAR		return END_VAR;
+RETAIN		return RETAIN;
+NON_RETAIN	return NON_RETAIN;
+R_EDGE		return R_EDGE;
+F_EDGE		return F_EDGE;
+AT		return AT;
+
+
+	/***********************/
+	/* B 1.5.1 - Functions */
+	/***********************/
+FUNCTION	return FUNCTION;
+END_FUNCTION	return END_FUNCTION;
+VAR		return VAR;
+CONSTANT	return CONSTANT;
+
+
+	/*****************************/
+	/* B 1.5.2 - Function Blocks */
+	/*****************************/
+FUNCTION_BLOCK		return FUNCTION_BLOCK;
+END_FUNCTION_BLOCK	return END_FUNCTION_BLOCK;
+VAR_TEMP		return VAR_TEMP;
+VAR			return VAR;
+NON_RETAIN		return NON_RETAIN;
+END_VAR			return END_VAR;
+
+
+	/**********************/
+	/* B 1.5.3 - Programs */
+	/**********************/
+PROGRAM		return PROGRAM;
+END_PROGRAM	return END_PROGRAM;
+
+
+	/********************************************/
+	/* B 1.6 Sequential Function Chart elements */
+	/********************************************/
+	/* NOTE: the following identifiers/tokens clash with the R and S IL operators, as well
+	.* as other identifiers that may be used as variable names inside IL and ST programs.
+	 * They will have to be handled when we include parsing of SFC... For now, simply
+	 * ignore them!
+	 */
+	 /*
+ACTION		return ACTION;
+END_ACTION	return END_ACTION;
+
+TRANSITION	return TRANSITION;
+END_TRANSITION	return END_TRANSITION;
+FROM		return FROM;
+TO		return TO;
+PRIORITY	return PRIORITY;
+
+INITIAL_STEP	return INITIAL_STEP;
+STEP		return STEP;
+END_STEP	return END_STEP;
+
+L		return L;
+D		return D;
+SD		return SD;
+DS		return DS;
+SL		return SL;
+
+N		return N;
+P		return P;
+
+R		return R;
+S		return S;
+	*/
+
+
+	/********************************/
+	/* B 1.7 Configuration elements */
+	/********************************/
+CONFIGURATION		return CONFIGURATION;
+END_CONFIGURATION	return END_CONFIGURATION;
+TASK			return TASK;
+RESOURCE		return RESOURCE;
+ON			return ON;
+END_RESOURCE		return END_RESOURCE;
+VAR_CONFIG		return VAR_CONFIG;
+VAR_ACCESS		return VAR_ACCESS;
+END_VAR			return END_VAR;
+WITH			return WITH;
+PROGRAM			return PROGRAM;
+RETAIN			return RETAIN;
+NON_RETAIN		return NON_RETAIN;
+PRIORITY		return PRIORITY;
+SINGLE			return SINGLE;
+INTERVAL		return INTERVAL;
+READ_WRITE		return READ_WRITE;
+READ_ONLY		return READ_ONLY;
+
+
+	/***********************************/
+	/* B 2.1 Instructions and Operands */
+	/***********************************/
+<il>\n		return EOL;
+
+
+	/*******************/
+	/* B 2.2 Operators */
+	/*******************/
+	/* NOTE: we can't have flex return the same token for
+	 *       ANDN and &N, neither for AND and &, since
+	 *       AND and ANDN are considered valid variable
+	 *       function or functionblock type names!
+	 *       This means that the parser may decide that the
+	 *       AND or ANDN strings found in the source code
+	 *       are being used as variable names
+	 *       and not as operators, and will therefore transform
+	 *       these tokens into indentifier tokens!
+	 *       We can't have the parser thinking that the source
+	 *       code contained the string AND (which may be interpreted
+	 *       as a vairable name) when in reality the source code
+	 *       merely contained the character &, so we use two
+	 *       different tokens for & and AND (and similarly
+	 *       ANDN and &N)!
+	 */
+LD		return LD;
+LDN		return LDN;
+ST		return ST;
+STN		return STN;
+NOT		return NOT;
+S		return S;
+R		return R;
+S1		return S1;
+R1		return R1;
+CLK		return CLK;
+CU		return CU;
+CD		return CD;
+PV		return PV;
+IN		return IN;
+PT		return PT;
+AND		return AND;
+&		return AND2;
+OR		return OR;
+XOR		return XOR;
+ANDN		return ANDN;
+&N		return ANDN2;
+ORN		return ORN;
+XORN		return XORN;
+ADD		return ADD;
+SUB		return SUB;
+MUL		return MUL;
+DIV		return DIV;
+MOD		return MOD;
+GT		return GT;
+GE		return GE;
+EQ		return EQ;
+LT		return LT;
+LE		return LE;
+NE		return NE;
+CAL		return CAL;
+CALC		return CALC;
+CALCN		return CALCN;
+RET		return RET;
+RETC		return RETC;
+RETCN		return RETCN;
+JMP		return JMP;
+JMPC		return JMPC;
+JMPCN		return JMPCN;
+
+
+	/***********************/
+	/* B 3.1 - Expressions */
+	/***********************/
+"**"		return OPER_EXP;
+"<>"		return OPER_NE;
+">="		return OPER_GE;
+"<="		return OPER_LE;
+AND		return AND;
+XOR		return XOR;
+OR		return OR;
+NOT		return NOT;
+MOD		return MOD;
+
+
+	/*****************************************/
+	/* B 3.2.2 Subprogram Control Statements */
+	/*****************************************/
+:=		return ASSIGN;
+=>		return SENDTO;
+RETURN		return RETURN;
+
+
+	/********************************/
+	/* B 3.2.3 Selection Statements */
+	/********************************/
+IF		return IF;
+THEN		return THEN;
+ELSIF		return ELSIF;
+ELSE		return ELSE;
+END_IF		return END_IF;
+
+CASE		return CASE;
+OF		return OF;
+ELSE		return ELSE;
+END_CASE	return END_CASE;
+
+
+	/********************************/
+	/* B 3.2.4 Iteration Statements */
+	/********************************/
+FOR		return FOR;
+TO		return TO;
+BY		return BY;
+DO		return DO;
+END_FOR		return END_FOR;
+
+WHILE		return WHILE;
+DO		return DO;
+END_WHILE	return END_WHILE;
+
+REPEAT		return REPEAT;
+UNTIL		return UNTIL;
+END_REPEAT	return END_REPEAT;
+
+EXIT		return EXIT;
+
+
+
+
+
+	/********************************************************/
+	/********************************************************/
+	/********************************************************/
+	/*****                                              *****/
+	/*****                                              *****/
+	/*****  N O W    W O R K    W I T H    V A L U E S  *****/
+	/*****                                              *****/
+	/*****                                              *****/
+	/********************************************************/
+	/********************************************************/
+	/********************************************************/
+
+
+	/********************************************/
+	/* B.1.4.1   Directly Represented Variables */
+	/********************************************/
+{direct_variable}	{yylval.ID=strdup(yytext); return direct_variable_token;}
+
+
+	/******************************************/
+	/* B 1.4.3 - Declaration & Initialisation */
+	/******************************************/
+{incompl_location}	{yylval.ID=strdup(yytext); return incompl_location_token;}
+
+
+	/************************/
+	/* B 1.2.3.1 - Duration */
+	/************************/
+{fixed_point}		{yylval.ID=strdup(yytext); return fixed_point_token;}
+
+{fixed_point_d}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_d_token;}
+{integer_d}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_d_token;}
+
+{fixed_point_h}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_h_token;}
+{integer_h}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_h_token;}
+
+{fixed_point_m}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_m_token;}
+{integer_m}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_m_token;}
+
+{fixed_point_s}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return fixed_point_s_token;}
+{integer_s}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-1] = '\0'; return integer_s_token;}
+
+{fixed_point_ms}	{yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return fixed_point_ms_token;}
+{integer_ms}		{yylval.ID=strdup(yytext); yylval.ID[yyleng-2] = '\0'; return integer_ms_token;}
+
+
+	/*******************************/
+	/* B.1.2.2   Character Strings */
+	/*******************************/
+{double_byte_character_string} {yylval.ID=strdup(yytext); return double_byte_character_string_token;}
+{single_byte_character_string} {yylval.ID=strdup(yytext); return single_byte_character_string_token;}
+
+
+	/******************************/
+	/* B.1.2.1   Numeric literals */
+	/******************************/
+{integer}		{yylval.ID=strdup(yytext); return integer_token;}
+{real}			{yylval.ID=strdup(yytext); return real_token;}
+{binary_integer}	{yylval.ID=strdup(yytext); return binary_integer_token;}
+{octal_integer} 	{yylval.ID=strdup(yytext); return octal_integer_token;}
+{hex_integer} 		{yylval.ID=strdup(yytext); return hex_integer_token;}
+
+
+	/*****************************************/
+	/* B.1.1 Letters, digits and identifiers */
+	/*****************************************/
+<st>{identifier}/({st_whitespace})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
+<il>{identifier}/({il_whitespace})"=>"	{yylval.ID=strdup(yytext); return sendto_identifier_token;}
+{identifier} 				{yylval.ID=strdup(yytext);
+					 /*printf("returning identifier...: %s, %d\n", yytext, get_identifier_token(yytext));*/
+					 return get_identifier_token(yytext);}
+
+
+
+
+
+
+	/************************************************/
+	/************************************************/
+	/************************************************/
+	/*****                                      *****/
+	/*****                                      *****/
+	/*****   T H E    L E F T O V E R S . . .   *****/
+	/*****                                      *****/
+	/*****                                      *****/
+	/************************************************/
+	/************************************************/
+	/************************************************/
+
+	/* do the single character tokens...
+	 *
+	 *  e.g.:  ':'  '('  ')'  '+'  '*'  ...
+	 */
+.	{return yytext[0];}
+
+
+%%
+
+
+
+
+
+/***********************************/
+/* Utility function definitions... */
+/***********************************/
+
+/* print the include file stack to stderr... */
+void print_include_stack(void) {
+  int i;
+
+  if ((include_stack_ptr - 1) >= 0)
+    fprintf (stderr, "in file "); 
+  for (i = include_stack_ptr - 1; i >= 0; i--)
+    fprintf (stderr, "included from file %s:%d\n", include_stack[i].filename, include_stack[i].lineno);
+}
+
+
+/* return all the text in the current token back to the input stream, except the first n chars. */
+void unput_text(unsigned int n) {
+  /* it seems that flex has a bug in that it will not correctly count the line numbers
+   * if we return newlines back to the input stream. These newlines will be re-counted
+   * a second time when they are processed again by flex.
+   * We therefore determine how many newlines are in the text we are returning,
+   * and decrement the line counter acordingly...
+   */
+  unsigned int i;
+
+  for (i = n; i < strlen(yytext); i++)
+    if (yytext[i] == '\n')
+      yylineno--;
+
+  /* now return all the text back to the input stream... */
+  yyless(n);
+}
+
+
+/* Called by flex when it reaches the end-of-file */
+int yywrap(void)
+{
+  /* We reached the end of the input file... */
+
+  /* Should we continue with another file? */
+  /* If so:
+   *   open the new file...
+   *   return 0;
+   */
+
+  /* to we stop processing...
+   *
+   *   return 1;
+   */
+
+
+  return 1;  /* Stop scanning at end of input file. */
+}
+
+
+
+/*************************************/
+/* Include a main() function to test */
+/* the token parsing by flex....     */
+/*************************************/
+#ifdef TEST_MAIN
+
+#include "../util/symtable.hh"
+
+yystype yylval;
+YYLTYPE yylloc;
+
+const char *current_filename;
+
+int get_identifier_token(const char *identifier_str) {return 0;}
+
+
+
+
+
+int main(int argc, char **argv) {
+
+  FILE *in_file;
+  int res;
+
+  if (argc == 1) {
+    /* Work as an interactive (command line) parser... */
+    while((res=yylex()))
+      fprintf(stderr, "(line %d)token: %d\n", yylineno, res);
+  } else {
+    /* Work as non-interactive (file) parser... */
+    if((in_file = fopen(argv[1], "r")) == NULL) {
+      char *errmsg = strdup2("Error opening main file ", argv[1]);
+      perror(errmsg);
+      free(errmsg);
+      return -1;
+    }
+
+    /* parse the file... */
+    yyin = in_file;
+    current_filename = argv[1];
+    while(1) {
+      res=yylex();
+      fprintf(stderr, "(line %d)token: %d (%s)\n", yylineno, res, yylval.ID);
+    }
+  }
+
+  return 0;
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage1_2/iec.y	Wed Jan 31 15:32:38 2007 +0100
@@ -0,0 +1,5422 @@
+/*
+ * (c) 2003 Mario de Sousa
+ *
+ * Offered to the public under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 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.
+ *
+ * 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 IL and ST 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. 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.y.hh"
+
+/* file with the declarations of symbol tables... */
+#include "../util/symtable.hh"
+
+
+/* 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;						\
+  }							\
+}
+
+
+/* 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);
+
+
+/*********************************/
+/* The global symbol tables...   */
+/*********************************/
+/* NOTE: declared static because they are not accessed
+ *       directly by the lexical parser (flex), but rather
+ *       through the function get_identifier_token()
+ */
+/* A symbol table to store all the library elements */
+/* e.g.: <function_name , function_decl>
+ *       <fb_name , fb_decl>
+ *       <type_name , type_decl>
+ *       <program_name , program_decl>
+ *       <configuration_name , configuration_decl>
+ */
+static symtable_c<int, BOGUS_TOKEN_ID> library_element_symtable;
+
+/* A symbol table to store the declared variables of
+ * the function currently being parsed...
+ */
+static symtable_c<int, BOGUS_TOKEN_ID> variable_name_symtable;
+
+
+/*************************/
+/* global variables...   */
+/*************************/
+static symbol_c *tree_root = NULL;
+
+/* The name of the file currently being parsed...
+ * Note that flex accesses and updates this global variable
+ * apropriately whenever it comes across an (*#include <filename> *)
+ * directive...
+ */
+const char *current_filename = NULL;
+
+/* 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...
+ */
+bool allow_function_overloading = false;
+
+
+/************************/
+/* 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);
+
+/* print an error message */
+void print_err_msg(const char *filename, int lineno, const char *additional_error_msg);
+
+
+/************************/
+/* forward declarations */
+/************************/
+/* The functions declared here are defined in iec.flex... */
+void print_include_stack(void);
+
+
+%}
+
+
+
+%union {
+    symbol_c 	*leaf;
+    list_c	*list;
+    char 	*ID;	/* token value */
+    struct {
+      symbol_c	*first;
+      symbol_c	*second;
+    } double_symbol; /* used by il_simple_operator_clash_il_operand */
+}
+
+
+
+
+
+
+/*****************************/
+/* Prelimenary constructs... */
+/*****************************/
+%type <leaf> start
+
+%type <leaf>	any_identifier
+
+%token <ID>	prev_declared_variable_name_token
+%token <ID>	prev_declared_fb_name_token
+%type <leaf>	prev_declared_variable_name
+%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
+
+
+/* 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
+
+
+/* The pragmas... */
+%token <ID>	pragma_token
+%type <leaf>	pragma
+
+
+/* Where do these tokens belong ?? */
+/* TODO: get the syntax parser to handle these tokens... */
+%token	EN
+%token	ENO
+
+
+
+/***************************/
+/* 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
+/* a helper symbol for expression */
+%type  <leaf> non_negative_constant
+
+
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+/* Done totally within flex...
+  bit
+*/
+%type  <leaf> numeric_literal
+/* helper symbol for non_negative_constant */
+%type  <leaf> non_negative_numeric_literal
+%type  <leaf> integer_literal
+%type  <leaf> signed_integer
+/* a helper symbol for non_negative_constant */
+%type  <leaf> non_negative_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
+/* helper symbol for non_negative_real_literal */
+%type  <leaf> non_negative_signed_real
+%type  <leaf> real_literal
+/* helper symbol for non_negative_numeric_literal */
+%type  <leaf> non_negative_real_literal
+// %type  <leaf> exponent
+%type  <leaf> bit_string_literal
+%type  <leaf> boolean_literal
+
+%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
+
+
+/********************************/
+/* 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>	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
+%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>	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
+ *  - output_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 */
+/********************************************/
+/* TODO */
+/*
+%type  <list>	sequential_function_chart
+%type  <leaf>	sfc_network
+%type  <leaf>	initial_step
+%type  <leaf>	step
+%type  <leaf>	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>	timed_qualifier
+%type  <leaf>	action_time
+%type  <leaf>	indicator_name
+%type  <leaf>	transition
+%type  <leaf>	steps
+%type  <list>	step_name_list
+%type  <leaf>	transition_condition
+%type  <leaf>	action
+*/
+
+%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
+%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 <double_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
+%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
+/* 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
+/* helper symbol for fb_invocation */
+%type <list> param_assignment_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
+
+%%
+
+
+
+
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+/********************************************************/
+
+
+
+
+
+/*****************************/
+/* Prelimenary constructs... */
+/*****************************/
+start:
+  library	{$$ = $1;}
+;
+
+/* the pragmas... */
+pragma:
+  pragma_token	{$$ = new pragma_c($1);}
+
+
+
+/* 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);};
+prev_declared_fb_name: prev_declared_fb_name_token {$$ = new identifier_c($1);};
+
+prev_declared_simple_type_name: prev_declared_simple_type_name_token {$$ = new identifier_c($1);};
+prev_declared_subrange_type_name: prev_declared_subrange_type_name_token {$$ = new identifier_c($1);};
+prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1);};
+prev_declared_array_type_name: prev_declared_array_type_name_token {$$ = new identifier_c($1);};
+prev_declared_structure_type_name: prev_declared_structure_type_name_token {$$ = new identifier_c($1);};
+prev_declared_string_type_name: prev_declared_string_type_name_token {$$ = new identifier_c($1);};
+
+prev_declared_derived_function_name: prev_declared_derived_function_name_token {$$ = new identifier_c($1);};
+prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1);};
+prev_declared_program_type_name: prev_declared_program_type_name_token {$$ = new identifier_c($1);};
+
+
+
+
+
+/***************************/
+/* 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 error
+	{$$ = NULL;
+	 print_err_msg(current_filename, @2.last_line, "unknown error.");
+	 /* yychar */
+	 yyerrok;
+	}
+;
+
+
+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...
+ *       BUT, the lexical parser will interpret these names as tokens (keywords).
+ *       To allow these names to be used as function names, variable names, etc...,
+ *       I (Mario) have augmented the definition of identifier to also include the tokens
+ *       that are not explicitly defined as keywords in the spec!!
+ *
+ *
+ *
+ *
+ * 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);}
+/*  Make sure that all tokens (names) not defined as keywords are included here...
+ * I (Mario) have already done this, but if any changes are made to this file,
+ * this list MUST be kept consistent!!
+ */
+/**/
+| PRIORITY		{$$ = new identifier_c(strdup("PRIORITY"));}
+| SINGLE		{$$ = new identifier_c(strdup("SINGLE"));}
+| INTERVAL		{$$ = new identifier_c(strdup("INTERVAL"));}
+/**/
+| LD_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| LDN_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| ST_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| STN_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| S_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| R_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| S1_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| R1_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| CLK_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| CU_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| CD_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| PV_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| IN_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| PT_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| ANDN_operator		{$$ = il_operator_c_2_identifier_c($1);}
+/* NOTE: ANDN2_operator corresponds to the string '&N' in the source code!
+ *       This is __not__ a valid name, so it is omitted from this list!!
+ *| ANDN2_operator		{$$ = il_operator_c_2_identifier_c($1);}
+ */
+/* NOTE: 'AND' is a keyword, so should not appear on this list... */
+| ORN_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| XORN_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);}
+| 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);}
+| CAL_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| CALC_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| CALCN_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| RET_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| RETC_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| RETCN_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| JMP_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| JMPC_operator		{$$ = il_operator_c_2_identifier_c($1);}
+| JMPCN_operator	{$$ = il_operator_c_2_identifier_c($1);}
+/**/
+| L		{$$ = new identifier_c(strdup("L"));}
+| D		{$$ = new identifier_c(strdup("D"));}
+| SD		{$$ = new identifier_c(strdup("SD"));}
+| DS		{$$ = new identifier_c(strdup("DS"));}
+| SL		{$$ = new identifier_c(strdup("SL"));}
+| N		{$$ = new identifier_c(strdup("N"));}
+/* NOTE: the following two clash with the R and S IL operators.
+ * It will have to be handled when we include parsing of SFC...
+ */
+/*
+| R		{$$ = new identifier_c(strdup("R"));}
+| S		{$$ = new identifier_c(strdup("S"));}
+*/
+| P		{$$ = new identifier_c(strdup("P"));}
+
+;
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+constant:
+  numeric_literal
+| character_string
+| time_literal
+| bit_string_literal
+| boolean_literal
+/* 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
+ * either 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
+;
+
+/* a helper symbol for expression */
+/* A constant without any preceding '-', but may
+ * include a preceding '+' !
+ */
+non_negative_constant:
+  non_negative_numeric_literal
+| character_string
+| time_literal
+| bit_string_literal
+| boolean_literal
+| non_negative_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, intger '.' 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);}
+| fixed_point_token	{$$ = new real_c($1);}
+;
+
+integer:	integer_token		{$$ = new integer_c($1);};
+binary_integer:	binary_integer_token	{$$ = new binary_integer_c($1);};
+octal_integer:	octal_integer_token	{$$ = new octal_integer_c($1);};
+hex_integer:	hex_integer_token	{$$ = new hex_integer_c($1);};
+
+numeric_literal:
+  integer_literal
+| real_literal
+;
+
+/* helper symbol for non_negative_constant */
+non_negative_numeric_literal:
+  integer_literal
+| non_negative_real_literal
+;
+
+
+integer_literal:
+  integer_type_name '#' signed_integer
+	{$$ = new integer_literal_c($1, $3);}
+| integer_type_name '#' binary_integer
+	{$$ = new integer_literal_c($1, $3);}
+| integer_type_name '#' octal_integer
+	{$$ = new integer_literal_c($1, $3);}
+| integer_type_name '#' hex_integer
+	{$$ = new integer_literal_c($1, $3);}
+/* NOTE: see note in the definition of constant for reason
+ * why signed_integer, binary_integer, octal_integer
+ * and hex_integer are missing here!
+ */
+;
+
+signed_integer:
+  integer
+| '+' integer   {$$ = $2;}
+| '-' integer	{$$ = new neg_expression_c($2);}
+;
+
+/* a helper symbol for non_negative_constant */
+/* A integer without any preceding '-', but may
+ * include a preceding '+' !
+ */
+non_negative_signed_integer:
+  integer
+| '+' integer   {$$ = $2;}
+;
+
+
+real_literal:
+  signed_real
+| real_type_name '#' signed_real
+	{$$ = new real_literal_c($1, $3);}
+;
+
+/* helper symbol for non_negative_numeric_literal */
+non_negative_real_literal:
+  non_negative_signed_real
+| real_type_name '#' signed_real
+	{$$ = new real_literal_c($1, $3);}
+;
+
+signed_real:
+  real
+| '+' real	{$$ = $2;}
+| '-' real	{$$ = new neg_expression_c($2);}
+;
+
+/* helper symbol for non_negative_real_literal */
+non_negative_signed_real:
+  real
+| '+' real	{$$ = $2;}
+;
+
+
+bit_string_literal:
+  bit_string_type_name '#' integer  /* i.e. unsigned_integer */
+	{$$ = new bit_string_literal_c($1, $3);}
+| bit_string_type_name '#' binary_integer
+	{$$ = new bit_string_literal_c($1, $3);}
+| bit_string_type_name '#' octal_integer
+	{$$ = new bit_string_literal_c($1, $3);}
+| bit_string_type_name '#' hex_integer
+	{$$ = new bit_string_literal_c($1, $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!
+ */
+;
+
+
+boolean_literal:
+  TRUE	{$$ = new boolean_literal_c(new bool_type_name_c(),
+  				    new boolean_true_c());}
+| FALSE	{$$ = new boolean_literal_c(new bool_type_name_c(),
+				    new boolean_false_c());}
+/*
+|	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);};
+
+double_byte_character_string:	double_byte_character_string_token
+	{$$ = new double_byte_character_string_c($1);};
+
+
+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(NULL, $3);}
+| TIME '#' '-' interval
+	{$$ = new duration_c(new neg_time_c(), $4);}
+| T_SHARP interval
+	{$$ = new duration_c(NULL, $2);}
+| T_SHARP '-' interval
+	{$$ = new duration_c(new neg_time_c(), $3);}
+;
+
+
+interval:
+  days
+| hours
+| minutes
+| seconds
+| milliseconds
+;
+
+integer_d:  integer_d_token  {$$ = new integer_c($1);};
+integer_h:  integer_h_token  {$$ = new integer_c($1);};
+integer_m:  integer_m_token  {$$ = new integer_c($1);};
+integer_s:  integer_s_token  {$$ = new integer_c($1);};
+integer_ms: integer_ms_token {$$ = new integer_c($1);};
+
+fixed_point_d:
+  fixed_point_d_token
+	{$$ = new fixed_point_c($1);}
+| integer_d
+;
+
+fixed_point_h:
+  fixed_point_h_token
+	{$$ = new fixed_point_c($1);}
+| integer_h
+;
+
+fixed_point_m:
+  fixed_point_m_token
+	{$$ = new fixed_point_c($1);}
+| integer_m
+;
+
+fixed_point_s:
+  fixed_point_s_token
+	{$$ = new fixed_point_c($1);}
+| integer_s
+;
+
+fixed_point_ms:
+  fixed_point_ms_token
+	{$$ = new fixed_point_c($1);}
+| integer_ms
+;
+
+
+fixed_point:
+  fixed_point_token
+	{$$ = new fixed_point_c($1);}
+| integer
+;
+
+
+days:
+/*  fixed_point ('d') */
+  fixed_point_d
+	{$$ = new days_c($1, NULL);}
+/*| integer ('d') ['_'] hours */
+| integer_d hours
+	{$$ = new days_c($1, $2);}
+| integer_d '_' hours
+	{$$ = new days_c($1, $3);}
+;
+
+
+hours:
+/*  fixed_point ('h') */
+  fixed_point_h
+	{$$ = new hours_c($1, NULL);}
+/*| integer ('h') ['_'] minutes */
+| integer_h minutes
+	{$$ = new hours_c($1, $2);}
+| integer_h '_' minutes
+	{$$ = new hours_c($1, $3);}
+;
+
+minutes:
+/*  fixed_point ('m') */
+  fixed_point_m
+	{$$ = new minutes_c($1, NULL);}
+/*| integer ('m') ['_'] seconds */
+| integer_m seconds
+	{$$ = new minutes_c($1, $2);}
+| integer_m '_' seconds
+	{$$ = new minutes_c($1, $3);}
+;
+
+seconds:
+/*  fixed_point ('s') */
+  fixed_point_s
+	{$$ = new seconds_c($1, NULL);}
+/*| integer ('s') ['_'] milliseconds */
+| integer_s milliseconds
+	{$$ = new seconds_c($1, $2);}
+| integer_s '_' milliseconds
+	{$$ = new seconds_c($1, $3);}
+;
+
+milliseconds:
+/*  fixed_point ('ms') */
+  fixed_point_ms
+	{$$ = new milliseconds_c($1);}
+;
+
+
+
+/************************************/
+/* B 1.2.3.2 - Time of day and Date */
+/************************************/
+time_of_day:
+  TIME_OF_DAY '#' daytime
+	{$$ = new time_of_day_c($3);}
+;
+
+
+daytime:
+  day_hour ':' day_minute ':' day_second
+	{$$ = new daytime_c($1, $3, $5);}
+;
+
+
+day_hour: integer;
+day_minute: integer;
+day_second: fixed_point;
+
+
+date:
+  DATE '#' date_literal
+	{$$ = new date_c($3);}
+| D_SHARP date_literal
+	{$$ = new date_c($2);}
+;
+
+
+date_literal:
+  year '-' month '-' day
+	{$$ = new date_literal_c($1, $3, $5);}
+;
+
+
+year: integer;
+month: integer;
+day: integer;
+
+
+date_and_time:
+  DATE_AND_TIME '#' date_literal '-' daytime
+	{$$ = new date_and_time_c($3, $5);}
+;
+
+
+
+
+
+
+/**********************/
+/* 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 */
+/***********************************/
+elementary_type_name:
+  numeric_type_name
+| date_type_name
+| bit_string_type_name
+| elementary_string_type_name
+| TIME		{$$ = new time_type_name_c();}
+| BOOL		{$$ = new bool_type_name_c();}
+/* 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.
+ */
+;
+
+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();}
+| INT	{$$ = new int_type_name_c();}
+| DINT	{$$ = new dint_type_name_c();}
+| LINT	{$$ = new lint_type_name_c();}
+;
+
+unsigned_integer_type_name:
+  USINT	{$$ = new usint_type_name_c();}
+| UINT	{$$ = new uint_type_name_c();}
+| UDINT	{$$ = new udint_type_name_c();}
+| ULINT	{$$ = new ulint_type_name_c();}
+;
+
+real_type_name:
+  REAL	{$$ = new real_type_name_c();}
+| LREAL	{$$ = new lreal_type_name_c();}
+;
+
+date_type_name:
+  DATE		{$$ = new date_type_name_c();}
+| TIME_OF_DAY	{$$ = new tod_type_name_c();}
+| TOD		{$$ = new tod_type_name_c();}
+| DATE_AND_TIME	{$$ = new dt_type_name_c();}
+| DT		{$$ = new dt_type_name_c();}
+;
+
+
+bit_string_type_name:
+  BYTE	{$$ = new byte_type_name_c();}
+| WORD	{$$ = new word_type_name_c();}
+| DWORD	{$$ = new dword_type_name_c();}
+| LWORD	{$$ = new lword_type_name_c();}
+/* 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();}
+| WSTRING	{$$ = new wstring_type_name_c();}
+;
+
+
+
+/********************************/
+/* B 1.3.2 - Generic data types */
+/********************************/
+/* Strangely, the following symbol does 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	{$$ = $1;}
+| prev_declared_structure_type_name	{$$ = $1;}
+| prev_declared_string_type_name	{$$ = $1;}
+;
+
+single_element_type_name:
+  prev_declared_simple_type_name		{$$ = $1;}
+/* 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	{$$ = $1;}
+| prev_declared_subrange_type_name		{$$ = $1;}
+| prev_declared_enumerated_type_name		{$$ = $1;}
+;
+
+/* 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);}
+;
+
+/* helper symbol for data_type_declaration */
+type_declaration_list:
+  type_declaration ';'
+	{$$ = new type_declaration_list_c(); $$->add_element($1);}
+| type_declaration_list type_declaration ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+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);
+	 library_element_symtable.insert($1, prev_declared_simple_type_name_token);
+	}
+;
+
+
+simple_spec_init:
+  simple_specification
+  /* The following line was changed 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);}
+| prev_declared_simple_type_name ASSIGN constant
+	{$$ = new simple_spec_init_c($1, $3);}
+;
+
+/* 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);}
+| prev_declared_simple_type_name
+	{$$ = new simple_spec_init_c($1, NULL);}
+;
+
+
+subrange_type_declaration:
+/*  subrange_type_name ':' subrange_spec_init */
+  identifier ':' subrange_spec_init
+	{$$ = new subrange_type_declaration_c($1, $3);
+	 library_element_symtable.insert($1, prev_declared_subrange_type_name_token);
+	}
+;
+
+subrange_spec_init:
+  subrange_specification
+	{$$ = new subrange_spec_init_c($1, NULL);}
+| subrange_specification ASSIGN signed_integer
+	{$$ = new subrange_spec_init_c($1, $3);}
+;
+
+subrange_specification:
+  integer_type_name '(' subrange')'
+	{$$ = new subrange_specification_c($1, $3);}
+| prev_declared_subrange_type_name	{$$ = $1;}
+;
+
+
+subrange:
+  signed_integer DOTDOT signed_integer
+	{$$ = new subrange_c($1, $3);}
+;
+
+enumerated_type_declaration:
+/*  enumerated_type_name ':' enumerated_spec_init */
+  identifier ':' enumerated_spec_init
+	{$$ = new enumerated_type_declaration_c($1, $3);
+	 library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);
+	}
+;
+
+
+enumerated_spec_init:
+  enumerated_specification
+	{$$ = new enumerated_spec_init_c($1, NULL);}
+| enumerated_specification ASSIGN enumerated_value
+	{$$ = new enumerated_spec_init_c($1, $3);}
+;
+
+enumerated_specification:
+  '(' enumerated_value_list ')'
+	{$$ = $2;}
+| prev_declared_enumerated_type_name	{$$ = $1;}
+;
+
+/* helper symbol for enumerated_specification */
+enumerated_value_list:
+  enumerated_value
+	{$$ = new enumerated_value_list_c(); $$->add_element($1);}
+| enumerated_value_list ',' enumerated_value
+	{$$ = $1; $$->add_element($3);}
+;
+
+
+enumerated_value:
+  identifier
+	{$$ = $1;}
+| prev_declared_enumerated_type_name '#' any_identifier
+	{$$ = new enumerated_value_c($1, $3);}
+;
+
+
+
+array_type_declaration:
+/*  array_type_name ':' array_spec_init */
+  identifier ':' array_spec_init
+	{$$ = new array_type_declaration_c($1, $3);
+	 library_element_symtable.insert($1, prev_declared_array_type_name_token);
+	}
+;
+
+array_spec_init:
+  array_specification
+	{$$ = new array_spec_init_c($1, NULL);}
+| array_specification ASSIGN array_initialization
+	{$$ = new array_spec_init_c($1, $3);}
+;
+
+
+array_specification:
+  prev_declared_array_type_name
+	{$$ = $1;}
+| ARRAY '[' array_subrange_list ']' OF non_generic_type_name
+	{$$ = new array_specification_c($3, $6);}
+;
+
+/* helper symbol for array_specification */
+array_subrange_list:
+  subrange
+	{$$ = new array_subrange_list_c(); $$->add_element($1);}
+| array_subrange_list ',' subrange
+	{$$ = $1; $$->add_element($1);}
+;
+
+
+array_initialization:
+  '[' array_initial_elements_list ']'
+	{$$ = $2;}
+;
+
+
+/* helper symbol for array_initialization */
+array_initial_elements_list:
+  array_initial_elements
+	{$$ = new array_initial_elements_list_c(); $$->add_element($1);}
+| array_initial_elements_list ',' array_initial_elements
+	{$$ = $1; $$->add_element($3);}
+;
+
+
+array_initial_elements:
+  array_initial_element
+| integer '(' ')'
+| integer '(' array_initial_element ')'
+	{$$ = new array_initial_elements_c($1, $3);}
+;
+
+
+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);
+	 library_element_symtable.insert($1, prev_declared_structure_type_name_token);
+	}
+;
+
+
+structure_specification:
+  structure_declaration
+| initialized_structure
+;
+
+
+initialized_structure:
+  prev_declared_structure_type_name
+	{$$ = new initialized_structure_c($1, NULL);}
+| prev_declared_structure_type_name ASSIGN structure_initialization
+	{$$ = new initialized_structure_c($1, $3);}
+;
+
+
+structure_declaration:
+  STRUCT structure_element_declaration_list END_STRUCT
+	{$$ = $2;}
+;
+
+/* helper symbol for structure_declaration */
+structure_element_declaration_list:
+  structure_element_declaration ';'
+	{$$ = new structure_element_declaration_list_c(); $$->add_element($1);}
+| structure_element_declaration_list structure_element_declaration ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+structure_element_declaration:
+  structure_element_name ':' simple_spec_init
+	{$$ = new structure_element_declaration_c($1, $3);}
+| structure_element_name ':' subrange_spec_init
+	{$$ = new structure_element_declaration_c($1, $3);}
+| structure_element_name ':' enumerated_spec_init
+	{$$ = new structure_element_declaration_c($1, $3);}
+| structure_element_name ':' array_spec_init
+	{$$ = new structure_element_declaration_c($1, $3);}
+| structure_element_name ':' initialized_structure
+	{$$ = new structure_element_declaration_c($1, $3);}
+;
+
+
+structure_element_name: any_identifier;
+
+
+structure_initialization:
+  '(' structure_element_initialization_list ')'
+	{$$ = $2;}
+;
+
+/* helper symbol for structure_initialization */
+structure_element_initialization_list:
+  structure_element_initialization
+	{$$ = new structure_element_initialization_list_c(); $$->add_element($1);}
+| structure_element_initialization_list ',' structure_element_initialization
+	{$$ = $1; $$->add_element($3);}
+;
+
+
+structure_element_initialization:
+  structure_element_name ASSIGN constant
+	{$$ = new structure_element_initialization_c($1, $3);}
+| structure_element_name ASSIGN enumerated_value
+	{$$ = new structure_element_initialization_c($1, $3);}
+| structure_element_name ASSIGN array_initialization
+	{$$ = new structure_element_initialization_c($1, $3);}
+| structure_element_name ASSIGN structure_initialization
+	{$$ = new structure_element_initialization_c($1, $3);}
+;
+
+/* 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);
+	 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 */
+/*********************/
+variable:
+  symbolic_variable
+| direct_variable
+;
+
+
+symbolic_variable:
+/* NOTE: To be entirely correct, variable_name should be replacemed by
+ *         prev_declared_variable_name | prev_declared_fb_name | prev_declared_global_var_name
+ */
+  prev_declared_variable_name
+	{$$ = new symbolic_variable_c($1);}
+| prev_declared_fb_name
+	{$$ = new symbolic_variable_c($1);}
+| prev_declared_global_var_name
+	{$$ = new symbolic_variable_c($1);}
+| multi_element_variable
+;
+
+
+/* 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);}
+| any_multi_element_variable
+;
+
+
+/* for yet undeclared variable names ! */
+variable_name: identifier;
+
+
+
+
+
+/********************************************/
+/* B.1.4.1   Directly Represented Variables */
+/********************************************/
+direct_variable: direct_variable_token	{$$ = new direct_variable_c($1);};
+
+
+
+
+/*************************************/
+/* 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);}
+;
+
+/* please see note above any_symbolic_variable */
+any_array_variable:
+  any_subscripted_variable '[' subscript_list ']'
+	{$$ = new array_variable_c($1, $3);}
+;
+
+
+subscripted_variable:
+  symbolic_variable
+;
+
+
+/* please see note above any_symbolic_variable */
+any_subscripted_variable:
+  any_symbolic_variable
+;
+
+
+subscript_list:
+  subscript
+	{$$ = new subscript_list_c(); $$->add_element($1);}
+| subscript_list ',' subscript
+	{$$ = $1; $$->add_element($3);}
+;
+
+
+subscript:  expression;
+
+
+structured_variable:
+  record_variable '.' field_selector
+	{$$ = new structured_variable_c($1, $3);}
+;
+
+
+/* please see note above any_symbolic_variable */
+any_structured_variable:
+  any_record_variable '.' field_selector
+	{$$ = new structured_variable_c($1, $3);}
+;
+
+
+
+record_variable:
+  symbolic_variable
+;
+
+
+/* please see note above any_symbolic_variable */
+any_record_variable:
+  any_symbolic_variable
+;
+
+
+field_selector: any_identifier;
+
+
+
+
+
+
+/******************************************/
+/* B 1.4.3 - Declaration & Initialisation */
+/******************************************/
+input_declarations:
+  VAR_INPUT            input_declaration_list END_VAR
+	{$$ = new input_declarations_c(NULL, $2);}
+| VAR_INPUT RETAIN     input_declaration_list END_VAR
+	{$$ = new input_declarations_c(new retain_option_c(), $3);}
+| VAR_INPUT NON_RETAIN input_declaration_list END_VAR
+	{$$ = new input_declarations_c(new non_retain_option_c(), $3);}
+;
+
+/* helper symbol for input_declarations */
+input_declaration_list:
+  input_declaration ';'
+	{$$ = new input_declaration_list_c(); $$->add_element($1);}
+| input_declaration_list input_declaration ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+input_declaration:
+  var_init_decl
+| edge_declaration
+;
+
+
+edge_declaration:
+  var1_list ':' BOOL R_EDGE
+	{$$ = new edge_declaration_c(new raising_edge_option_c(), $1);}
+| var1_list ':' BOOL F_EDGE
+	{$$ = new edge_declaration_c(new falling_edge_option_c(), $1);}
+;
+
+
+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);}
+| var1_list ':' subrange_spec_init
+	{$$ = new var1_init_decl_c($1, $3);}
+| var1_list ':' enumerated_spec_init
+	{$$ = new var1_init_decl_c($1, $3);}
+;
+
+
+var1_list:
+  variable_name
+	{$$ = new var1_list_c(); $$->add_element($1);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+ | var1_list ',' variable_name
+	{$$ = $1; $$->add_element($3);
+	 variable_name_symtable.insert($3, prev_declared_variable_name_token);
+	}
+;
+
+
+
+array_var_init_decl:
+ var1_list ':' array_spec_init
+	{$$ = new array_var_init_decl_c($1, $3);}
+;
+
+
+structured_var_init_decl:
+  var1_list ':' initialized_structure
+	{$$ = new structured_var_init_decl_c($1, $3);}
+;
+
+
+/* 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);}
+/*| 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);}
+;
+
+
+
+/* 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();
+	 /* 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_init_decl_list END_VAR
+	{$$ = new output_declarations_c(NULL, $2);}
+| VAR_OUTPUT RETAIN var_init_decl_list END_VAR
+	{$$ = new output_declarations_c(new retain_option_c(), $3);}
+| VAR_OUTPUT NON_RETAIN var_init_decl_list END_VAR
+	{$$ = new output_declarations_c(new non_retain_option_c(), $3);}
+;
+
+
+
+input_output_declarations:
+  VAR_IN_OUT var_declaration_list END_VAR
+	{$$ = new input_output_declarations_c($2);}
+;
+
+
+
+/* helper symbol for input_output_declarations */
+var_declaration_list:
+  var_declaration ';'
+	{$$ = new var_declaration_list_c(); $$->add_element($1);}
+| var_declaration_list var_declaration ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+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);}
+| var1_list  ':' subrange_specification
+	{$$ = new var1_init_decl_c($1, $3);}
+| var1_list  ':' enumerated_specification
+	{$$ = new var1_init_decl_c($1, $3);}
+;
+
+
+
+array_var_declaration:
+  var1_list ':' array_specification
+	{$$ = new array_var_declaration_c($1, $3);}
+;
+
+structured_var_declaration:
+  var1_list ':' prev_declared_structure_type_name
+	{$$ = new structured_var_declaration_c($1, $3);}
+;
+
+
+var_declarations:
+  VAR var_init_decl_list END_VAR
+	{$$ = new var_declarations_c(NULL, $2);}
+| VAR CONSTANT var_init_decl_list END_VAR
+	{$$ = new var_declarations_c(new constant_option_c(), $3);}
+;
+
+
+retentive_var_declarations:
+  VAR RETAIN var_init_decl_list END_VAR
+	{$$ = new retentive_var_declarations_c($3);}
+;
+
+
+located_var_declarations:
+  VAR  located_var_decl_list END_VAR
+	{$$ = new located_var_declarations_c(NULL, $2);}
+| VAR CONSTANT located_var_decl_list END_VAR
+	{$$ = new located_var_declarations_c(new constant_option_c(), $3);}
+| VAR RETAIN located_var_decl_list END_VAR
+	{$$ = new located_var_declarations_c(new retain_option_c(), $3);}
+| VAR NON_RETAIN located_var_decl_list END_VAR
+	{$$ = new located_var_declarations_c(new non_retain_option_c(), $3);}
+;
+
+
+/* helper symbol for located_var_declarations */
+located_var_decl_list:
+  located_var_decl ';'
+	{$$ = new located_var_decl_list_c(); $$->add_element($1);}
+| located_var_decl_list located_var_decl ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+located_var_decl:
+  variable_name location ':' located_var_spec_init
+	{$$ = new located_var_decl_c($1, $2, $4);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+| location ':' located_var_spec_init
+	{$$ = new located_var_decl_c(NULL, $1, $3);}
+;
+
+
+
+
+external_var_declarations:
+  VAR_EXTERNAL external_declaration_list END_VAR
+	{$$ = new external_var_declarations_c(NULL, $2);}
+| VAR_EXTERNAL CONSTANT external_declaration_list END_VAR
+	{$$ = new external_var_declarations_c(new constant_option_c(), $3);}
+;
+
+/* helper symbol for external_var_declarations */
+external_declaration_list:
+  external_declaration ';'
+	{$$ = new external_declaration_list_c(); $$->add_element($1);}
+| external_declaration_list external_declaration';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+external_declaration:
+  global_var_name ':' simple_specification
+	{$$ = new external_declaration_c($1, $3);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+| global_var_name ':' subrange_specification
+	{$$ = new external_declaration_c($1, $3);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+| global_var_name ':' enumerated_specification
+	{$$ = new external_declaration_c($1, $3);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+| global_var_name ':' array_specification
+	{$$ = new external_declaration_c($1, $3);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+| global_var_name ':' prev_declared_structure_type_name
+	{$$ = new external_declaration_c($1, $3);
+	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
+	}
+| global_var_name ':' function_block_type_name
+	{$$ = new external_declaration_c($1, $3);
+	 variable_name_symtable.insert($1, prev_declared_fb_name_token);
+	}
+;
+
+
+global_var_name: identifier;
+
+
+global_var_declarations:
+  VAR_GLOBAL global_var_decl_list END_VAR
+	{$$ = new global_var_declarations_c(NULL, $2);}
+| VAR_GLOBAL CONSTANT global_var_decl_list END_VAR
+	{$$ = new global_var_declarations_c(new constant_option_c(), $3);}
+| VAR_GLOBAL RETAIN global_var_decl_list END_VAR
+	{$$ = new global_var_declarations_c(new retain_option_c(), $3);}
+;
+
+
+/* helper symbol for global_var_declarations */
+global_var_decl_list:
+  global_var_decl ';'
+	{$$ = new global_var_decl_list_c(); $$->add_element($1);}
+| global_var_decl_list global_var_decl ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+global_var_decl:
+  global_var_spec ':'
+	{$$ = new global_var_decl_c($1, NULL);}
+| global_var_spec ':' located_var_spec_init
+	{$$ = new global_var_decl_c($1, $3);}
+| global_var_spec ':' function_block_type_name
+	{$$ = new global_var_decl_c($1, $3);}
+;
+
+
+global_var_spec:
+  global_var_list	{$$ = $1;}
+| location
+| global_var_name location
+	{$$ = new global_var_spec_c($1, $2);
+	 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
+	{$$ = new location_c($2);}
+;
+
+
+
+global_var_list:
+  global_var_name
+	{$$ = new global_var_list_c(); $$->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);
+	}
+;
+
+
+
+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);}
+;
+
+/* NOTE: The constructs
+ *
+ *       [W]STRING
+ *       and
+ *       [W]STRING ASSIGN single_byte_character_string
+ *
+ *       were removed as they are already contained
+ *       within a other constructs.
+ *
+ *       single_byte_string_spec is used in:
+ *        - single_byte_string_var_declaration ->
+ *           -> string_var_declaration ---> var_init_decl
+ *                                     |--> temp_var_decl
+ *                                     |--> var2_init_decl
+ *        - located_var_spec_init
+ *
+ *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
+ *        -> simple_spec -> simple_specification -> simple_spec_init ->
+ *        -> located_var_spec_init
+ *
+ *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
+ *        -> simple_spec -> simple_specification -> simple_spec_init ->
+ *        -> var1_init_decl -> var_init_decl
+ *
+ *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
+ *        -> simple_spec -> simple_specification -> simple_spec_init ->
+ *        -> var1_init_decl -> var2_init_decl
+ *
+ *       STRING [ASSIGN string_constant] -> elementary_string_type_name ->
+ *        -> simple_spec -> simple_specification ->
+ *        -> var1_declaration -> temp_var_decl
+ */
+single_byte_string_spec:
+/*  STRING
+	{$$ = new single_byte_string_spec_c(NULL, NULL);}
+*/
+  STRING '[' integer ']'
+	{$$ = new single_byte_string_spec_c($3, NULL);}
+/*
+| STRING ASSIGN single_byte_character_string
+	{$$ = new single_byte_string_spec_c(NULL, $3);}
+*/
+| STRING '[' integer ']' ASSIGN single_byte_character_string
+	{$$ = new single_byte_string_spec_c($3, $6);}
+;
+
+
+double_byte_string_var_declaration:
+  var1_list ':' double_byte_string_spec
+	{$$ = new double_byte_string_var_declaration_c($1, $3);}
+;
+
+double_byte_string_spec:
+/*  WSTRING
+	{$$ = new double_byte_string_spec_c(NULL, NULL);}
+*/
+  WSTRING '[' integer ']'
+	{$$ = new double_byte_string_spec_c($3, NULL);}
+/*
+| WSTRING ASSIGN double_byte_character_string
+	{$$ = new double_byte_string_spec_c(NULL, $3);}
+*/
+| WSTRING '[' integer ']' ASSIGN double_byte_character_string
+	{$$ = new double_byte_string_spec_c($3, $6);}
+;
+
+
+
+incompl_located_var_declarations:
+  VAR            incompl_located_var_decl_list END_VAR
+	{$$ = new incompl_located_var_declarations_c(NULL, $2);}
+| VAR     RETAIN incompl_located_var_decl_list END_VAR
+	{$$ = new incompl_located_var_declarations_c(new retain_option_c(), $3);}
+| VAR NON_RETAIN incompl_located_var_decl_list END_VAR
+	{$$ = new incompl_located_var_declarations_c(new non_retain_option_c(), $3);}
+;
+
+/* helper symbol for incompl_located_var_declarations */
+incompl_located_var_decl_list:
+  incompl_located_var_decl ';'
+	{$$ = new incompl_located_var_decl_list_c(); $$->add_element($1);}
+| incompl_located_var_decl_list incompl_located_var_decl ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+incompl_located_var_decl:
+  variable_name incompl_location ':' var_spec
+	{$$ = new incompl_located_var_decl_c($1, $2, $4);}
+;
+
+
+incompl_location:
+  AT incompl_location_token
+	{$$ = new incompl_location_c($2);}
+;
+
+
+var_spec:
+  simple_specification
+| subrange_specification
+| enumerated_specification
+| array_specification
+| prev_declared_structure_type_name
+| string_spec
+;
+
+
+/* helper symbol for var_spec */
+/* NOTE: The constructs
+ *
+ *       STRING
+ *       and
+ *       WSTRING
+ *
+ *       were removed as they are already contained
+ *       within a simple_specification.
+ */
+string_spec:
+/*  STRING
+	{$$ = new single_byte_string_spec_c(NULL, NULL);}
+*/
+  STRING '[' integer ']'
+	{$$ = new single_byte_string_spec_c($3, NULL);}
+/*
+| WSTRING
+	{$$ = new double_byte_string_spec_c(NULL, NULL);}
+*/
+| WSTRING '[' integer ']'
+	{$$ = new double_byte_string_spec_c($3, NULL);}
+;
+
+
+
+
+/* intermediate helper symbol for:
+ *  - non_retentive_var_decls
+ *  - output_declarations
+ *  - var_declarations
+ */
+var_init_decl_list:
+  var_init_decl ';'
+	{$$ = new var_init_decl_list_c(); $$->add_element($1);}
+| var_init_decl_list var_init_decl ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+
+
+/***********************/
+/* B 1.5.1 - Functions */
+/***********************/
+/* 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;
+
+/*
+function_name:
+  prev_declared_derived_function_name
+| standard_function_name
+;
+*/
+
+/* 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);}
+;
+
+
+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"));}
+;
+
+/* 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_operator	{$$ = il_operator_c_2_identifier_c($1);}
+//NOTE: AND2 (corresponding to the source code string '&') does not clash
+//      with a standard function name, so should be commented out!
+//| AND2_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| OR_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| XOR_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| ADD_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| SUB_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| MUL_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| DIV_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| MOD_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| GT_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| GE_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| EQ_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| LT_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| LE_operator	{$$ = il_operator_c_2_identifier_c($1);}
+| NE_operator	{$$ = il_operator_c_2_identifier_c($1);}
+;
+
+
+derived_function_name:
+  identifier
+| prev_declared_derived_function_name
+	{$$ = $1;
+	 if (not(allow_function_overloading))
+	   ERROR;
+	}
+;
+
+
+function_declaration:
+/*  FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
+  function_name_declaration ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION
+	{$$ = new function_declaration_c($1, $3, $4, $5);
+	 variable_name_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);
+	 variable_name_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);
+	 }
+	}
+;
+
+/* 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);
+	}
+;
+
+
+
+/* intermediate helper symbol for function_declaration */
+io_OR_function_var_declarations_list:
+  /* empty */
+	{$$ = new var_declarations_list_c();}
+| 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);}
+;
+
+
+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(), $3);}
+| VAR var2_init_decl_list END_VAR
+	{$$ = new function_var_decls_c(NULL, $2);}
+;
+
+/* intermediate helper symbol for function_var_decls */
+var2_init_decl_list:
+  var2_init_decl ';'
+	{$$ = new var2_init_decl_list_c(); $$->add_element($1);}
+| var2_init_decl_list var2_init_decl ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+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);};
+
+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);
+	 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();
+	}
+;
+
+
+
+/* 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:
+  /* empty */
+	{$$ = new var_declarations_list_c();}
+| 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);}
+;
+
+/* 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);}
+;
+
+
+/* intermediate helper symbol for temp_var_decls */
+temp_var_decls_list:
+  temp_var_decl ';'
+	{$$ = new temp_var_decls_list_c(); $$->add_element($1);}
+| temp_var_decls_list temp_var_decl ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+non_retentive_var_decls:
+  VAR NON_RETAIN var_init_decl_list END_VAR
+	{$$ = new non_retentive_var_decls_c($3);}
+;
+
+
+
+function_block_body:
+  statement_list	{$$ = $1;}
+| instruction_list	{$$ = $1;}
+/*
+| sequential_function_chart
+| 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);
+	 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();
+	}
+;
+
+
+/* helper symbol for program_declaration */
+/*
+ * NOTE: we re-use the var_declarations_list_c
+ */
+program_var_declarations_list:
+  /* empty */
+	{$$ = new var_declarations_list_c();}
+| 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);}
+*/
+;
+
+
+/* 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 */
+/********************************************/
+/* TODO ... */
+
+/*
+sequential_function_chart:
+  sfc_network
+| sequential_function_chart sfc_network
+;
+
+sfc_network:
+  initial_step
+| sfc_network step
+| sfc_network transition
+| sfc_network action
+;
+
+initial_step:
+  INITIAL_STEP step_name ':' action_association_list END_STEP
+;
+
+step:
+  STEP step_name ':' action_association_list END_STEP
+;
+
+/* helper symbol for:
+ *  - initial_step
+ *  - step
+ *
+action_association_list:
+  /* empty *
+| action_association_list action_association ';'
+;
+
+step_name: identifier;
+
+action_association:
+  action_name '(' action_qualifier indicator_name_list ')'
+;
+
+/* helper symbol for action_association *
+indicator_name_list:
+  /* empty *
+| indicator_name_list ',' indicator_name
+;
+
+action_name: identifier;
+
+action_qualifier:
+  /* empty *
+| N
+| R
+| S
+| P
+| timed_qualifier ',' action_time
+;
+
+timed_qualifier:
+  L
+| D
+| SD
+| DS
+| SL
+;
+
+action_time:
+  duration
+| variable_name
+;
+
+indicator_name: variable_name;
+
+transition:
+  TRANSITION FROM steps TO steps transition_condition END_TRANSITION
+| TRANSITION transition_name FROM steps TO steps transition_condition END_TRANSITION
+| TRANSITION '(' PRIORITY ASSIGN integer ')' FROM steps TO steps transition_condition END_TRANSITION
+| TRANSITION transition_name '(' PRIORITY ASSIGN integer ')' FROM steps TO steps transition_condition END_TRANSITION
+;
+
+transition_name: identifier;
+
+steps:
+  step_name
+| '(' step_name_list ')'
+;
+
+
+step_name_list:
+  step_name ',' step_name
+| step_name_list ',' step_name
+;
+
+
+transition_condition:
+  ':' simple_instruction_list
+| ASSIGN expression ';'
+| ':' fbd_network
+| ':' rung
+;
+
+action:
+  ACTION action_name ':' function_block_body END_ACTION
+;
+*/
+
+/********************************/
+/* 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_delcared_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);};
+prev_declared_resource_name: prev_declared_resource_name_token {$$ = new identifier_c($1);};
+prev_declared_program_name: prev_declared_program_name_token {$$ = new identifier_c($1);};
+// prev_declared_task_name: prev_declared_task_name_token {$$ = new identifier_c($1);};
+
+
+
+
+
+
+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();}
+   optional_access_declarations
+   optional_instance_specific_initializations
+  END_CONFIGURATION
+	{$$ = new configuration_declaration_c($2, $3, $4, $6, $7);
+	 library_element_symtable.insert($2, prev_declared_configuration_name_token);
+	 variable_name_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);
+	 library_element_symtable.insert($2, prev_declared_configuration_name_token);
+	 variable_name_symtable.pop();
+	}
+| CONFIGURATION error END_CONFIGURATION
+	{$$ = NULL;
+	 print_err_msg(current_filename, @2.last_line, "error in configuration declaration.");
+	 /* yychar */
+	 yyerrok;
+	}
+;
+
+// 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(); $$->add_element($1);}
+| resource_declaration_list resource_declaration
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+resource_declaration:
+  RESOURCE {variable_name_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);
+         variable_name_symtable.pop();
+	 variable_name_symtable.insert($3, prev_declared_resource_name_token);
+	}
+;
+
+
+single_resource_declaration:
+ task_configuration_list program_configuration_list
+	{$$ = new single_resource_declaration_c($1, $2);}
+;
+
+
+// helper symbol for single_resource_declaration //
+task_configuration_list:
+  // empty
+	{$$ = new task_configuration_list_c();}
+| task_configuration_list task_configuration ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+// helper symbol for single_resource_declaration //
+program_configuration_list:
+  program_configuration ';'
+	{$$ = new program_configuration_list_c(); $$->add_element($1);}
+| program_configuration_list program_configuration ';'
+	{$$ = $1; $$->add_element($2);}
+;
+
+
+resource_name: identifier;
+
+/*
+access_declarations:
+ VAR_ACCESS access_declaration_list END_VAR
+	{$$ = NULL;}
+;
+
+// helper symbol for access_declarations //
+access_declaration_list:
+  access_declaration ';'
+| access_declaration_list access_declaration ';'
+;
+
+
+access_declaration:
+  access_name ':' access_path ':' non_generic_type_name
+| access_name ':' access_path ':' non_generic_type_name direction
+;
+
+
+access_path:
+  direct_variable
+| prev_delcared_resource_name '.' direct_variable
+| any_fb_name_list symbolic_variable
+| prev_delcared_resource_name '.' any_fb_name_list symbolic_variable
+| prev_delcared_program_name '.'  any_fb_name_list symbolic_variable
+| prev_delcared_resource_name '.' prev_delcared_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();}
+//| 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);}
+|                                 prev_declared_global_var_name '.' structure_element_name
+	{$$ = new global_var_reference_c(NULL, $1, $3);}
+| prev_declared_resource_name '.' prev_declared_global_var_name
+	{$$ = new global_var_reference_c($1, $3, NULL);}
+| prev_declared_resource_name '.' prev_declared_global_var_name '.' structure_element_name
+	{$$ = new global_var_reference_c($1, $3, $5);}
+;
+
+
+//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);}
+;
+
+program_name: identifier;
+
+/*
+direction:
+  READ_WRITE
+	{$$ = NULL;}
+| READ_ONLY
+	{$$ = NULL;}
+;
+*/
+
+task_configuration:
+  TASK task_name task_initialization
+	{$$ = new task_configuration_c($2, $3);}
+;
+
+/* NOTE: The specification does nopt 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 ')' //
+  '(' PRIORITY ASSIGN integer ')'
+	{$$ = new task_initialization_c(NULL, NULL, $4);}
+| '(' SINGLE ASSIGN data_source ','   PRIORITY ASSIGN integer ')'
+	{$$ = new task_initialization_c($4, NULL, $8);}
+| '(' INTERVAL ASSIGN data_source ',' PRIORITY ASSIGN integer ')'
+	{$$ = new task_initialization_c(NULL, $4, $8);}
+| '(' SINGLE ASSIGN data_source ',' INTERVAL ASSIGN data_source ',' PRIORITY ASSIGN integer ')'
+	{$$ = new task_initialization_c($4, $8, $12);}
+;
+
+data_source:
+  constant
+| global_var_reference
+| program_output_reference
+| 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);
+	 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(), $3, $4, $6, $7);
+	 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(), $3, $4, $6, $7);
+	 variable_name_symtable.insert($3, prev_declared_program_name_token);
+	}
+;
+
+// helper symbol for program_configuration //
+optional_task_name:
+  // empty //
+	{$$ = NULL;}
+| WITH task_name
+	{$$ = $2;}
+;
+
+// helper symbol for program_configuration //
+optional_prog_conf_elements:
+  // empty //
+	{$$ = NULL;}
+| '(' prog_conf_elements ')'
+	{$$ = $2;}
+;
+
+
+prog_conf_elements:
+  prog_conf_element
+	{$$ = new prog_conf_elements_c(); $$->add_element($1);}
+| prog_conf_elements ',' prog_conf_element
+	{$$ = $1; $$->add_element($3);}
+;
+
+
+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);}
+;
+
+
+/* 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);}