/* * formula_grammar.h * * $Author: graziano $ * * $Revision: 1.5 $ * * $Log: formula_grammar.h,v $ * * * copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale * Strada Statale 14 - km 163,5 in AREA Science Park * 34012 Basovizza, Trieste ITALY */ #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 #if BOOST_VERSION < 103600 #ifndef BOOST_SPIRIT_THREADSAFE #define BOOST_SPIRIT_THREADSAFE #endif #endif #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> //for ast parse trees (in tree_formula) #include <boost/spirit/include/classic_symbols.hpp> //for symbol table using namespace boost::spirit::classic; #endif using namespace std; /*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; typedef tree_parse_info<iterator_t, factory_t> tree_parse_t; typedef parse_tree_match_t::tree_iterator iter_t;*/ typedef node_val_data<iterator_t, unsigned int> node_t; typedef tree_node<node_t> tree_node_t; /*static unsigned int stat_tmp; static void Save_Stat (unsigned int val) { stat_tmp = val; } static void Assign_Stat (tree_node_t & node, const iterator_t & begin, const iterator_t & end) { node.value.value(stat_tmp); }*/ static unsigned int stat_tmp; struct Save_Stat { void operator () (unsigned int val) const { stat_tmp = val; } }; struct Assign_Stat { void operator () (tree_node_t & node, const iterator_t & begin, const iterator_t & end) const { node.value.value(stat_tmp); } }; //TODO: duplicated from alarm.h enum _AlarmStateEnum { _NORM, _UNACK, _ACKED, _RTNUN, _SHLVD, _DSUPR, _OOSRV, _ERROR } ; static vector<string> quality_labels = {"ATTR_VALID","ATTR_INVALID","ATTR_ALARM","ATTR_CHANGING","ATTR_WARNING"}; 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; static const int event_ID = 4; static const int nameID = 5; static const int indexID = 6; static const int funcID = 7; static const int logical_exprID = 8; static const int bitwise_exprID = 9; static const int equality_exprID = 10; static const int compare_exprID = 11; static const int add_exprID = 12; static const int mult_exprID = 13; 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; static const int val_alarm_enum_stID = 24; static const int propertyID = 25; symbols<unsigned int> tango_states; symbols<unsigned int> attr_quality; symbols<unsigned int> alarm_enum_states; formula_grammar() { tango_states.add("ON", (unsigned int)Tango::ON); tango_states.add("OFF", (unsigned int)Tango::OFF); tango_states.add("CLOSE", (unsigned int)Tango::CLOSE); tango_states.add("OPEN", (unsigned int)Tango::OPEN); tango_states.add("INSERT", (unsigned int)Tango::INSERT); tango_states.add("EXTRACT", (unsigned int)Tango::EXTRACT); tango_states.add("MOVING", (unsigned int)Tango::MOVING); tango_states.add("STANDBY", (unsigned int)Tango::STANDBY); tango_states.add("FAULT", (unsigned int)Tango::FAULT); tango_states.add("INIT", (unsigned int)Tango::INIT); tango_states.add("RUNNING", (unsigned int)Tango::RUNNING); 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); alarm_enum_states.add("NORM", (unsigned int)_NORM); alarm_enum_states.add("UNACK", (unsigned int)_UNACK); alarm_enum_states.add("ACKED", (unsigned int)_ACKED); alarm_enum_states.add("RTNUN", (unsigned int)_RTNUN); alarm_enum_states.add("SHLVD", (unsigned int)_SHLVD); alarm_enum_states.add("DSUPR", (unsigned int)_DSUPR); alarm_enum_states.add("OOSRV", (unsigned int)_OOSRV); alarm_enum_states.add("ERROR", (unsigned int)_ERROR); } template <typename ScannerT> struct definition { /* typedef scanner< typename ScannerT::iterator_t, scanner_policies< typename ScannerT::iteration_policy_t, ast_match_policy< typename ScannerT::match_policy_t::iterator_t, typename ScannerT::match_policy_t::factory_t >, typename ScannerT::action_policy_t > > ast_scanner;*/ //typedef scanner_list< ScannerT, phrase_scanner_t > scanners; //try using multiple scanners definition(formula_grammar const& self) { symbol = (alnum_p | '.' | '_' | '-' | '+') //any alpha numeric char plus '.', '_', '-' ; symbol_attr = (alnum_p | '_' | '.') //any alpha numeric char plus '_', '.' for attribute names ; //------------------------------ALARM NAME-------------------------------------- name #if BOOST_VERSION < 103600 = token_node_d[ #else = reduced_node_d[ #endif lexeme_d[ //needed to ignore "space_p" (skip white spaces) evaluating name !("tango://" >> (+symbol) >> ':' >> uint_p >> "/") //eventually match FQDN >> (+symbol) >> '/' >> (+symbol) >> '/' >> (+symbol) >> '/' >> (+symbol_attr) ] ] // = repeat_p(3)[(+symbol) >> ch_p('/')] >> (+symbol) ; index = inner_node_d[ch_p('[') >> uint_p >> ch_p(']')] ; property = str_p(".quality") | str_p(".alarm") | str_p(".normal") ; //------------------------------FORMULA-------------------------------------- val_r #if BOOST_VERSION < 103600 = leaf_node_d[real_p] #else = reduced_node_d[real_p] #endif ; val_h #if BOOST_VERSION < 103600 = token_node_d[(str_p("0x") >> hex_p)] //token_node_d here to create only one node with all chars #else = reduced_node_d[(str_p("0x") >> hex_p)] //token_node_d here to create only one node with all chars #endif ; val_st = //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 ; val_quality = //access_node_d[self.attr_quality[&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_alarm_enum_st = //access_node_d[self.alarm_enum_states[&Save_Stat]][&Assign_Stat] //save Tango::state value in node access_node_d[self.alarm_enum_states[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) | (property) ) ; /*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 >> *( (root_node_d[str_p("&&")] >> bitwise_expr) | (root_node_d[str_p("||")] >> bitwise_expr) ) ; bitwise_expr = equality_expr >> *( (root_node_d[ch_p('&')] >> equality_expr) | (root_node_d[ch_p('|')] >> equality_expr) | (root_node_d[ch_p('^')] >> equality_expr) ) ; equality_expr = compare_expr >> *( (root_node_d[str_p("==")] >> compare_expr) | (root_node_d[str_p("!=")] >> compare_expr) ) ; compare_expr = shift_expr >> *( (root_node_d[str_p("<=")] >> add_expr) | (root_node_d[str_p(">=")] >> add_expr) | (root_node_d[ch_p('<')] >> add_expr) | (root_node_d[ch_p('>')] >> add_expr) ) ; shift_expr = add_expr >> *( (root_node_d[str_p("<<")] >> add_expr) | (root_node_d[str_p(">>")] >> add_expr) ) ; add_expr = mult_expr >> *( (root_node_d[ch_p('+')] >> mult_expr) | (root_node_d[ch_p('-')] >> mult_expr) ) ; mult_expr = unary_expr >> *( (root_node_d[ch_p('*')] >> unary_expr) | (root_node_d[ch_p('/')] >> unary_expr) ) ; unary_expr = ( 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")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ? | root_node_d[str_p("cos")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ? | root_node_d[str_p("sin")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ? | root_node_d[str_p("quality")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ? | root_node_d[str_p("AND")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ? | root_node_d[str_p("OR")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ? ) ; function_dual = ( (root_node_d[str_p("max")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> discard_node_d[ch_p(')')])) //| (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")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> discard_node_d[ch_p(')')])) //| (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")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> discard_node_d[ch_p(')')])) ) //= *( (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 event_ | val_h | val_r | val_st | val_quality | val_alarm_enum_st | 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; //needed to use lexeme_d in rule name rule<typename lexeme_scanner<ScannerT>::type> symbol_attr; //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; rule<ScannerT, parser_context<>, parser_tag<event_ID> > event_; rule<ScannerT, parser_context<>, parser_tag<logical_exprID> > logical_expr; rule<ScannerT, parser_context<>, parser_tag<bitwise_exprID> > bitwise_expr; rule<ScannerT, parser_context<>, parser_tag<shift_exprID> > shift_expr; rule<ScannerT, parser_context<>, parser_tag<equality_exprID> > equality_expr; rule<ScannerT, parser_context<>, parser_tag<compare_exprID> > compare_expr; rule<ScannerT, parser_context<>, parser_tag<add_exprID> > add_expr; rule<ScannerT, parser_context<>, parser_tag<mult_exprID> > mult_expr; rule<ScannerT, parser_context<>, parser_tag<unary_exprID> > unary_expr; rule<ScannerT, parser_context<>, parser_tag<expr_atomID> > expr_atom; 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, parser_context<>, parser_tag<val_alarm_enum_stID> > val_alarm_enum_st; rule<ScannerT, parser_context<>, parser_tag<propertyID> > property; rule<ScannerT> const& start() const { return top; } }; }; #endif /*FORMULA_GRAMMAR_H_*/