LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-mfextensions/ErrorHandler/MessageAnalyzer - ma_parse.cpp (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 0.0 % 134 0
Test Date: 2025-09-04 00:45:34 Functions: 0.0 % 25 0

            Line data    Source code
       1              : 
       2              : #include "ErrorHandler/MessageAnalyzer/ma_parse.h"
       3              : 
       4              : #include "ErrorHandler/MessageAnalyzer/ma_types.h"
       5              : 
       6              : #include "ErrorHandler/MessageAnalyzer/ma_boolean_andexpr.h"
       7              : #include "ErrorHandler/MessageAnalyzer/ma_boolean_cond.h"
       8              : #include "ErrorHandler/MessageAnalyzer/ma_boolean_expr.h"
       9              : 
      10              : #include "ErrorHandler/MessageAnalyzer/ma_domain_andexpr.h"
      11              : #include "ErrorHandler/MessageAnalyzer/ma_domain_cond.h"
      12              : #include "ErrorHandler/MessageAnalyzer/ma_domain_expr.h"
      13              : 
      14              : #include "ErrorHandler/MessageAnalyzer/ma_cond_test_andexpr.h"
      15              : #include "ErrorHandler/MessageAnalyzer/ma_cond_test_expr.h"
      16              : #include "ErrorHandler/MessageAnalyzer/ma_cond_test_primary.h"
      17              : 
      18              : #include "ErrorHandler/MessageAnalyzer/ma_rule.h"
      19              : 
      20              : #include <boost/any.hpp>
      21              : #include <boost/spirit/include/phoenix_bind.hpp>
      22              : #include <boost/spirit/include/phoenix_core.hpp>
      23              : #include <boost/spirit/include/phoenix_operator.hpp>
      24              : #include <boost/spirit/include/qi.hpp>
      25              : 
      26              : namespace ascii = ::boost::spirit::ascii;
      27              : namespace phx = ::boost::phoenix;
      28              : namespace qi = ::boost::spirit::qi;
      29              : namespace ql = ::boost::spirit::qi::labels;
      30              : 
      31              : using ascii::char_;
      32              : using ascii::digit;
      33              : using ascii::graph;
      34              : using ascii::no_case;
      35              : using ascii::space;
      36              : 
      37              : using phx::ref;
      38              : // using phx::bind;
      39              : 
      40              : using qi::bool_;
      41              : using qi::double_;
      42              : using qi::eol;
      43              : using qi::int_;
      44              : using qi::lexeme;
      45              : using qi::lit;
      46              : using qi::locals;
      47              : using qi::no_skip;
      48              : using qi::raw;
      49              : using qi::skip;
      50              : 
      51              : // using namespace qi::labels;
      52              : 
      53              : using novadaq::errorhandler::CO_E;
      54              : using novadaq::errorhandler::CO_G;
      55              : using novadaq::errorhandler::CO_GE;
      56              : using novadaq::errorhandler::CO_L;
      57              : using novadaq::errorhandler::CO_LE;
      58              : using novadaq::errorhandler::CO_NE;
      59              : using novadaq::errorhandler::compare_op_t;
      60              : using novadaq::errorhandler::cond_arg_t;
      61              : using novadaq::errorhandler::cond_idx_t;
      62              : using novadaq::errorhandler::ma_boolean_andexpr;
      63              : using novadaq::errorhandler::ma_boolean_cond;
      64              : using novadaq::errorhandler::ma_boolean_expr;
      65              : using novadaq::errorhandler::ma_cond_test_andexpr;
      66              : using novadaq::errorhandler::ma_cond_test_expr;
      67              : using novadaq::errorhandler::ma_cond_test_primary;
      68              : using novadaq::errorhandler::ma_condition;
      69              : using novadaq::errorhandler::ma_domain_andexpr;
      70              : using novadaq::errorhandler::ma_domain_cond;
      71              : using novadaq::errorhandler::ma_domain_expr;
      72              : using novadaq::errorhandler::ma_rule;
      73              : using novadaq::errorhandler::NONE;
      74              : using novadaq::errorhandler::SOURCE;
      75              : using novadaq::errorhandler::TARGET;
      76              : 
      77              : // ------------------------------------------------------------------
      78              : 
      79              : namespace novadaq {
      80              : namespace errorhandler {
      81              : template<class FwdIter, class Skip>
      82              : struct domain_expr_parser;
      83              : 
      84              : template<class FwdIter, class Skip>
      85              : struct boolean_expr_parser;
      86              : 
      87              : template<class FwdIter, class Skip>
      88              : struct cond_test_expr_parser;
      89              : 
      90              : class ma_rule;
      91              : }  // namespace errorhandler
      92              : }  // namespace novadaq
      93              : 
      94              : // ------------------------------------------------------------------
      95              : 
      96              : static void
      97            0 : insert_domain_andexpr(ma_domain_expr& expr, ma_domain_andexpr const& andexpr)
      98              : {
      99            0 :         expr.insert_andexpr(andexpr);
     100            0 : }
     101              : 
     102              : static void
     103            0 : insert_domain_cond(ma_domain_andexpr& andexpr, ma_domain_cond const& cond)
     104              : {
     105            0 :         andexpr.insert_cond(cond);
     106            0 : }
     107              : 
     108              : static void
     109            0 : insert_domain_expr(ma_domain_cond& cond, ma_domain_expr const& expr)
     110              : {
     111            0 :         cond.insert_expr(expr);
     112            0 : }
     113              : 
     114              : static void
     115            0 : insert_cond_arg(ma_domain_cond& cond, std::string const& name, char arg, ma_rule* rule)
     116              : {
     117              :         // update condition's notification list
     118            0 :         rule->update_notify_list(name, (arg == 's') ? SOURCE : TARGET);
     119              : 
     120              :         // push the condition ptr into domain_cond
     121            0 :         cond.insert_cond_arg(rule->get_cond_idx(name), (arg == 's') ? SOURCE : TARGET, rule->get_cond_size());
     122            0 : }
     123              : 
     124              : static void
     125            0 : insert_str_cond(ma_domain_cond& cond, std::string const& str)
     126              : {
     127            0 :         cond.insert_str_cond(str);
     128            0 : }
     129              : 
     130              : // ------------------------------------------------------------------
     131              : 
     132              : template<class FwdIter, class Skip>
     133              : struct novadaq::errorhandler::domain_expr_parser
     134              :     : qi::grammar<FwdIter, ma_domain_expr(), Skip>
     135              : {
     136              :         // default c'tor
     137              :         domain_expr_parser(ma_rule* rule);
     138              : 
     139              :         // data member
     140              :         qi::rule<FwdIter, ma_domain_expr(), Skip> domain_expr;
     141              :         qi::rule<FwdIter, ma_domain_andexpr(), Skip> domain_andexpr;
     142              :         qi::rule<FwdIter, ma_domain_cond(), locals<std::string>, Skip> domain_cond;
     143              : 
     144              :         qi::rule<FwdIter, std::string(), Skip> key;
     145              :         qi::rule<FwdIter, std::string(), Skip> keywords;
     146              :         qi::rule<FwdIter, std::string(), Skip> str;
     147              : };
     148              : 
     149              : // ------------------------------------------------------------------
     150              : 
     151              : template<class FwdIter, class Skip>
     152            0 : novadaq::errorhandler::domain_expr_parser<FwdIter, Skip>::domain_expr_parser(ma_rule* rule)
     153            0 :     : domain_expr_parser::base_type(domain_expr)
     154              : {
     155            0 :         domain_expr =
     156            0 :             domain_andexpr[phx::bind(&insert_domain_andexpr, ql::_val, ql::_1)] % "OR";
     157              : 
     158            0 :         domain_andexpr =
     159            0 :             domain_cond[phx::bind(&insert_domain_cond, ql::_val, ql::_1)] % "AND";
     160              : 
     161            0 :         domain_cond =
     162            0 :             (lit('(') >> domain_expr[phx::bind(&insert_domain_expr, ql::_val, ql::_1)] >> lit(')'))  // '(' >> expr >> ')'
     163            0 :             |
     164              :             ((
     165              :                  (
     166            0 :                      key[ql::_a = ql::_1] >> ".$" >> char_("st")
     167            0 :                                                          [phx::bind(&insert_cond_arg, ql::_val, ql::_a, ql::_1, rule)]) %
     168            0 :                  '=') >>
     169            0 :              -('=' >> (str[phx::bind(&insert_str_cond, ql::_val, ql::_1)] | "ANY")))  // cond1.$x = cond2.$y = ... -( = "str_cond" )
     170              :                                                                                       // cond1.$x = cond2.$y = ... -( = ANY )
     171              :             ;
     172              : 
     173            0 :         keywords = no_case["AND"] | no_case["OR"] | no_case["ANY"];
     174              : 
     175            0 :         key = qi::lexeme[char_("a-zA-Z_") >> *char_("a-zA-Z_0-9")] - keywords;
     176              :         ;
     177              : 
     178            0 :         str = qi::lexeme['\'' >> +(ascii::char_ - '\'') >> '\''];
     179            0 : }
     180              : 
     181              : // ------------------------------------------------------------------
     182              : 
     183              : static void
     184            0 : insert_boolean_andexpr(ma_boolean_expr& expr, ma_boolean_andexpr const& andexpr)
     185              : {
     186            0 :         expr.insert(andexpr);
     187            0 : }
     188              : 
     189              : static void
     190            0 : insert_boolean_cond(ma_boolean_andexpr& andexpr, ma_boolean_cond const& cond)
     191              : {
     192            0 :         andexpr.insert(cond);
     193            0 : }
     194              : 
     195              : static void
     196            0 : insert_boolean_expr(ma_boolean_cond& cond, ma_boolean_expr const& expr)
     197              : {
     198            0 :         cond.insert_expr(expr);
     199            0 : }
     200              : 
     201              : static void
     202            0 : insert_primitive_cond(ma_boolean_cond& cond, std::string const& name, ma_rule* rule)
     203              : {
     204              :         // 1. first insert the condition ptr to the corresponding rule
     205              :         //    such that the condition has an index in the rule
     206              :         //    NOTE* that the insertion of condition ptr only happens when
     207              :         //          parsing the boolean expression
     208              :         // 2. then insert the (ptr, idx) pair to the boolean_cond
     209            0 :         cond.insert_cond(rule->insert_condition_ptr(name, true));
     210            0 : }
     211              : 
     212              : static void
     213            0 : insert_ext_func(ma_boolean_cond& cond, std::string const& function, std::string const& name, char cond_arg, std::vector<boost::any> const& func_args, ma_rule* rule)
     214              : {
     215            0 :         cond.insert_ext_func(rule->insert_condition_ptr(name, false /*non-primitive*/), (cond_arg == 's') ? SOURCE : ((cond_arg == 't') ? TARGET : NONE), func_args, function);
     216            0 : }
     217              : 
     218              : static void
     219            0 : insert_compare_op_double(ma_boolean_cond& cond, compare_op_t op, double rhv)
     220              : {
     221            0 :         cond.insert_compare_op_double(op, rhv);
     222            0 : }
     223              : 
     224              : static void
     225            0 : insert_compare_op_bool(ma_boolean_cond& cond, compare_op_t op, bool rhv)
     226              : {
     227            0 :         if ((op != CO_E) && (op != CO_NE))
     228            0 :                 throw std::runtime_error("error in parsing rule: booleans can only use == or !=");
     229              : 
     230            0 :         cond.insert_compare_op_bool(op, rhv);
     231            0 : }
     232              : 
     233              : static void
     234            0 : insert_compare_op_string(ma_boolean_cond& cond, compare_op_t op, std::string rhv)
     235              : {
     236            0 :         cond.insert_compare_op_string(op, rhv);
     237            0 : }
     238              : 
     239              : // ------------------------------------------------------------------
     240              : 
     241              : using boost::any;
     242              : typedef std::vector<any> anys;
     243              : 
     244              : template<class FwdIter, class Skip>
     245              : struct novadaq::errorhandler::boolean_expr_parser
     246              :     : qi::grammar<FwdIter, ma_boolean_expr(), Skip>
     247              : {
     248              :         // default c'tor
     249              :         boolean_expr_parser(ma_rule* rule);
     250              : 
     251              :         // data member
     252              :         qi::rule<FwdIter, ma_boolean_expr(), Skip> boolean_expr;
     253              :         qi::rule<FwdIter, ma_boolean_andexpr(), Skip> boolean_andexpr;
     254              :         qi::rule<FwdIter, ma_boolean_cond(), locals<std::string, char, compare_op_t, std::string, anys>, Skip> boolean_cond;
     255              : 
     256              :         qi::rule<FwdIter, std::string(), Skip> key;
     257              :         qi::rule<FwdIter, std::string(), Skip> str;
     258              :         qi::rule<FwdIter, std::string(), Skip> keywords;
     259              :         qi::rule<FwdIter, compare_op_t(), Skip> compare_op;
     260              : 
     261              :         qi::rule<FwdIter, any(), Skip> arg;
     262              :         qi::rule<FwdIter, anys(), Skip> args;
     263              : };
     264              : 
     265              : // ------------------------------------------------------------------
     266              : 
     267              : template<class FwdIter, class Skip>
     268            0 : novadaq::errorhandler::boolean_expr_parser<FwdIter, Skip>::boolean_expr_parser(ma_rule* rule)
     269            0 :     : boolean_expr_parser::base_type(boolean_expr)
     270              : {
     271            0 :         boolean_expr =
     272            0 :             boolean_andexpr[phx::bind(&insert_boolean_andexpr, ql::_val, ql::_1)] % "||";
     273              : 
     274            0 :         boolean_andexpr =
     275            0 :             boolean_cond[phx::bind(&insert_boolean_cond, ql::_val, ql::_1)] % "&&";
     276              : 
     277            0 :         boolean_cond =
     278            0 :             (lit('(') >> boolean_expr[phx::bind(&insert_boolean_expr, ql::_val, ql::_1)] >> ')')  // '(' >> expr >> ')'
     279            0 :             |
     280            0 :             (key[ql::_a = ql::_1] >> lit('(') >> key[ql::_d = ql::_1] >> -(".$" >> char_("st")[ql::_b = ql::_1]) >> -(',' >> args[ql::_e = ql::_1]) >> lit(')')[phx::bind(&insert_ext_func, ql::_val, ql::_a, ql::_d, ql::_b, ql::_e, rule)]
     281              : 
     282            0 :              >> -(compare_op[ql::_c = ql::_1] >> (double_[phx::bind(&insert_compare_op_double, ql::_val, ql::_c, ql::_1)] | bool_[phx::bind(&insert_compare_op_bool, ql::_val, ql::_c, ql::_1)] | str[phx::bind(&insert_compare_op_string, ql::_val, ql::_c, ql::_1)])))  // custom_function(cond.$st)
     283            0 :             |
     284            0 :             key[phx::bind(&insert_primitive_cond, ql::_val, ql::_1, rule)]
     285              :             // Cond
     286              :             ;
     287              : 
     288            0 :         args = (arg % ',');
     289              : 
     290            0 :         arg = double_[ql::_val = ql::_1] | bool_[ql::_val = ql::_1] | str[ql::_val = ql::_1];
     291              : 
     292            0 :         keywords = no_case["AND"] | no_case["OR"];
     293              : 
     294            0 :         key = qi::lexeme[char_("a-zA-Z_") >> *char_("a-zA-Z_0-9")] - keywords;
     295              : 
     296            0 :         str = qi::lexeme['\'' >> +(char_ - '\'') >> '\''];
     297              : 
     298            0 :         compare_op = lit("==")[ql::_val = CO_E] | lit("!=")[ql::_val = CO_NE] | lit("<=")[ql::_val = CO_LE] | lit(">=")[ql::_val = CO_GE] | lit("<")[ql::_val = CO_L] | lit(">")[ql::_val = CO_G];
     299            0 : }
     300              : 
     301              : // ------------------------------------------------------------------
     302              : 
     303              : static void
     304            0 : set_boolean_expr(ma_boolean_expr& expr, ma_rule* rule)
     305              : {
     306            0 :         rule->set_boolean_expr(expr);
     307            0 : }
     308              : 
     309              : static void
     310            0 : set_domain_expr(ma_domain_expr& expr, ma_rule* rule)
     311              : {
     312            0 :         rule->set_domain_expr(expr);
     313            0 : }
     314              : 
     315              : // ------------------------------------------------------------------
     316              : 
     317            0 : bool novadaq::errorhandler::parse_condition_expr(std::string const& s, ma_rule* rule)
     318              : {
     319              :         typedef std::string::const_iterator iter_t;
     320              :         typedef ascii::space_type ws_t;
     321              : 
     322            0 :         boolean_expr_parser<iter_t, ws_t> boolean_p(rule);
     323            0 :         domain_expr_parser<iter_t, ws_t> domain_p(rule);
     324              : 
     325            0 :         iter_t begin = s.begin();
     326            0 :         iter_t const end = s.end();
     327              : 
     328            0 :         bool b = qi::phrase_parse(
     329            0 :                      begin, end, boolean_p[phx::bind(&set_boolean_expr, ql::_1, rule)] >> -("WHERE" >> domain_p[phx::bind(&set_domain_expr, ql::_1, rule)]), space) &&
     330            0 :                  begin == end;
     331              : 
     332            0 :         return b;
     333            0 : }
     334              : 
     335              : // ------------------------------------------------------------------
     336              : //  Condition test expression parser
     337              : // ------------------------------------------------------------------
     338              : 
     339              : static void
     340            0 : insert_test_primary(ma_cond_test_andexpr& andexpr, ma_cond_test_primary const& primary)
     341              : {
     342            0 :         andexpr.insert(primary);
     343            0 : }
     344              : 
     345              : static void
     346            0 : insert_test_andexpr(ma_cond_test_expr& expr, ma_cond_test_andexpr const& andexpr)
     347              : {
     348            0 :         expr.insert(andexpr);
     349            0 : }
     350              : 
     351              : static void
     352            0 : insert_test_expr(ma_cond_test_primary& primary, ma_cond_test_expr const& expr)
     353              : {
     354            0 :         primary.insert_expr(expr);
     355            0 : }
     356              : 
     357              : static void
     358            0 : insert_test_func(ma_cond_test_primary& primary, std::string const& function, std::vector<boost::any> const& func_args)
     359              : {
     360            0 :         primary.insert_func(function, func_args);
     361            0 : }
     362              : 
     363              : static void
     364            0 : insert_test_compare_op(ma_cond_test_primary& primary, compare_op_t op, boost::any const& rhv)
     365              : {
     366            0 :         primary.insert_compare_op(op, rhv);
     367            0 : }
     368              : 
     369              : // ------------------------------------------------------------------
     370              : 
     371              : template<typename T>
     372              : struct strict_real_policies : qi::real_policies<T>
     373              : {
     374              :         static bool const expect_dot = true;
     375              : };
     376              : 
     377              : template<class FwdIter, class Skip>
     378              : struct novadaq::errorhandler::cond_test_expr_parser
     379              :     : qi::grammar<FwdIter, ma_cond_test_expr(), Skip>
     380              : {
     381              :         // default c'tor
     382              :         cond_test_expr_parser();
     383              : 
     384              :         // data member
     385              :         qi::rule<FwdIter, ma_cond_test_expr(), Skip> test_expr;
     386              :         qi::rule<FwdIter, ma_cond_test_andexpr(), Skip> test_andexpr;
     387              :         qi::rule<FwdIter, ma_cond_test_primary(), locals<std::string, anys_t, compare_op_t>, Skip> test_primary;
     388              : 
     389              :         qi::rule<FwdIter, std::string(), Skip> key;
     390              :         qi::rule<FwdIter, std::string(), Skip> str;
     391              :         qi::rule<FwdIter, std::string(), Skip> keywords;
     392              :         qi::rule<FwdIter, compare_op_t(), Skip> compare_op;
     393              : 
     394              :         qi::rule<FwdIter, any(), Skip> value;
     395              :         qi::rule<FwdIter, anys(), Skip> values;
     396              : 
     397              :         qi::real_parser<double, strict_real_policies<double> > real;
     398              : };
     399              : 
     400              : // ------------------------------------------------------------------
     401              : 
     402              : template<class FwdIter, class Skip>
     403            0 : novadaq::errorhandler::cond_test_expr_parser<FwdIter, Skip>::cond_test_expr_parser()
     404            0 :     : cond_test_expr_parser::base_type(test_expr)
     405              : {
     406            0 :         test_expr =
     407            0 :             test_andexpr[phx::bind(&insert_test_andexpr, ql::_val, ql::_1)] % "||";
     408              : 
     409            0 :         test_andexpr =
     410            0 :             test_primary[phx::bind(&insert_test_primary, ql::_val, ql::_1)] % "&&";
     411              : 
     412            0 :         test_primary =
     413            0 :             (lit('(') >> test_expr[phx::bind(&insert_test_expr, ql::_val, ql::_1)] >> lit(')')) |
     414            0 :             (key[ql::_a = ql::_1] >> lit('(') >> -values[ql::_b = ql::_1] >> lit(')')[phx::bind(&insert_test_func, ql::_val, ql::_a, ql::_b)] >> -(compare_op[ql::_c = ql::_1] >> value[phx::bind(&insert_test_compare_op, ql::_val, ql::_c, ql::_1)]));
     415              : 
     416            0 :         values = (value % ',');
     417              : 
     418            0 :         value = (int_[ql::_val = ql::_1] >> !char_(".eE")) | double_[ql::_val = ql::_1] | bool_[ql::_val = ql::_1] | str[ql::_val = ql::_1];
     419              : 
     420            0 :         keywords = no_case["AND"] | no_case["OR"];
     421              : 
     422            0 :         key = qi::lexeme[char_("a-zA-Z_") >> *char_("a-zA-Z_0-9")] - keywords;
     423              : 
     424            0 :         str = qi::lexeme['\'' >> +(char_ - '\'') >> '\''];
     425              : 
     426            0 :         compare_op = lit("==")[ql::_val = CO_E] | lit("!=")[ql::_val = CO_NE] | lit("<=")[ql::_val = CO_LE] | lit(">=")[ql::_val = CO_GE] | lit("<")[ql::_val = CO_L] | lit(">")[ql::_val = CO_G];
     427            0 : }
     428              : 
     429              : // ------------------------------------------------------------------
     430              : 
     431            0 : bool novadaq::errorhandler::parse_condition_test(std::string const& s, ma_cond_test_expr& expr)
     432              : {
     433              :         typedef std::string::const_iterator iter_t;
     434              :         typedef ascii::space_type ws_t;
     435              : 
     436            0 :         if (s.empty()) return true;
     437              : 
     438            0 :         cond_test_expr_parser<iter_t, ws_t> test_p;
     439              : 
     440            0 :         iter_t begin = s.begin();
     441            0 :         iter_t const end = s.end();
     442              : 
     443            0 :         bool b = qi::phrase_parse(begin, end, test_p, space, expr) && begin == end;
     444              : 
     445            0 :         return b;
     446            0 : }
        

Generated by: LCOV version 2.0-1