Add support for de-referencing of REF_TO datatypes (Note: dereferencing of arrays and structs not yet supported!)
--- a/absyntax/absyntax.def Sat Sep 27 20:09:19 2014 +0100
+++ b/absyntax/absyntax.def Sun Sep 28 16:35:44 2014 +0100
@@ -1139,16 +1139,17 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
-SYM_REF1(ref_expression_c, exp) /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
-SYM_REF2(or_expression_c, l_exp, r_exp)
+SYM_REF1( ref_expression_c, exp) /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+SYM_REF1(deref_expression_c, exp) /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Dereferences an address! */
+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( 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, bool deprecated_operation;)
SYM_REF2(sub_expression_c, l_exp, r_exp, bool deprecated_operation;)
SYM_REF2(mul_expression_c, l_exp, r_exp, bool deprecated_operation;)
--- a/lib/C/accessor.h Sat Sep 27 20:09:19 2014 +0100
+++ b/lib/C/accessor.h Sun Sep 28 16:35:44 2014 +0100
@@ -111,6 +111,15 @@
#define __GET_LOCATED_REF(name, ...)\
(&((*(name.value)) __VA_ARGS__))
+#define __GET_VAR_DREF(name, ...)\
+ (*(name.value __VA_ARGS__))
+#define __GET_EXTERNAL_DREF(name, ...)\
+ (*((*(name.value)) __VA_ARGS__))
+#define __GET_EXTERNAL_FB_DREF(name, ...)\
+ (*(__GET_VAR(((*name) __VA_ARGS__))))
+#define __GET_LOCATED_DREF(name, ...)\
+ (*((*(name.value)) __VA_ARGS__))
+
// variable setting macros
#define __SET_VAR(prefix, name, suffix, new_value)\
--- a/main.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/main.cc Sun Sep 28 16:35:44 2014 +0100
@@ -122,7 +122,7 @@
/******************************************************/
printf(" -s : allow use of safe datatypes (SAFEBOOL, etc.) (defined in PLCOpen Safety)\n");
printf(" -n : allow use of nested comments (an IEC 61131-3 v3 feature)\n");
- printf(" -r : allow use of references (REF_TO, REF, NULL) (an IEC 61131-3 v3 feature)\n");
+ printf(" -r : allow use of references (REF_TO, REF, ^, NULL) (an IEC 61131-3 v3 feature)\n");
printf(" -R : allow use of REF_TO ANY datatypes (a non-standard extension!)\n");
printf(" as well as REF_TO in ARRAYs and STRUCTs (a non-standard extension!)\n");
printf(" -c : create conversion functions for enumerated data types\n");
--- a/stage1_2/iec_bison.yy Sat Sep 27 20:09:19 2014 +0100
+++ b/stage1_2/iec_bison.yy Sun Sep 28 16:35:44 2014 +0100
@@ -416,6 +416,7 @@
/* Keywords in IEC 61131-3 v3 */
%token REF
+%token DREF
%token REF_TO
%token NULL_token /* cannot use simply 'NULL', as it conflicts with the NULL keyword in C++ */
@@ -1319,7 +1320,8 @@
* are not required. Their values are integrated
* directly into other rules...
*/
-%type <leaf> ref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */
+%type <leaf> ref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */
+%type <leaf> deref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */
%type <leaf> expression
%type <leaf> xor_expression
%type <leaf> and_expression
@@ -3399,7 +3401,27 @@
| identifier
{$$ = new symbolic_variable_c($1, locloc(@$));}
*/
-;
+| symbolic_variable '^'
+ /* Dereferencing operator defined in IEC 61131-3 v3. However, implemented here differently then how it is defined in the standard! See following note for explanation! */
+ {$$ = new deref_expression_c($1, locloc(@$));}
+;
+/*
+ * NOTE: The syntax defined in the v3 standard for the dereferencing operator '^' seems to me to be un-intentionally
+ * limited. For example
+ * ref_to_bool_var := REF( array_of_bool [1] ); <--- Allowed!
+ * ref_to_bool_var := REF( ref_to_array_of_bool^[1] ); <--- Allowed!
+ * bool_var := array_of_ref_to_bool[1]^; <--- NOT Allowed!
+ * ref_to_array_of_bool^[1] := FALSE; <--- Allowed!
+ * I consider this a bug in the v3 standard!!
+ * I have therefore opted to implement this by simply adding a rule to symbolic_variable
+ * symbolic_variable:
+ * ...
+ * | symbolic_variable '^'
+ * This simple rule should be able to cover all the needed dereferencing syntax!
+ * I have also added a dereferencing expression for the DREF() operator.
+ * Since both of them do the exact same operation, they will both be translated to the exact same
+ * entry type in the abstract syntax tree (an deref_expression_c)
+ */
/* NOTE: in section B 1.7, when configuring a program, symbolic_variable
@@ -7233,7 +7255,8 @@
/***********************/
expression:
xor_expression
-| ref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */
+| ref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */
+| deref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */
| expression OR xor_expression
{$$ = new or_expression_c($1, $3, locloc(@$));}
/* ERROR_CHECK_BEGIN */
@@ -7254,6 +7277,14 @@
{$$ = new ref_expression_c($3, locloc(@$));}
;
+/* DREF(var_name) */
+/* This is an extension to the IEC 61131-3 standard. It is actually defined in the IEC 61131-3 v3 standard */
+/* The DREF() operator accesses the variable stored in the specified address. Basically, it dereferences a pointer to the variable */
+deref_expression:
+ DREF '(' symbolic_variable ')'
+ {$$ = new deref_expression_c($3, locloc(@$));}
+;
+
xor_expression:
and_expression
| xor_expression XOR and_expression
--- a/stage1_2/iec_flex.ll Sat Sep 27 20:09:19 2014 +0100
+++ b/stage1_2/iec_flex.ll Sun Sep 28 16:35:44 2014 +0100
@@ -1252,6 +1252,7 @@
REF {if (get_opt_ref_operator()) return REF; else{REJECT;}} /* Keyword in IEC 61131-3 v3 */
+DREF {if (get_opt_ref_operator()) return DREF; else{REJECT;}} /* Keyword in IEC 61131-3 v3 */
REF_TO {if (get_opt_ref_operator()) return REF_TO; else{REJECT;}} /* Keyword in IEC 61131-3 v3 */
NULL {if (get_opt_ref_operator()) return NULL_token; else{REJECT;}} /* Keyword in IEC 61131-3 v3 */
--- a/stage3/fill_candidate_datatypes.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/stage3/fill_candidate_datatypes.cc Sun Sep 28 16:35:44 2014 +0100
@@ -1889,9 +1889,26 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
+/* SYM_REF1(deref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *fill_candidate_datatypes_c::visit(deref_expression_c *symbol) {
+ symbol->exp->accept(*this);
+
+ for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+ /* Determine whether the datatype is a ref_spec_c, as this is the class used as the */
+ /* canonical/base datatype of REF_TO types (see search_base_type_c ...) */
+ ref_spec_c *ref_spec = dynamic_cast<ref_spec_c *>(symbol->exp->candidate_datatypes[i]);
+
+ if (NULL != ref_spec)
+ add_datatype_to_candidate_list(symbol, ref_spec->type_name);
+ }
+
+ return NULL;
+}
+
+
/* SYM_REF1(ref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
void *fill_candidate_datatypes_c::visit( ref_expression_c *symbol) {
- /* We must first determine the datatype of the expression passe to the REF() operator, with no ambiguities!
+ /* We must first determine the datatype of the expression passed to the REF() operator, with no ambiguities!
* To do this, we could use the complete standard fill/narrow algorithm for determining the datatype
* of the expression. This is actually possible, as nothing stops us from directly calling the narrow_candidate_datatypes_c
* from this method inside fill_candidate_datatypes_c, to complete the fill/narrow algorithm on this
@@ -1910,9 +1927,8 @@
if (symbol->exp->candidate_datatypes.size() == 1)
symbol->exp->datatype = symbol->exp->candidate_datatypes[0];
- /* Create a new object of ref_spec_c, as this is the class used as the canonical/base datatype of REF_TO types
- * (see search_base_type_c ...)
- */
+ /* Create a new object of ref_spec_c, as this is the class used as the */
+ /* canonical/base datatype of REF_TO types (see search_base_type_c ...) */
ref_spec_c *ref_spec = new ref_spec_c(symbol->exp->datatype);
add_datatype_to_candidate_list(symbol, ref_spec);
return NULL;
--- a/stage3/fill_candidate_datatypes.hh Sat Sep 27 20:09:19 2014 +0100
+++ b/stage3/fill_candidate_datatypes.hh Sun Sep 28 16:35:44 2014 +0100
@@ -337,24 +337,25 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
- void *visit(ref_expression_c *symbol);
- void *visit(or_expression_c *symbol);
- void *visit(xor_expression_c *symbol);
- void *visit(and_expression_c *symbol);
- void *visit(equ_expression_c *symbol);
- void *visit(notequ_expression_c *symbol);
- void *visit(lt_expression_c *symbol);
- void *visit(gt_expression_c *symbol);
- void *visit(le_expression_c *symbol);
- void *visit(ge_expression_c *symbol);
- void *visit(add_expression_c *symbol);
- void *visit(sub_expression_c *symbol);
- void *visit(mul_expression_c *symbol);
- void *visit(div_expression_c *symbol);
- void *visit(mod_expression_c *symbol);
- void *visit(power_expression_c *symbol);
- void *visit(neg_expression_c *symbol);
- void *visit(not_expression_c *symbol);
+ void *visit( deref_expression_c *symbol);
+ void *visit( ref_expression_c *symbol);
+ void *visit( or_expression_c *symbol);
+ void *visit( xor_expression_c *symbol);
+ void *visit( and_expression_c *symbol);
+ void *visit( equ_expression_c *symbol);
+ void *visit( notequ_expression_c *symbol);
+ void *visit( lt_expression_c *symbol);
+ void *visit( gt_expression_c *symbol);
+ void *visit( le_expression_c *symbol);
+ void *visit( ge_expression_c *symbol);
+ void *visit( add_expression_c *symbol);
+ void *visit( sub_expression_c *symbol);
+ void *visit( mul_expression_c *symbol);
+ void *visit( div_expression_c *symbol);
+ void *visit( mod_expression_c *symbol);
+ void *visit( power_expression_c *symbol);
+ void *visit( neg_expression_c *symbol);
+ void *visit( not_expression_c *symbol);
void *visit(function_invocation_c *symbol);
/*********************************/
--- a/stage3/narrow_candidate_datatypes.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.cc Sun Sep 28 16:35:44 2014 +0100
@@ -1378,6 +1378,23 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
+/* SYM_REF1(deref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *narrow_candidate_datatypes_c::visit(deref_expression_c *symbol) {
+ for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+ /* Determine whether the datatype is a ref_spec_c, as this is the class used as the */
+ /* canonical/base datatype of REF_TO types (see search_base_type_c ...) */
+ ref_spec_c *ref_spec = dynamic_cast<ref_spec_c *>(symbol->exp->candidate_datatypes[i]);
+
+ if ((NULL != ref_spec) && get_datatype_info_c::is_type_equal(ref_spec->type_name, symbol->datatype))
+ /* if it points to the required datatype for symbol, then that is the required datatype for symbol->exp */
+ symbol->exp->datatype = ref_spec;
+ }
+
+ symbol->exp->accept(*this);
+ return NULL;
+}
+
+
/* SYM_REF1(ref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
void *narrow_candidate_datatypes_c::visit( ref_expression_c *symbol) {
if (symbol->exp->candidate_datatypes.size() > 0) {
--- a/stage3/narrow_candidate_datatypes.hh Sat Sep 27 20:09:19 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.hh Sun Sep 28 16:35:44 2014 +0100
@@ -308,25 +308,25 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
- void *visit(ref_expression_c *symbol);
- void *visit(or_expression_c *symbol);
- void *visit(xor_expression_c *symbol);
- void *visit(and_expression_c *symbol);
- void *visit(equ_expression_c *symbol);
- void *visit(notequ_expression_c *symbol);
- void *visit(lt_expression_c *symbol);
- void *visit(gt_expression_c *symbol);
- void *visit(le_expression_c *symbol);
- void *visit(ge_expression_c *symbol);
- void *visit(add_expression_c *symbol);
- void *visit(sub_expression_c *symbol);
- void *visit(mul_expression_c *symbol);
- void *visit(div_expression_c *symbol);
- void *visit(mod_expression_c *symbol);
- void *visit(power_expression_c *symbol);
- void *visit(neg_expression_c *symbol);
- void *visit(not_expression_c *symbol);
-
+ void *visit( deref_expression_c *symbol);
+ void *visit( ref_expression_c *symbol);
+ void *visit( or_expression_c *symbol);
+ void *visit( xor_expression_c *symbol);
+ void *visit( and_expression_c *symbol);
+ void *visit( equ_expression_c *symbol);
+ void *visit( notequ_expression_c *symbol);
+ void *visit( lt_expression_c *symbol);
+ void *visit( gt_expression_c *symbol);
+ void *visit( le_expression_c *symbol);
+ void *visit( ge_expression_c *symbol);
+ void *visit( add_expression_c *symbol);
+ void *visit( sub_expression_c *symbol);
+ void *visit( mul_expression_c *symbol);
+ void *visit( div_expression_c *symbol);
+ void *visit( mod_expression_c *symbol);
+ void *visit( power_expression_c *symbol);
+ void *visit( neg_expression_c *symbol);
+ void *visit( not_expression_c *symbol);
void *visit(function_invocation_c *symbol);
/*********************************/
--- a/stage3/print_datatypes_error.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/stage3/print_datatypes_error.cc Sun Sep 28 16:35:44 2014 +0100
@@ -1044,6 +1044,15 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
+/* SYM_REF1(deref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *print_datatypes_error_c::visit(deref_expression_c *symbol) {
+ symbol->exp->accept(*this);
+ /* we should really check whether the expression is merely a variable. For now, leave it for the future! */
+ if ((symbol->candidate_datatypes.size() == 0) && (symbol->exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(0, symbol, symbol, "DREF operator must be used with a value of type REF_TO.");
+ return NULL;
+}
+
/* SYM_REF1(ref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
void *print_datatypes_error_c::visit( ref_expression_c *symbol) {
symbol->exp->accept(*this);
--- a/stage3/print_datatypes_error.hh Sat Sep 27 20:09:19 2014 +0100
+++ b/stage3/print_datatypes_error.hh Sun Sep 28 16:35:44 2014 +0100
@@ -288,24 +288,25 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
- void *visit(ref_expression_c *symbol);
- void *visit(or_expression_c *symbol);
- void *visit(xor_expression_c *symbol);
- void *visit(and_expression_c *symbol);
- void *visit(equ_expression_c *symbol);
- void *visit(notequ_expression_c *symbol);
- void *visit(lt_expression_c *symbol);
- void *visit(gt_expression_c *symbol);
- void *visit(le_expression_c *symbol);
- void *visit(ge_expression_c *symbol);
- void *visit(add_expression_c *symbol);
- void *visit(sub_expression_c *symbol);
- void *visit(mul_expression_c *symbol);
- void *visit(div_expression_c *symbol);
- void *visit(mod_expression_c *symbol);
- void *visit(power_expression_c *symbol);
- void *visit(neg_expression_c *symbol);
- void *visit(not_expression_c *symbol);
+ void *visit( deref_expression_c *symbol);
+ void *visit( ref_expression_c *symbol);
+ void *visit( or_expression_c *symbol);
+ void *visit( xor_expression_c *symbol);
+ void *visit( and_expression_c *symbol);
+ void *visit( equ_expression_c *symbol);
+ void *visit( notequ_expression_c *symbol);
+ void *visit( lt_expression_c *symbol);
+ void *visit( gt_expression_c *symbol);
+ void *visit( le_expression_c *symbol);
+ void *visit( ge_expression_c *symbol);
+ void *visit( add_expression_c *symbol);
+ void *visit( sub_expression_c *symbol);
+ void *visit( mul_expression_c *symbol);
+ void *visit( div_expression_c *symbol);
+ void *visit( mod_expression_c *symbol);
+ void *visit( power_expression_c *symbol);
+ void *visit( neg_expression_c *symbol);
+ void *visit( not_expression_c *symbol);
void *visit(function_invocation_c *symbol);
/*********************************/
--- a/stage4/generate_c/generate_c.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/stage4/generate_c/generate_c.cc Sun Sep 28 16:35:44 2014 +0100
@@ -138,6 +138,11 @@
#define GET_EXTERNAL_FB_REF "__GET_EXTERNAL_FB_REF"
#define GET_LOCATED_REF "__GET_LOCATED_REF"
+#define GET_VAR_DREF "__GET_VAR_DREF"
+#define GET_EXTERNAL_DREF "__GET_EXTERNAL_DREF"
+#define GET_EXTERNAL_FB_DREF "__GET_EXTERNAL_FB_DREF"
+#define GET_LOCATED_DREF "__GET_LOCATED_DREF"
+
#define GET_VAR_BY_REF "__GET_VAR_BY_REF"
#define GET_EXTERNAL_BY_REF "__GET_EXTERNAL_BY_REF"
#define GET_EXTERNAL_FB_BY_REF "__GET_EXTERNAL_FB_BY_REF"
--- a/stage4/generate_c/generate_c_st.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/stage4/generate_c/generate_c_st.cc Sun Sep 28 16:35:44 2014 +0100
@@ -463,6 +463,48 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
+void *visit(deref_expression_c *symbol) {
+ s4o.print("(");
+ if (this->is_variable_prefix_null()) {
+ /* For code in FUNCTIONs */
+ s4o.print("*");
+ symbol->exp->accept(*this);
+ s4o.print("");
+ } else {
+ /* For code in FBs, and PROGRAMS... */
+ s4o.print("(");
+ unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_);
+ if (vartype == search_var_instance_decl_c::external_vt) {
+ if (!get_datatype_info_c::is_type_valid (symbol->exp->datatype)) ERROR;
+ if ( get_datatype_info_c::is_function_block(symbol->exp->datatype))
+ s4o.print(GET_EXTERNAL_FB_DREF);
+ else
+ s4o.print(GET_EXTERNAL_DREF);
+ }
+ else if (vartype == search_var_instance_decl_c::located_vt)
+ s4o.print(GET_LOCATED_DREF);
+ else
+ s4o.print(GET_VAR_DREF);
+
+ variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration;
+ s4o.print("(");
+ wanted_variablegeneration = complextype_base_vg;
+ print_variable_prefix();
+ symbol->exp->accept(*this);
+ s4o.print(",");
+ wanted_variablegeneration = complextype_suffix_vg;
+ symbol->exp->accept(*this);
+ s4o.print(")");
+ wanted_variablegeneration = old_wanted_variablegeneration;
+
+ s4o.print(")");
+ }
+ s4o.print(")");
+
+ return NULL;
+}
+
+
void *visit(ref_expression_c *symbol) {
s4o.print("(");
if (this->is_variable_prefix_null()) {
--- a/stage4/generate_iec/generate_iec.cc Sat Sep 27 20:09:19 2014 +0100
+++ b/stage4/generate_iec/generate_iec.cc Sun Sep 28 16:35:44 2014 +0100
@@ -1917,24 +1917,25 @@
/***********************/
/* B 3.1 - Expressions */
/***********************/
-void *visit(ref_expression_c *symbol) {return s4o.print("REF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
-void *visit(or_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " OR ");}
-void *visit(xor_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " XOR ");}
-void *visit(and_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " AND ");}
-void *visit(equ_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " = ");}
+void *visit( ref_expression_c *symbol) {return s4o.print( "REF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *visit( deref_expression_c *symbol) {return s4o.print("DREF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *visit( or_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " OR ");}
+void *visit( xor_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " XOR ");}
+void *visit( and_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " AND ");}
+void *visit( equ_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " = ");}
void *visit(notequ_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " <> ");}
-void *visit(lt_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " < ");}
-void *visit(gt_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " > ");}
-void *visit(le_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " <= ");}
-void *visit(ge_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " >= ");}
-void *visit(add_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " + ");}
-void *visit(sub_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " - ");}
-void *visit(mul_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " * ");}
-void *visit(div_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " / ");}
-void *visit(mod_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " MOD ");}
-void *visit(power_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " ** ");}
-void *visit(neg_expression_c *symbol) {return print_unary_expression(symbol, symbol->exp, "-");}
-void *visit(not_expression_c *symbol) {return print_unary_expression(symbol, symbol->exp, "NOT ");}
+void *visit( lt_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " < ");}
+void *visit( gt_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " > ");}
+void *visit( le_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " <= ");}
+void *visit( ge_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " >= ");}
+void *visit( add_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " + ");}
+void *visit( sub_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " - ");}
+void *visit( mul_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " * ");}
+void *visit( div_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " / ");}
+void *visit( mod_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " MOD ");}
+void *visit( power_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " ** ");}
+void *visit( neg_expression_c *symbol) {return print_unary_expression (symbol, symbol->exp, "-");}
+void *visit( not_expression_c *symbol) {return print_unary_expression (symbol, symbol->exp, "NOT ");}
void *visit(function_invocation_c *symbol) {
symbol->function_name->accept(*this);