CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/HLTrigger/HLTcore/interface/TriggerExpressionParser.h

Go to the documentation of this file.
00001 #ifndef HLTrigger_HLTfilters_TriggerExpressionParser_h
00002 #define HLTrigger_HLTfilters_TriggerExpressionParser_h
00003 
00004 // Note: this requires Boost 1.41 or higher, for Spirit 2.1 or higher
00005 #include <boost/spirit/include/phoenix.hpp>
00006 #include <boost/spirit/include/qi.hpp>
00007 
00008 #include "HLTrigger/HLTcore/interface/TriggerExpressionHLTReader.h"
00009 #include "HLTrigger/HLTcore/interface/TriggerExpressionL1Reader.h"
00010 #include "HLTrigger/HLTcore/interface/TriggerExpressionL1TechReader.h"
00011 #include "HLTrigger/HLTcore/interface/TriggerExpressionOperators.h"
00012 #include "HLTrigger/HLTcore/interface/TriggerExpressionPrescaler.h"
00013 #include "HLTrigger/HLTcore/interface/TriggerExpressionConstant.h"
00014 
00015 namespace triggerExpression {
00016 
00017 namespace qi = boost::spirit::qi;
00018 namespace ascii = boost::spirit::ascii;
00019 
00020 using boost::phoenix::new_;
00021 using boost::spirit::unused_type;
00022 
00023 template <typename Iterator>
00024 class Parser : public qi::grammar<Iterator, Evaluator*(), ascii::space_type>
00025 {
00026 public:
00027   Parser() : 
00028     Parser::base_type(expression)
00029   {
00030     token_hlt       %= qi::raw[qi::lexeme["HLT_"    >> +(qi::char_("a-zA-Z0-9_*?"))]];
00031     token_alca      %= qi::raw[qi::lexeme["AlCa_"   >> +(qi::char_("a-zA-Z0-9_*?"))]];
00032     token_dqm       %= qi::raw[qi::lexeme["DQM_"    >> +(qi::char_("a-zA-Z0-9_*?"))]];
00033     token_dst       %= qi::raw[qi::lexeme["DST_"    >> +(qi::char_("a-zA-Z0-9_*?"))]];
00034     token_step      %= qi::raw[qi::lexeme["generation_step"]];
00035     token_l1        %= qi::raw[qi::lexeme["L1_"     >> +(qi::char_("a-zA-Z0-9_*?"))]];
00036     token_l1tech    %= qi::raw[qi::lexeme["L1Tech_" >> +(qi::char_("a-zA-Z0-9_*?"))]];
00037 
00038     token            = ( token_hlt                      [qi::_val = new_<HLTReader>(qi::_1)]
00039                        | token_alca                     [qi::_val = new_<HLTReader>(qi::_1)]
00040                        | token_dqm                      [qi::_val = new_<HLTReader>(qi::_1)]
00041                        | token_dst                      [qi::_val = new_<HLTReader>(qi::_1)]
00042                        | token_step                     [qi::_val = new_<HLTReader>(qi::_1)]
00043                        | token_l1                       [qi::_val = new_<L1Reader>(qi::_1)]
00044                        | token_l1tech                   [qi::_val = new_<L1TechReader>(qi::_1)]
00045                        | qi::lit("TRUE")                [qi::_val = new_<Constant>(true)]
00046                        | qi::lit("FALSE")               [qi::_val = new_<Constant>(false)]
00047                        );
00048 
00049     parenthesis     %= ('(' >> expression >> ')');
00050 
00051     element         %= (token | parenthesis);
00052 
00053     prescale         = (element >> '/' >> qi::uint_)    [qi::_val = new_<Prescaler> (qi::_1, qi::_2)];
00054 
00055     operand         %= (prescale | element);
00056 
00057     unary            = ( operand                        [qi::_val = qi::_1]
00058                        | (qi::lit("NOT") >> operand)    [qi::_val = new_<OperatorNot> (qi::_1)]
00059                        );
00060 
00061     expression       = unary                            [qi::_val = qi::_1] 
00062                        >> *(
00063                               (qi::lit("AND") >> unary) [qi::_val = new_<OperatorAnd> (qi::_val, qi::_1)] 
00064                             | (qi::lit("OR")  >> unary) [qi::_val = new_<OperatorOr>  (qi::_val, qi::_1)] 
00065                        );
00066   }
00067 
00068 private:
00069   typedef qi::rule<Iterator, unused_type(), ascii::space_type> void_rule;
00070   typedef qi::rule<Iterator, std::string(), ascii::space_type> name_rule;
00071   typedef qi::rule<Iterator, Evaluator*(),  ascii::space_type> rule;
00072 
00073   name_rule token_hlt;
00074   name_rule token_alca;
00075   name_rule token_dqm;
00076   name_rule token_dst;
00077   name_rule token_step;
00078   name_rule token_l1;
00079   name_rule token_l1tech;
00080 
00081   rule token;
00082   rule parenthesis;
00083   rule element;
00084   rule prescale;
00085   rule operand;
00086   rule unary;
00087   rule expression;
00088 };
00089 
00090 
00091 // generic interface for string-like objects
00092 template <class T>
00093 Evaluator * parse(const T & text) {
00094   typedef typename T::const_iterator Iterator;
00095   Parser<Iterator> parser;
00096   Evaluator * evaluator = 0;
00097 
00098   Iterator begin = text.begin();
00099   Iterator end   = text.end();
00100 
00101   // the interface of qi::phrase_parse has changed between Boost 1.40 (Spirit 2.0) and Boost 1.41 (Spirit 2.1)
00102   bool result = qi::phrase_parse( begin, end, parser, ascii::space, evaluator );
00103 
00104   if (not result or begin != end) {
00105     delete evaluator;
00106     return 0;
00107   }
00108 
00109   return evaluator;
00110 }
00111 
00112 // overloaded interface for null-terminated strings
00113 inline Evaluator * parse(const char * text) {
00114   Parser<const char *> parser;
00115   Evaluator * evaluator = 0;
00116 
00117   const char * begin = text;
00118   const char * end   = text + strlen(text);
00119 
00120   // the interface of qi::phrase_parse has changed between Boost 1.40 (Spirit 2.0) and Boost 1.41 (Spirit 2.1)
00121   bool result = qi::phrase_parse( begin, end, parser, ascii::space, evaluator );
00122 
00123   if (not result or begin != end) {
00124     delete evaluator;
00125     return 0;
00126   }
00127 
00128   return evaluator;
00129 }
00130 
00131 } // namespace triggerExpression
00132 
00133 #endif // HLTrigger_HLTfilters_TriggerExpressionParser_h