1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#ifndef HLTrigger_HLTcore_TriggerExpressionParser_h
#define HLTrigger_HLTcore_TriggerExpressionParser_h
// Note: this requires Boost 1.41 or higher, for Spirit 2.1 or higher
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include "HLTrigger/HLTcore/interface/TriggerExpressionPathReader.h"
#include "HLTrigger/HLTcore/interface/TriggerExpressionL1uGTReader.h"
#include "HLTrigger/HLTcore/interface/TriggerExpressionOperators.h"
#include "HLTrigger/HLTcore/interface/TriggerExpressionPrescaler.h"
#include "HLTrigger/HLTcore/interface/TriggerExpressionConstant.h"
namespace triggerExpression {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::new_;
using boost::spirit::unused_type;
template <typename Iterator>
class Parser : public qi::grammar<Iterator, Evaluator *(), ascii::space_type> {
public:
Parser() : Parser::base_type(expression) {
auto delimiter = qi::copy(qi::eoi | !qi::char_("a-zA-Z0-9_*?"));
operand_not = qi::lexeme[qi::lit("NOT") >> delimiter];
operand_and = qi::lexeme[qi::lit("AND") >> delimiter];
operand_or = qi::lexeme[qi::lit("OR") >> delimiter];
operand_xor = qi::lexeme[qi::lit("XOR") >> delimiter];
operand_masking = qi::lexeme[qi::lit("MASKING") >> delimiter];
// "TRUE": keyword to accept all events
token_true = qi::lexeme[qi::lit("TRUE") >> delimiter];
// "FALSE": keyword to reject all events
token_false = qi::lexeme[qi::lit("FALSE") >> delimiter];
// Level-1 Global Trigger decisions: must begin with characters "L1_"
token_l1algo %= qi::raw[qi::lexeme["L1_" >> +(qi::char_("a-zA-Z0-9_*?"))]];
// Decisions of Paths in the CMSSW configuration (e.g. high-level triggers):
// any alphanumeric pattern except for "TRUE", "FALSE", "NOT", "AND", "OR", "XOR" and "MASKING"
token_path %= qi::raw[qi::lexeme[+(qi::char_("a-zA-Z0-9_*?"))] - token_true - token_false - operand_not -
operand_and - operand_or - operand_xor - operand_masking];
token = (token_true[qi::_val = new_<Constant>(true)] | token_false[qi::_val = new_<Constant>(false)] |
token_l1algo[qi::_val = new_<L1uGTReader>(qi::_1)] | token_path[qi::_val = new_<PathReader>(qi::_1)]);
parenthesis %= ('(' >> expression >> ')');
element %= (token | parenthesis);
prescale = (element >> '/' >> qi::uint_)[qi::_val = new_<Prescaler>(qi::_1, qi::_2)];
operand %= (prescale | element);
unary = ((operand_not >> unary)[qi::_val = new_<OperatorNot>(qi::_1)] | operand[qi::_val = qi::_1]);
// token_masking is used to restrict the argument (rhs) of the "MASKING"
// operation to Constant[FALSE], L1uGTReader and PathReader evaluators
token_masking =
(token_false[qi::_val = new_<Constant>(false)] | token_l1algo[qi::_val = new_<L1uGTReader>(qi::_1)] |
token_path[qi::_val = new_<PathReader>(qi::_1)]);
argument_masking %= (token_masking | ('(' >> argument_masking >> ')'));
expression = unary[qi::_val = qi::_1] >>
*((operand_and >> unary)[qi::_val = new_<OperatorAnd>(qi::_val, qi::_1)] |
(operand_or >> unary)[qi::_val = new_<OperatorOr>(qi::_val, qi::_1)] |
(operand_xor >> unary)[qi::_val = new_<OperatorXor>(qi::_val, qi::_1)] |
(operand_masking >> argument_masking)[qi::_val = new_<OperatorMasking>(qi::_val, qi::_1)]);
}
private:
typedef qi::rule<Iterator, std::string(), ascii::space_type> name_rule;
typedef qi::rule<Iterator, Evaluator *(), ascii::space_type> rule;
typedef qi::rule<Iterator> terminal_rule;
terminal_rule token_true;
terminal_rule token_false;
terminal_rule operand_not;
terminal_rule operand_and;
terminal_rule operand_or;
terminal_rule operand_xor;
terminal_rule operand_masking;
name_rule token_l1algo;
name_rule token_path;
rule token;
rule parenthesis;
rule element;
rule prescale;
rule operand;
rule unary;
rule token_masking;
rule argument_masking;
rule expression;
};
// generic interface for string-like objects
template <class T>
Evaluator *parse(const T &text) {
typedef typename T::const_iterator Iterator;
Parser<Iterator> parser;
Evaluator *evaluator = nullptr;
Iterator begin = text.begin();
Iterator end = text.end();
// the interface of qi::phrase_parse has changed between Boost 1.40 (Spirit 2.0) and Boost 1.41 (Spirit 2.1)
bool result = qi::phrase_parse(begin, end, parser, ascii::space, evaluator);
if (not result or begin != end) {
delete evaluator;
return nullptr;
}
return evaluator;
}
// overloaded interface for null-terminated strings
inline Evaluator *parse(const char *text) {
Parser<const char *> parser;
Evaluator *evaluator = nullptr;
const char *begin = text;
const char *end = text + strlen(text);
// the interface of qi::phrase_parse has changed between Boost 1.40 (Spirit 2.0) and Boost 1.41 (Spirit 2.1)
bool result = qi::phrase_parse(begin, end, parser, ascii::space, evaluator);
if (not result or begin != end) {
delete evaluator;
return nullptr;
}
return evaluator;
}
} // namespace triggerExpression
#endif // HLTrigger_HLTcore_TriggerExpressionParser_h
|