From ef864ce9820080be4fac86d3e5f45eb35806802b Mon Sep 17 00:00:00 2001 From: gscalamera <graziano.scalamera@elettra.eu> Date: Wed, 22 Feb 2017 16:43:16 +0100 Subject: [PATCH] Upgraded parser to support quality, min, max, sin, cos conditional expression and string comparison --- src/Alarm.cpp | 287 ++++++++++++++++++++++++++++++++---------- src/Alarm.h | 1 - src/alarm_table.cpp | 9 -- src/alarm_table.h | 14 +-- src/event_table.cpp | 12 +- src/event_table.h | 4 +- src/formula_grammar.h | 150 +++++++++++++++++----- 7 files changed, 348 insertions(+), 129 deletions(-) diff --git a/src/Alarm.cpp b/src/Alarm.cpp index c49c801..7f3aa79 100644 --- a/src/Alarm.cpp +++ b/src/Alarm.cpp @@ -390,8 +390,18 @@ void Alarm::init_device() rule_names[formula_grammar::mult_exprID] = "MultE"; rule_names[formula_grammar::expr_atomID] = "AtomicE"; rule_names[formula_grammar::shift_exprID] = "ShiftE"; - rule_names[formula_grammar::unary_exprID] = "UnaryE"; - + rule_names[formula_grammar::unary_exprID] = "UnaryE"; + rule_names[formula_grammar::funcID] = "FunctionE"; + rule_names[formula_grammar::nameID] = "NameE"; + rule_names[formula_grammar::indexID] = "IndexE"; + rule_names[formula_grammar::val_stringID] = "ValString"; + rule_names[formula_grammar::func_dualID] = "FuncDualE"; + rule_names[formula_grammar::logical_expr_parenID] = "LogicalParenE"; + rule_names[formula_grammar::cond_exprID] = "ConditionalE"; + rule_names[formula_grammar::nonempty_exprID] = "NonEmptyE"; + rule_names[formula_grammar::exprID] = "Expression"; + rule_names[formula_grammar::val_qualityID] = "ValQuality"; + /* * get device attribute properties and initialize internal * data structures @@ -1940,13 +1950,9 @@ void Alarm::modify(Tango::DevString argin) alm.send_arg_n = false; alm.dp_n = NULL; -#ifndef _ACCESS_NODE_D - alm.formula_tree = ast_parse(alarm_string.c_str(), al_gr, space_p); //parse string s with grammar al_gr, skipping white spaces -#else alm.formula_tree = //boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp = ast_parse<factory_t>(alarm_string.begin(), alarm_string.end(), al_gr, space_p); //parse string s with grammar al_gr, skipping white spaces -#endif if (alm.formula_tree.full) { std::transform(alm.name.begin(), alm.name.end(), alm.name.begin(), (int(*)(int))tolower); //transform to lowercase @@ -1986,11 +1992,7 @@ void Alarm::modify(Tango::DevString argin) else { ostringstream o; -#ifndef _ACCESS_NODE_D - o << __func__<<": Parsing Failed, syntax error stopped at " << alm.formula_tree.stop << ends; -#else o << __func__<<": Parsing Failed, syntax error stopped at " << string(alm.formula_tree.stop, alarm_string.end()) << ends; //TODO -#endif DEBUG_STREAM << o.str() << endl; Tango::Except::throw_exception( \ (const char*)"Parsing Failed!", \ @@ -2238,13 +2240,9 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn) alm.dp_n = NULL; evn.clear(); -#ifndef _ACCESS_NODE_D - alm.formula_tree = ast_parse(alarm_string.c_str(), al_gr, space_p); //parse string s with grammar al_gr, skipping white spaces -#else alm.formula_tree = //boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp = ast_parse<factory_t>(alarm_string.begin(), alarm_string.end(), al_gr, space_p); //parse string s with grammar al_gr, skipping white spaces -#endif if (alm.formula_tree.full) { std::transform(alm.name.begin(), alm.name.end(), alm.name.begin(), (int(*)(int))tolower); //transform to lowercase @@ -2307,11 +2305,7 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn) else { ostringstream o; -#ifndef _ACCESS_NODE_D - o << "Alarm::load_alarm(): Parsing Failed, syntax error stopped at " << alm.formula_tree.stop << ends; -#else o << "Alarm::load_alarm(): Parsing Failed, syntax error stopped at " << string(alm.formula_tree.stop, alarm_string.end()) << ends; //TODO -#endif DEBUG_STREAM << o.str() << endl; Tango::Except::throw_exception( \ (const char*)"Parsing Failed!", \ @@ -2729,6 +2723,7 @@ void Alarm::do_alarm(bei_t& e) if (found != events->v_event.end()) { found->value = e.value; + found->value_string = e.value_string; found->quality = e.quality; //found->errors = e.errors; found->ex_reason = e.ex_reason; @@ -3230,44 +3225,27 @@ formula_res_t Alarm::eval_expression(iter_t const& i, string &attr_values, int e throw err.str(); } string val_st(i->value.begin(), i->value.end()); -#ifndef _ACCESS_NODE_D - Tango::DevState st; - if(val_st == "ON") - st = Tango::ON; - else if(val_st == "OFF") - st = Tango::OFF; - else if(val_st == "CLOSE") - st = Tango::CLOSE; - else if(val_st == "OPEN") - st = Tango::OPEN; - else if(val_st == "INSERT") - st = Tango::INSERT; - else if(val_st == "EXTRACT") - st = Tango::EXTRACT; - else if(val_st == "MOVING") - st = Tango::MOVING; - else if(val_st == "STANDBY") - st = Tango::STANDBY; - else if(val_st == "FAULT") - st = Tango::FAULT; - else if(val_st == "INIT") - st = Tango::INIT; - else if(val_st == "RUNNING") - st = Tango::RUNNING; - else if(val_st == "ALARM") - st = Tango::ALARM; - else if(val_st == "DISABLE") - st = Tango::DISABLE; - else if(val_st == "UNKNOWN") - st = Tango::UNKNOWN; -#else double st = i->value.value(); //get value directly from node saved with access_node_d -#endif //_ACCESS_NODE_D DEBUG_STREAM << " node value state : " << val_st << "=" << st << endl; formula_res_t res; res.value = st; return res; - } + } + else if (i->value.id() == formula_grammar::val_qualityID) + { + if(i->children.size() != 0) + { + err << "in node val_qualityID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; + throw err.str(); + } + string val_quality(i->value.begin(), i->value.end()); + + double quality = i->value.value(); //get value directly from node saved with access_node_d + DEBUG_STREAM << " node value quality : " << val_quality << "=" << quality << endl; + formula_res_t res; + res.value = quality; + return res; + } else if (i->value.id() == formula_grammar::unary_exprID) { DEBUG_STREAM << " node unary expression: " << string(i->value.begin(), i->value.end()) << endl; @@ -3371,7 +3349,7 @@ formula_res_t Alarm::eval_expression(iter_t const& i, string &attr_values, int e err << "in node nameID(" << string(i->value.begin(), i->value.end()) << ") value not valid!" << ends; throw err.str(); } - else if(it->value.empty()) + else if(it->type != Tango::DEV_STRING && it->value.empty()) { err << "in node nameID(" << string(i->value.begin(), i->value.end()) << ") value not initialized!!" << ends; throw err.str(); @@ -3538,22 +3516,92 @@ formula_res_t Alarm::eval_expression(iter_t const& i, string &attr_values, int e { err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; throw err.str(); - } - if (string(i->value.begin(), i->value.end()) == string("!=")) - { - return eval_expression(i->children.begin(), attr_values) != - eval_expression(i->children.begin()+1, attr_values); } - else if (string(i->value.begin(), i->value.end()) == string("==")) - { - return eval_expression(i->children.begin(), attr_values) == - eval_expression(i->children.begin()+1, attr_values); - } - else - { - err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends; - throw err.str(); - } + + + //string comparison here + iter_t const& i2_1 = i->children.begin(); + iter_t const& i2_2 = i->children.begin()+1; + //OK only attr == 'string' or attr != 'string' + if(i2_1->value.id() == formula_grammar::nameID && i2_2->value.id() == formula_grammar::val_stringID) + { + if(i2_1->children.size() == 0 && i2_2->children.size() == 0) + { + //retrieve string from attribute: + string attr_val = ""; + string name_id(i2_1->value.begin(), i2_1->value.end()); + std::transform(name_id.begin(), name_id.end(), name_id.begin(), (int(*)(int))tolower); //transform to lowercase + formula_res_t res; + vector<event>::iterator it = events->v_event.begin(); + + while ((it != events->v_event.end()) && (it->name != name_id)) + it++; + if (it != events->v_event.end()) + { + if(!it->valid) + { + err << "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not valid!" << ends; + throw err.str(); + } + else if(it->type != Tango::DEV_STRING && it->value.empty()) + { + err << "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not initialized!!" << ends; + throw err.str(); + } + ostringstream temp_attr_val; + temp_attr_val << it->name << "=" <<it->value_string << ";"; + attr_values += temp_attr_val.str(); + res.quality = it->quality; + res.ex_reason = it->ex_reason; + res.ex_desc = it->ex_desc; + res.ex_origin = it->ex_origin; + DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl; + attr_val = string("'") + it->value_string + string("'"); + } + else + { + err << "in event: (" << string(i->value.begin(), i->value.end()) << ") not found in event table" << ends; + throw err.str(); + } + + //retrieve string from formula + string val_string(i2_2->value.begin(), i2_2->value.end()); + + if (string(i->value.begin(), i->value.end()) == string("!=")) + { + res.value = attr_val != val_string; + return res; + } + else if (string(i->value.begin(), i->value.end()) == string("==")) + { + res.value = attr_val == val_string; + return res; + } + else + { + err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed (val_stringID)" << ends; + throw err.str(); + } + } + } + else + { + if (string(i->value.begin(), i->value.end()) == string("!=")) + { + return eval_expression(i->children.begin(), attr_values) != + eval_expression(i->children.begin()+1, attr_values); + } + else if (string(i->value.begin(), i->value.end()) == string("==")) + { + return eval_expression(i->children.begin(), attr_values) == + eval_expression(i->children.begin()+1, attr_values); + } + else + { + err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends; + throw err.str(); + } + } } else if (i->value.id() == formula_grammar::compare_exprID) { @@ -3599,9 +3647,110 @@ formula_res_t Alarm::eval_expression(iter_t const& i, string &attr_values, int e } formula_res_t res; res = eval_expression(i->children.begin(), attr_values); - res.value = fabs(res.value); - return res; //now handled only abs as function + + if (string(i->value.begin(), i->value.end()) == string("abs")) + { + res.value = fabs(res.value); + return res; + } + else if (string(i->value.begin(), i->value.end()) == string("cos")) + { + res.value = cos(res.value); + return res; + } + else if (string(i->value.begin(), i->value.end()) == string("sin")) + { + res.value = sin(res.value); + return res; + } + else if (string(i->value.begin(), i->value.end()) == string("quality")) + { + if(i->children.size() != 1) + { + err << "in node funcID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; + throw err.str(); + } + if(i->children.begin()->value.id() != formula_grammar::nameID) + { + string name_id(i->children.begin()->value.begin(), i->children.begin()->value.end()); + err << "in node funcID(" << string(i->value.begin(), i->value.end()) << ") children is not an attribute name but " << name_id << ends; + throw err.str(); + } + res.value = res.quality; + return res; + } + else + { + err << "in node funcID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends; + throw err.str(); + } } + else if (i->value.id() == formula_grammar::func_dualID) + { + DEBUG_STREAM << " node function dual: " << string(i->value.begin(), i->value.end()) << endl; + if(i->children.size() != 2) + { + err << "in node func_dualID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; + throw err.str(); + } + formula_res_t res_1=eval_expression(i->children.begin(), attr_values), + res_2=eval_expression(i->children.begin()+1, attr_values); + if (string(i->value.begin(), i->value.end()) == string("min")) + { + formula_res_t res; + res.value = min(res_1.value, res_2.value); + res.quality = res.combine_quality(res_1.quality, res_2.quality); + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + return res; + } + else if (string(i->value.begin(), i->value.end()) == string("max")) + { + formula_res_t res; + res.value = max(res_1.value, res_2.value); + res.quality = res.combine_quality(res_1.quality, res_2.quality); + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + return res; + } + else if (string(i->value.begin(), i->value.end()) == string("pow")) + { + formula_res_t res; + res.value = pow(res_1.value, res_2.value); + res.quality = res.combine_quality(res_1.quality, res_2.quality); + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + return res; + } + else + { + err << "in node func_dualID(" << string(i->value.begin(), i->value.end()) << ") value not allowed" << ends; + throw err.str(); + } + } + else if (i->value.id() == formula_grammar::cond_exprID) + { + DEBUG_STREAM << " node ternary_if expression: " << string(i->value.begin(), i->value.end()) << endl; + if(i->children.size() != 3) + { + err << "in node ternary_ifID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size() << ends; + throw err.str(); + } + formula_res_t res_1=eval_expression(i->children.begin(), attr_values); + if(res_1.value) + { + formula_res_t res = eval_expression(i->children.begin()+1, attr_values); + return res; + } + else + { + formula_res_t res = eval_expression(i->children.begin()+2, attr_values); + return res; + } + } else { DEBUG_STREAM << " node unknown id: " << string(i->value.begin(), i->value.end()) << endl; diff --git a/src/Alarm.h b/src/Alarm.h index 9bd4f81..39e2af9 100644 --- a/src/Alarm.h +++ b/src/Alarm.h @@ -42,7 +42,6 @@ #include <mysql.h> #include <boost/version.hpp> -#define _ACCESS_NODE_D 1 #if BOOST_VERSION >= 103600 #define BOOST_VER_1_36_0 1 #endif diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp index 6bdc90f..09c43dd 100644 --- a/src/alarm_table.cpp +++ b/src/alarm_table.cpp @@ -20,7 +20,6 @@ #include "log_thread.h" #include "cmd_thread.h" -#define _ACCESS_NODE_D 1 static const char __FILE__rev[] = __FILE__ " $Revision: 1.5 $"; @@ -193,11 +192,7 @@ void alarm_table::init(vector<string>& avs, vector<string> &evn, map< string,vec tmp_alm.msg.clear(); tmp_alm.lev.clear(); tmp_alm.grp=0; -#ifndef _ACCESS_NODE_D - parse_info<> info = parse(i->c_str(), al, space_p); //parse string i with grammar al, skipping white spaces -#else tree_parse_info_t info = ast_parse<factory_t>(i->begin(), i->end(), al, space_p); -#endif if (info.full) { LOG_STREAM << gettime().tv_sec << " Parsing succeeded: " << tmp_alm.name << endl; @@ -206,11 +201,7 @@ void alarm_table::init(vector<string>& avs, vector<string> &evn, map< string,vec } else { -#ifndef _ACCESS_NODE_D - LOG_STREAM << gettime().tv_sec << " Parsing failed, stopped at: " << info.stop << endl; -#else LOG_STREAM << gettime().tv_sec << " Parsing failed, stopped at: " << string(info.stop, i->end()) << ends; //TODO -#endif } if ((tmp_alm.name.empty() == false) && \ diff --git a/src/alarm_table.h b/src/alarm_table.h index 88dd24a..e829767 100644 --- a/src/alarm_table.h +++ b/src/alarm_table.h @@ -52,30 +52,18 @@ using namespace std; -//#define _ACCESS_NODE_D 1 + #if BOOST_VERSION < 103600 -#ifndef _ACCESS_NODE_D -typedef char const* iterator_t; -typedef boost::spirit::tree_match<iterator_t> parse_tree_match_t; -typedef boost::spirit::tree_parse_info<> tree_parse_info_t; -#else typedef std::string::iterator iterator_t; typedef boost::spirit::node_val_data_factory<unsigned int> factory_t; //want a modified node to contain an unsigned int value typedef boost::spirit::tree_match<iterator_t, factory_t> parse_tree_match_t; typedef boost::spirit::tree_parse_info<iterator_t, factory_t> tree_parse_info_t; -#endif -#else -#ifndef _ACCESS_NODE_D -typedef char const* iterator_t; -typedef boost::spirit::classic::tree_match<iterator_t> parse_tree_match_t; -typedef boost::spirit::classic::tree_parse_info<> tree_parse_info_t; #else typedef std::string::iterator iterator_t; typedef boost::spirit::classic::node_val_data_factory<unsigned int> factory_t; //want a modified node to contain an unsigned int value typedef boost::spirit::classic::tree_match<iterator_t, factory_t> parse_tree_match_t; typedef boost::spirit::classic::tree_parse_info<iterator_t, factory_t> tree_parse_info_t; #endif -#endif typedef parse_tree_match_t::tree_iterator iter_t; diff --git a/src/event_table.cpp b/src/event_table.cpp index 020b9fb..eeed814 100644 --- a/src/event_table.cpp +++ b/src/event_table.cpp @@ -1120,7 +1120,7 @@ void EventCallBack::push_event(Tango::EventData* ev) e.ev_name = ev->attr_name; #endif e.ts = ev->attr_value->time; - extract_values(ev->attr_value, e.value, e.type); + extract_values(ev->attr_value, e.value, e.value_string, e.type); } else { #if 0//TANGO_VER >= 711 string ev_name_str(ev->attr_name); @@ -1181,13 +1181,11 @@ void EventCallBack::push_event(Tango::EventData* ev) static_cast<Alarm_ns::Alarm *>(mydev)->evlist.push_back(e); } /* push_event() */ -void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, int &type) +void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, string &val_string, int &type) { Tango::DevState stval; vector<Tango::DevState> v_st; -#if 1//TANGO_VER >= 600 vector<Tango::DevULong> v_ulo; -#endif vector<Tango::DevUChar> v_uch; vector<Tango::DevShort> v_sh; vector<Tango::DevUShort> v_ush; @@ -1197,6 +1195,8 @@ void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<do vector<Tango::DevBoolean> v_bo; vector<Tango::DevLong64> v_lo64; vector<Tango::DevULong64> v_ulo64; + vector<string> v_string; + val_string = string(""); if (attr_value->get_type() == Tango::DEV_UCHAR) { *(attr_value) >> v_uch; @@ -1257,6 +1257,10 @@ void EventCallBack::extract_values(Tango::DeviceAttribute *attr_value, vector<do for(vector<Tango::DevULong64>::iterator it = v_ulo64.begin(); it != v_ulo64.end(); it++) val.push_back((double)(*it)); //convert all to double type = Tango::DEV_ULONG64; + } else if (attr_value->get_type() == Tango::DEV_STRING) { + *(attr_value) >> v_string; + val_string = *(v_string.begin()); //TODO: support string spectrum attrbutes + type = Tango::DEV_STRING; } else { ostringstream o; diff --git a/src/event_table.h b/src/event_table.h index d9beb8e..8e6f95e 100644 --- a/src/event_table.h +++ b/src/event_table.h @@ -49,6 +49,7 @@ class event { string devname; string attname; value_t value; /* event value */ + string value_string; //added for DevString attributes int quality; //Tango::DevErrorList errors; string ex_reason; @@ -101,6 +102,7 @@ class event { typedef struct basic_event_info_s { string ev_name; value_t value; + string value_string; int quality; //Tango::DevErrorList errors; string ex_reason; @@ -190,7 +192,7 @@ class EventCallBack : public Tango::CallBack, public Tango::LogAdapter ~EventCallBack(void); void push_event(Tango::EventData* ev); //void init(event_list* e); - void extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, int &type); + void extract_values(Tango::DeviceAttribute *attr_value, vector<double> &val, string &val_string, int &type); private: //event_list* e_ptr; Tango::DeviceImpl *mydev; diff --git a/src/formula_grammar.h b/src/formula_grammar.h index f3bc90a..5b0c94c 100644 --- a/src/formula_grammar.h +++ b/src/formula_grammar.h @@ -15,6 +15,7 @@ #ifndef FORMULA_GRAMMAR_H_ #define FORMULA_GRAMMAR_H_ +#include <boost/version.hpp> //#define BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING //test trying to have node also if formula of type (ev/ev/ev/ev) 27/02/2008 @@ -24,23 +25,25 @@ #endif #endif -#if BOOST_VERSION < 103600 +#if BOOST_VERSION < 103600 #include <boost/spirit/core.hpp> #include <boost/spirit/tree/ast.hpp> +//for ast parse trees (in tree_formula) +#include <boost/spirit/symbols/symbols.hpp> //for symbol table using namespace boost::spirit; #else #include <boost/spirit/include/classic_core.hpp> #include <boost/spirit/include/classic_ast.hpp> -using namespace boost::spirit::classic; +//for ast parse trees (in tree_formula) +#include <boost/spirit/include/classic_symbols.hpp> //for symbol table +using namespace boost::spirit::classic; #endif - //for ast parse trees (in tree_formula) -//#include <boost/spirit/symbols/symbols.hpp> //for symbol table + using namespace std; -#ifdef _ACCESS_NODE_D /*typedef char const* iterator_t; typedef node_val_data_factory<unsigned int> factory_t; typedef tree_match<iterator_t, factory_t> parse_tree_match_t; @@ -60,7 +63,7 @@ static void Assign_Stat (tree_node_t & node, const iterator_t & begin, const ite node.value.value(stat_tmp); }*/ -unsigned int stat_tmp; +static unsigned int stat_tmp; struct Save_Stat { void operator () (unsigned int val) const @@ -77,9 +80,19 @@ struct Assign_Stat } }; -#endif //_ACCESS_NODE_D struct formula_grammar : public grammar<formula_grammar> { + + /*formula_t &m_formula; + + symbols<unsigned int> sym_grp; + + formula_grammar(formula_t &f) \ + : m_formula(f) + { + + }*/ + static const int val_rID = 1; static const int val_hID = 2; static const int val_stID = 3; @@ -96,8 +109,16 @@ struct formula_grammar : public grammar<formula_grammar> static const int expr_atomID = 14; static const int shift_exprID = 15; static const int unary_exprID = 16; + static const int val_stringID = 17; //TODO: OK ? + static const int func_dualID = 18; + static const int logical_expr_parenID = 19; + static const int cond_exprID = 20; + static const int exprID = 21; + static const int nonempty_exprID = 22; + static const int val_qualityID = 23; - symbols<unsigned int> tango_states; + symbols<unsigned int> tango_states; + symbols<unsigned int> attr_quality; formula_grammar() { @@ -115,6 +136,12 @@ struct formula_grammar : public grammar<formula_grammar> tango_states.add("ALARM", (unsigned int)Tango::ALARM); tango_states.add("DISABLE", (unsigned int)Tango::DISABLE); tango_states.add("UNKNOWN", (unsigned int)Tango::UNKNOWN); + + attr_quality.add("ATTR_VALID", (unsigned int)Tango::ATTR_VALID); + attr_quality.add("ATTR_INVALID", (unsigned int)Tango::ATTR_INVALID); + attr_quality.add("ATTR_ALARM", (unsigned int)Tango::ATTR_ALARM); + attr_quality.add("ATTR_CHANGING", (unsigned int)Tango::ATTR_CHANGING); + attr_quality.add("ATTR_WARNING", (unsigned int)Tango::ATTR_WARNING); } template <typename ScannerT> @@ -139,7 +166,7 @@ struct formula_grammar : public grammar<formula_grammar> definition(formula_grammar const& self) { symbol - = (alnum_p | '.' | '_' | '-' | '+') //any alpha numeric char plus '.', '_', '-', '+' + = (alnum_p | '.' | '_' | '-' | '+') //any alpha numeric char plus '.', '_', '-' ; //------------------------------ALARM NAME-------------------------------------- name @@ -176,21 +203,45 @@ struct formula_grammar : public grammar<formula_grammar> ; val_st = -#ifndef _ACCESS_NODE_D - token_node_d[self.tango_states] //match only group defined in sym_grp symbol table -#else //access_node_d[self.tango_states[&Save_Stat]][&Assign_Stat] //save Tango::state value in node access_node_d[self.tango_states[Save_Stat()]][Assign_Stat()] //save Tango::state value in node -#endif //_ACCESS_NODE_D + ; + val_quality + = + //access_node_d[self.tango_states[&Save_Stat]][&Assign_Stat] //save Tango::state value in node + access_node_d[self.attr_quality[Save_Stat()]][Assign_Stat()] //save Tango::state value in node + ; + val_string +#if BOOST_VERSION < 103600 + = token_node_d[ +#else + = reduced_node_d[ +#endif + lexeme_d[ //to conserve white spaces + ch_p('\'') + >> (+(anychar_p - '\'')) //one ore more char except '"' + >> '\'' + ] + ] +// = repeat_p(3)[(+symbol) >> ch_p('/')] >> (+symbol) ; event_ = name >> !(index) ; - - top = logical_expr - ; + + /*top = ternary_if; + + ternary_if + = logical_expr_paren + >> !(root_node_d[str_p("?")] >> logical_expr_paren >> discard_node_d[ch_p(':')] >> logical_expr_paren) + ;*/ + + cond_expr = logical_expr >> *(root_node_d[ch_p('?')] >> cond_expr >> discard_node_d[ch_p(':')] >> cond_expr); + + /*top = logical_expr + ;*/ logical_expr = bitwise_expr @@ -235,36 +286,64 @@ struct formula_grammar : public grammar<formula_grammar> ) ; mult_expr - = expr_atom - >> *( (root_node_d[ch_p('*')] >> expr_atom) - | (root_node_d[ch_p('/')] >> expr_atom) + = unary_expr + >> *( (root_node_d[ch_p('*')] >> unary_expr) + | (root_node_d[ch_p('/')] >> unary_expr) ) ; - function - = root_node_d[str_p("abs")] >> (inner_node_d[ch_p('(') >> logical_expr >> ')']) - ; + unary_expr - = ( (root_node_d[ch_p('+')] >> expr_atom) + = ( expr_atom + | function + | function_dual + | (root_node_d[ch_p('+')] >> expr_atom) | (root_node_d[ch_p('-')] >> expr_atom) | (root_node_d[ch_p('!')] >> expr_atom) + // | (root_node_d[ch_p('~')] >> expr_atom) //TODO + ) + ; + + function + = ( root_node_d[str_p("abs")] >> (inner_node_d[ch_p('(') >> cond_expr >> ')']) //TODO: ? not expr_atom ? + | root_node_d[str_p("cos")] >> (inner_node_d[ch_p('(') >> cond_expr >> ')']) //TODO: ? not expr_atom ? + | root_node_d[str_p("sin")] >> (inner_node_d[ch_p('(') >> cond_expr >> ')']) //TODO: ? not expr_atom ? + | root_node_d[str_p("quality")] >> (inner_node_d[ch_p('(') >> name >> ')']) //TODO: ? not expr_atom ? ) ; + function_dual + = ( (root_node_d[str_p("max")] >> (inner_node_d[ch_p('(') >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> ')'])) + //| (root_node_d[str_p("max")] >> (inner_node_d[ch_p('(') >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> discard_node_d[ch_p(',')] >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> ')'])) + | (root_node_d[str_p("min")] >> (inner_node_d[ch_p('(') >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> ')'])) + //| (root_node_d[str_p("min")] >> (inner_node_d[ch_p('(') >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> discard_node_d[ch_p(',')] >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> ')'])) + | (root_node_d[str_p("pow")] >> (inner_node_d[ch_p('(') >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> ')'])) + ) + //= *( (root_node_d[str_p("max")] >> (inner_node_d[ch_p('(') >> logical_expr_paren >> discard_node_d[ch_p(',')] >> logical_expr_paren >> ')'])) + // | (root_node_d[str_p("min")] >> (inner_node_d[ch_p('(') >> logical_expr_paren >> discard_node_d[ch_p(',')] >> logical_expr_paren >> ')'])) + //| (root_node_d[str_p("min")] >> (discard_node_d[ch_p('(')] >> logical_expr_paren >> discard_node_d[ch_p(',')] >> logical_expr_paren >> discard_node_d[ch_p(',')])) + //| (root_node_d[str_p("min")] >> (ch_p('(') >> expr_atom >> ch_p(',') >> expr_atom >> ch_p(','))) + //) + ; + + non_empty_expression = cond_expr; + top = non_empty_expression | epsilon_p; + // top = non_empty_expression; + expr_atom - = //val_h | val_r + = //val_h | val_r event_ - | unary_expr - | val_h | val_r | val_st - | function - //| (inner_node_d[ch_p('(') >> logical_expr >> ')']) - | (discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')]) - | unary_expr - + | val_h | val_r | val_st | val_quality | val_string + //| (inner_node_d[ch_p('(') >> non_empty_expression >> ')']) + | (discard_node_d[ch_p('(')] >> non_empty_expression >> discard_node_d[ch_p(')')]) + ; + logical_expr_paren + = (discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')]) + | logical_expr ; } rule<ScannerT> top; //rule<ScannerT> symbol; - rule<typename lexeme_scanner<ScannerT>::type> symbol; //neede to use lexeme_d in rule name + rule<typename lexeme_scanner<ScannerT>::type> symbol; //needed to use lexeme_d in rule name rule<ScannerT, parser_context<>, parser_tag<val_rID> > val_r; rule<ScannerT, parser_context<>, parser_tag<val_hID> > val_h; rule<ScannerT, parser_context<>, parser_tag<val_stID> > val_st; @@ -281,6 +360,13 @@ struct formula_grammar : public grammar<formula_grammar> rule<ScannerT, parser_context<>, parser_tag<funcID> > function; rule<ScannerT, parser_context<>, parser_tag<nameID> > name; rule<ScannerT, parser_context<>, parser_tag<indexID> > index; + rule<ScannerT, parser_context<>, parser_tag<val_stringID> > val_string; + rule<ScannerT, parser_context<>, parser_tag<func_dualID> > function_dual; + rule<ScannerT, parser_context<>, parser_tag<logical_expr_parenID> > logical_expr_paren; + rule<ScannerT, parser_context<>, parser_tag<cond_exprID> > cond_expr; + rule<ScannerT, parser_context<>, parser_tag<nonempty_exprID> > non_empty_expression; + rule<ScannerT, parser_context<>, parser_tag<exprID> > expression; + rule<ScannerT, parser_context<>, parser_tag<val_qualityID> > val_quality; rule<ScannerT> const& start() const { return top; } -- GitLab