# HG changeset patch # User mjsousa # Date 1406825384 -3600 # Node ID 8da635655f3746732e113cc815dd7009b209b3e2 # Parent e9bde0aa93ed2d3251984232596dc239605adb9f Add support for the 'NULL' keyword, defined in version 3 of IEC 61131-3. diff -r e9bde0aa93ed -r 8da635655f37 absyntax/absyntax.def --- a/absyntax/absyntax.def Tue Jul 29 13:39:40 2014 +0100 +++ b/absyntax/absyntax.def Thu Jul 31 17:49:44 2014 +0100 @@ -130,6 +130,11 @@ /*********************/ /* B 1.2 - Constants */ /*********************/ +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ +SYM_REF0(ref_value_null_literal_c) /******************************/ /* B 1.2.1 - Numeric Literals */ diff -r e9bde0aa93ed -r 8da635655f37 absyntax_utils/get_datatype_info.cc --- a/absyntax_utils/get_datatype_info.cc Tue Jul 29 13:39:40 2014 +0100 +++ b/absyntax_utils/get_datatype_info.cc Thu Jul 31 17:49:44 2014 +0100 @@ -248,9 +248,13 @@ (typeid(*first_type) == typeid(*second_type))) {return true;} /* ANY_DERIVED */ - if (is_ref_to(first_type) && is_ref_to(second_type)) - return is_type_equal(search_base_type_c::get_basetype_decl(get_ref_to(first_type )), - search_base_type_c::get_basetype_decl(get_ref_to(second_type))); + if (is_ref_to(first_type) && is_ref_to(second_type)) { + /* if either of them is the constant 'NULL' then we consider them 'equal', as NULL is compatible to a REF_TO any datatype! */ + if (typeid(* first_type) == typeid(ref_value_null_literal_c)) {return true;} + if (typeid(*second_type) == typeid(ref_value_null_literal_c)) {return true;} + return is_type_equal(search_base_type_c::get_basetype_decl(get_ref_to(first_type )), + search_base_type_c::get_basetype_decl(get_ref_to(second_type))); + } return (first_type == second_type); } @@ -295,6 +299,7 @@ if (typeid(*type_decl) == typeid(ref_type_decl_c)) {return true;} /* identifier ':' ref_spec_init */ if (typeid(*type_decl) == typeid(ref_spec_init_c)) {return true;} /* ref_spec [ ASSIGN ref_initialization ]; */ if (typeid(*type_decl) == typeid(ref_spec_c)) {return true;} /* REF_TO (non_generic_type_name | function_block_type_name) */ + if (typeid(*type_decl) == typeid(ref_value_null_literal_c)) {return true;} /* REF_TO (non_generic_type_name | function_block_type_name) */ return false; } diff -r e9bde0aa93ed -r 8da635655f37 absyntax_utils/search_base_type.cc --- a/absyntax_utils/search_base_type.cc Tue Jul 29 13:39:40 2014 +0100 +++ b/absyntax_utils/search_base_type.cc Thu Jul 31 17:49:44 2014 +0100 @@ -133,6 +133,12 @@ /*********************/ /* B 1.2 - Constants */ /*********************/ +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ +/* See the comment in fill_candidate_datatypes_c::visit(ref_value_null_literal_c) for reason why we use this symbol as a datatype! */ +void *search_base_type_c::visit(ref_value_null_literal_c *symbol) {return (void *)symbol;} /******************************/ /* B 1.2.1 - Numeric Literals */ diff -r e9bde0aa93ed -r 8da635655f37 absyntax_utils/search_base_type.hh --- a/absyntax_utils/search_base_type.hh Tue Jul 29 13:39:40 2014 +0100 +++ b/absyntax_utils/search_base_type.hh Thu Jul 31 17:49:44 2014 +0100 @@ -94,6 +94,12 @@ /*********************/ /* B 1.2 - Constants */ /*********************/ + /*********************************/ + /* B 1.2.XX - Reference Literals */ + /*********************************/ + /* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ + void *visit(ref_value_null_literal_c *symbol); + /******************************/ /* B 1.2.1 - Numeric Literals */ /******************************/ diff -r e9bde0aa93ed -r 8da635655f37 stage1_2/iec_bison.yy --- a/stage1_2/iec_bison.yy Tue Jul 29 13:39:40 2014 +0100 +++ b/stage1_2/iec_bison.yy Thu Jul 31 17:49:44 2014 +0100 @@ -414,9 +414,10 @@ %type en_identifier %type eno_identifier -/* Keyword in IEC 61131-3 v3 */ +/* Keywords in IEC 61131-3 v3 */ %token REF %token REF_TO +%token NULL_token /* cannot use simply 'NULL', as it conflicts with the NULL keyword in C++ */ @@ -445,6 +446,23 @@ %type constant %type non_int_or_real_constant +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* NOTE: The following syntax was added by MJS in order to add support for the NULL keyword, defined in IEC 61131-3 v3 + * In v3 expressions that reduce to a reference datatype (REF_TO) are handled explicitly in the syntax + * (e.g., any variable that is a of reference datatpe falls under the 'ref_name' rule), which means + * that we would need to keep track of which variables are declared as REF_TO. + * In order to reduce the changes to the current IEC 61131-3 v2 syntax, I have opted not to do this, + * and simply let the ref_expressions (Ref_Assign, Ref_Compare) be interpreted as all other standard expressions + * in v2. However, ref_expressions allow the use of the 'NULL' constant, which is handled explicitly + * in the ref_expressions syntax of v3. + * To allow the use of the 'NULL' constant in this extended v2, I have opted to interpret this 'NULL' constant + * as a literal. + */ +%type ref_value_null_literal /* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ + + /******************************/ /* B 1.2.1 - Numeric Literals */ /******************************/ @@ -1777,6 +1795,7 @@ * rules, is not defined in the spec! * We therefore replaced unsigned_integer as integer */ +| ref_value_null_literal /* defined in IEC 61131-3 v3. Basically the 'NULL' keyword! */ ; @@ -1808,6 +1827,16 @@ */ ; +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* NOTE: The following syntax was added by MJS in order to add support for the NULL keyword, defined in IEC 61131-3 v3 + * Please read the comment where the 'ref_value_null_literal' is declared as a + */ +/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ +ref_value_null_literal: + NULL_token {$$ = new ref_value_null_literal_c(locloc(@$));} +; /******************************/ /* B 1.2.1 - Numeric Literals */ diff -r e9bde0aa93ed -r 8da635655f37 stage1_2/iec_flex.ll --- a/stage1_2/iec_flex.ll Tue Jul 29 13:39:40 2014 +0100 +++ b/stage1_2/iec_flex.ll Thu Jul 31 17:49:44 2014 +0100 @@ -1251,8 +1251,9 @@ /******************************************************/ -REF {if (get_opt_ref_operator()) return REF; 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 */ +REF {if (get_opt_ref_operator()) return REF; 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 */ EN return EN; /* Keyword */ ENO return ENO; /* Keyword */ diff -r e9bde0aa93ed -r 8da635655f37 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Tue Jul 29 13:39:40 2014 +0100 +++ b/stage3/fill_candidate_datatypes.cc Thu Jul 31 17:49:44 2014 +0100 @@ -662,13 +662,15 @@ /* handle the two equality comparison operations, i.e. = (euqal) and != (not equal) */ /* This function is special, as it will also allow enumeration data types to be compared, with the result being a BOOL data type! - * This possibility os not expressed in the 'widening' tables, so we need to hard code it here + * It will also allow to REF_TO datatypes to be compared. + * These possibilities are not expressed in the 'widening' tables, so we need to hard code it here */ void *fill_candidate_datatypes_c::handle_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr) { handle_binary_expression(widen_table, symbol, l_expr, r_expr); for(unsigned int i = 0; i < l_expr->candidate_datatypes.size(); i++) for(unsigned int j = 0; j < r_expr->candidate_datatypes.size(); j++) { - if ((l_expr->candidate_datatypes[i] == r_expr->candidate_datatypes[j]) && get_datatype_info_c::is_enumerated(l_expr->candidate_datatypes[i])) + if ( (get_datatype_info_c::is_enumerated(l_expr->candidate_datatypes[i]) && (l_expr->candidate_datatypes[i] == r_expr->candidate_datatypes[j])) + || (get_datatype_info_c::is_ref_to (l_expr->candidate_datatypes[i]) && get_datatype_info_c::is_type_equal(l_expr->candidate_datatypes[i], r_expr->candidate_datatypes[j]))) add_datatype_to_candidate_list(symbol, &get_datatype_info_c::bool_type_name); } return NULL; @@ -689,15 +691,48 @@ /***************************/ /* main entry function! */ void *fill_candidate_datatypes_c::visit(library_c *symbol) { - symbol->accept(populate_globalenumvalue_symtable); - /* Now let the base class iterator_visitor_c iterate through all the library elements */ - return iterator_visitor_c::visit(symbol); + symbol->accept(populate_globalenumvalue_symtable); + /* Now let the base class iterator_visitor_c iterate through all the library elements */ + return iterator_visitor_c::visit(symbol); } /*********************/ /* B 1.2 - Constants */ /*********************/ +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ +void *fill_candidate_datatypes_c::visit(ref_value_null_literal_c *symbol) { + /* 'NULL' does not have any specific datatype. It is compatible with any reference, i.e. REF_TO + * The fill_candidate_datatypes / narrow_candidate_datatypes algorithm would require us to add + * as possible datatypes all the REF_TO . To do this we would need to go through the list of all + * user declared datatypes, as well as all the elementary datatypes. This is easily done by using the + * type_symtable symbol table declared in absyntax_utils.hh. + * + * for(int i=0; il_exp->accept(*this); symbol->r_exp->accept(*this); for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) { @@ -2009,7 +2043,7 @@ left_type = symbol->l_exp->candidate_datatypes[i]; right_type = symbol->r_exp->candidate_datatypes[j]; if (get_datatype_info_c::is_type_equal(left_type, right_type)) - add_datatype_to_candidate_list(symbol, left_type); + add_datatype_to_candidate_list(symbol, left_type); // NOTE: Must use left_type, as the right_type may be the 'NULL' reference! (see comment in visit(ref_value_null_literal_c)) */ } } if (debug) std::cout << ":= [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; diff -r e9bde0aa93ed -r 8da635655f37 stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Tue Jul 29 13:39:40 2014 +0100 +++ b/stage3/fill_candidate_datatypes.hh Thu Jul 31 17:49:44 2014 +0100 @@ -121,6 +121,12 @@ /*********************/ /* B 1.2 - Constants */ /*********************/ + /*********************************/ + /* B 1.2.XX - Reference Literals */ + /*********************************/ + /* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ + void *visit(ref_value_null_literal_c *symbol); + /******************************/ /* B 1.2.1 - Numeric Literals */ /******************************/ diff -r e9bde0aa93ed -r 8da635655f37 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Tue Jul 29 13:39:40 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Thu Jul 31 17:49:44 2014 +0100 @@ -1412,7 +1412,10 @@ l_expr->datatype = l_type; r_expr->datatype = r_type; count ++; - } else if ((l_type == r_type) && get_datatype_info_c::is_enumerated(l_type) && get_datatype_info_c::is_BOOL_compatible(symbol->datatype)) { + } else if ( /* handle the special case of enumerations */ + (get_datatype_info_c::is_BOOL_compatible(symbol->datatype) && get_datatype_info_c::is_enumerated(l_type) && (l_type == r_type)) + /* handle the special case of comparison between REF_TO datatypes */ + || (get_datatype_info_c::is_BOOL_compatible(symbol->datatype) && get_datatype_info_c::is_ref_to (l_type) && get_datatype_info_c::is_type_equal(l_type, r_type))) { if (NULL != deprecated_operation) *deprecated_operation = false; l_expr->datatype = l_type; r_expr->datatype = r_type; diff -r e9bde0aa93ed -r 8da635655f37 stage4/generate_c/generate_c_base.cc --- a/stage4/generate_c/generate_c_base.cc Tue Jul 29 13:39:40 2014 +0100 +++ b/stage4/generate_c/generate_c_base.cc Thu Jul 31 17:49:44 2014 +0100 @@ -303,6 +303,12 @@ /*********************/ /* originally empty... */ +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ + void *visit(ref_value_null_literal_c *symbol) {s4o.print("NULL"); return NULL;} + /******************************/ /* B 1.2.1 - Numeric Literals */ /******************************/ diff -r e9bde0aa93ed -r 8da635655f37 stage4/generate_iec/generate_iec.cc --- a/stage4/generate_iec/generate_iec.cc Tue Jul 29 13:39:40 2014 +0100 +++ b/stage4/generate_iec/generate_iec.cc Thu Jul 31 17:49:44 2014 +0100 @@ -258,6 +258,11 @@ /*********************/ /* B 1.2 - Constants */ /*********************/ +/*********************************/ +/* B 1.2.XX - Reference Literals */ +/*********************************/ +/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */ +void *visit(ref_value_null_literal_c *symbol) {s4o.print("NULL"); return NULL;} /******************************/ /* B 1.2.1 - Numeric Literals */ @@ -276,7 +281,7 @@ void *visit(boolean_literal_c *symbol) {return print_literal(symbol->type, symbol->value);} /* helper class for boolean_literal_c */ -void *visit(boolean_true_c *symbol) {s4o.print(/*"TRUE"*/"1"); return NULL;} +void *visit(boolean_true_c *symbol) {s4o.print(/*"TRUE" */"1"); return NULL;} void *visit(boolean_false_c *symbol) {s4o.print(/*"FALSE"*/"0"); return NULL;} /*******************************/