Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:18:24

0001 #ifndef HLTrigger_HLTcore_TriggerExpressionParser_h
0002 #define HLTrigger_HLTcore_TriggerExpressionParser_h
0003 
0004 // Note: this requires Boost 1.41 or higher, for Spirit 2.1 or higher
0005 #include <boost/phoenix.hpp>
0006 #include <boost/spirit/include/qi.hpp>
0007 
0008 #include "HLTrigger/HLTcore/interface/TriggerExpressionPathReader.h"
0009 #include "HLTrigger/HLTcore/interface/TriggerExpressionL1uGTReader.h"
0010 #include "HLTrigger/HLTcore/interface/TriggerExpressionOperators.h"
0011 #include "HLTrigger/HLTcore/interface/TriggerExpressionPrescaler.h"
0012 #include "HLTrigger/HLTcore/interface/TriggerExpressionConstant.h"
0013 
0014 namespace triggerExpression {
0015 
0016   namespace qi = boost::spirit::qi;
0017   namespace ascii = boost::spirit::ascii;
0018 
0019   using boost::phoenix::new_;
0020   using boost::spirit::unused_type;
0021 
0022   template <typename Iterator>
0023   class Parser : public qi::grammar<Iterator, Evaluator *(), ascii::space_type> {
0024   public:
0025     Parser() : Parser::base_type(expression) {
0026       auto delimiter = qi::copy(qi::eoi | !qi::char_("a-zA-Z0-9_*?"));
0027 
0028       operand_not = qi::lexeme[qi::lit("NOT") >> delimiter];
0029       operand_and = qi::lexeme[qi::lit("AND") >> delimiter];
0030       operand_or = qi::lexeme[qi::lit("OR") >> delimiter];
0031       operand_xor = qi::lexeme[qi::lit("XOR") >> delimiter];
0032       operand_masking = qi::lexeme[qi::lit("MASKING") >> delimiter];
0033 
0034       // "TRUE": keyword to accept all events
0035       token_true = qi::lexeme[qi::lit("TRUE") >> delimiter];
0036 
0037       // "FALSE": keyword to reject all events
0038       token_false = qi::lexeme[qi::lit("FALSE") >> delimiter];
0039 
0040       // Level-1 Global Trigger decisions: must begin with characters "L1_"
0041       token_l1algo %= qi::raw[qi::lexeme["L1_" >> +(qi::char_("a-zA-Z0-9_*?"))]];
0042 
0043       // Decisions of Paths in the CMSSW configuration (e.g. high-level triggers):
0044       // any alphanumeric pattern except for "TRUE", "FALSE", "NOT", "AND", "OR", "XOR" and "MASKING"
0045       token_path %= qi::raw[qi::lexeme[+(qi::char_("a-zA-Z0-9_*?"))] - token_true - token_false - operand_not -
0046                             operand_and - operand_or - operand_xor - operand_masking];
0047 
0048       token = (token_true[qi::_val = new_<Constant>(true)] | token_false[qi::_val = new_<Constant>(false)] |
0049                token_l1algo[qi::_val = new_<L1uGTReader>(qi::_1)] | token_path[qi::_val = new_<PathReader>(qi::_1)]);
0050 
0051       parenthesis %= ('(' >> expression >> ')');
0052 
0053       element %= (token | parenthesis);
0054 
0055       prescale = (element >> '/' >> qi::uint_)[qi::_val = new_<Prescaler>(qi::_1, qi::_2)];
0056 
0057       operand %= (prescale | element);
0058 
0059       unary = ((operand_not >> unary)[qi::_val = new_<OperatorNot>(qi::_1)] | operand[qi::_val = qi::_1]);
0060 
0061       // token_masking is used to restrict the argument (rhs) of the "MASKING"
0062       // operation to Constant[FALSE], L1uGTReader and PathReader evaluators
0063       token_masking =
0064           (token_false[qi::_val = new_<Constant>(false)] | token_l1algo[qi::_val = new_<L1uGTReader>(qi::_1)] |
0065            token_path[qi::_val = new_<PathReader>(qi::_1)]);
0066 
0067       argument_masking %= (token_masking | ('(' >> argument_masking >> ')'));
0068 
0069       expression = unary[qi::_val = qi::_1] >>
0070                    *((operand_and >> unary)[qi::_val = new_<OperatorAnd>(qi::_val, qi::_1)] |
0071                      (operand_or >> unary)[qi::_val = new_<OperatorOr>(qi::_val, qi::_1)] |
0072                      (operand_xor >> unary)[qi::_val = new_<OperatorXor>(qi::_val, qi::_1)] |
0073                      (operand_masking >> argument_masking)[qi::_val = new_<OperatorMasking>(qi::_val, qi::_1)]);
0074     }
0075 
0076   private:
0077     typedef qi::rule<Iterator, std::string(), ascii::space_type> name_rule;
0078     typedef qi::rule<Iterator, Evaluator *(), ascii::space_type> rule;
0079     typedef qi::rule<Iterator> terminal_rule;
0080 
0081     terminal_rule token_true;
0082     terminal_rule token_false;
0083 
0084     terminal_rule operand_not;
0085     terminal_rule operand_and;
0086     terminal_rule operand_or;
0087     terminal_rule operand_xor;
0088     terminal_rule operand_masking;
0089 
0090     name_rule token_l1algo;
0091     name_rule token_path;
0092 
0093     rule token;
0094     rule parenthesis;
0095     rule element;
0096     rule prescale;
0097     rule operand;
0098     rule unary;
0099     rule token_masking;
0100     rule argument_masking;
0101     rule expression;
0102   };
0103 
0104   // generic interface for string-like objects
0105   template <class T>
0106   Evaluator *parse(const T &text) {
0107     typedef typename T::const_iterator Iterator;
0108     Parser<Iterator> parser;
0109     Evaluator *evaluator = nullptr;
0110 
0111     Iterator begin = text.begin();
0112     Iterator end = text.end();
0113 
0114     // the interface of qi::phrase_parse has changed between Boost 1.40 (Spirit 2.0) and Boost 1.41 (Spirit 2.1)
0115     bool result = qi::phrase_parse(begin, end, parser, ascii::space, evaluator);
0116 
0117     if (not result or begin != end) {
0118       delete evaluator;
0119       return nullptr;
0120     }
0121 
0122     return evaluator;
0123   }
0124 
0125   // overloaded interface for null-terminated strings
0126   inline Evaluator *parse(const char *text) {
0127     Parser<const char *> parser;
0128     Evaluator *evaluator = nullptr;
0129 
0130     const char *begin = text;
0131     const char *end = text + strlen(text);
0132 
0133     // the interface of qi::phrase_parse has changed between Boost 1.40 (Spirit 2.0) and Boost 1.41 (Spirit 2.1)
0134     bool result = qi::phrase_parse(begin, end, parser, ascii::space, evaluator);
0135 
0136     if (not result or begin != end) {
0137       delete evaluator;
0138       return nullptr;
0139     }
0140 
0141     return evaluator;
0142   }
0143 
0144 }  // namespace triggerExpression
0145 
0146 #endif  // HLTrigger_HLTcore_TriggerExpressionParser_h