46 #include <boost/spirit/include/phoenix_bind.hpp> 47 #include <boost/spirit/include/qi.hpp> 57 namespace qi = boost::spirit::qi;
58 namespace ascii = boost::spirit::ascii;
59 namespace phoenix = boost::phoenix;
66 namespace pathStatusExpression {
81 namespace pathStatusExpression {
90 virtual void setLeft(std::unique_ptr<Evaluator>&&) {}
91 virtual void setRight(std::unique_ptr<Evaluator>&&) {}
93 virtual void print(std::ostream&
out,
unsigned int indentation)
const {}
100 Operand(std::vector<char>
const& pathName) : pathName_(pathName.
begin(), pathName.
end()) {}
104 void print(std::ostream&
out,
unsigned int indentation)
const override {
105 out <<
std::string(indentation,
' ') << pathName_ <<
"\n";
123 void print(std::ostream&
out,
unsigned int indentation)
const override {
125 operand_->print(out, indentation + 4);
136 template <
typename T>
144 void print(std::ostream&
out,
unsigned int indentation)
const override;
153 return op(left_->evaluate(event), right_->evaluate(event));
174 left_->print(out, indentation + 4);
175 right_->print(out, indentation + 4);
180 left_->print(out, indentation + 4);
181 right_->print(out, indentation + 4);
198 void addPathName(std::vector<char>
const&
s) { operandStack.push_back(std::make_unique<Operand>(s)); }
201 if (operatorStack.empty() || operatorStack.back()->type() !=
Evaluator::Not) {
202 operatorStack.push_back(std::make_unique<NotOperator>());
205 operatorStack.pop_back();
210 std::unique_ptr<Evaluator>& backEvaluator = operatorStack.back();
211 backEvaluator->setRight(
std::move(operandStack.back()));
212 operandStack.pop_back();
213 backEvaluator->setLeft(
std::move(operandStack.back()));
214 operandStack.pop_back();
215 operandStack.push_back(
std::move(backEvaluator));
216 operatorStack.pop_back();
220 std::unique_ptr<Evaluator>& backEvaluator = operatorStack.back();
221 backEvaluator->setLeft(
std::move(operandStack.back()));
222 operandStack.pop_back();
223 operandStack.push_back(
std::move(backEvaluator));
224 operatorStack.pop_back();
228 while (!operatorStack.empty()) {
229 std::unique_ptr<Evaluator>& backEvaluator = operatorStack.back();
231 moveBinaryOperator();
238 operatorStack.push_back(std::make_unique<AndOperator>());
242 while (!operatorStack.empty()) {
243 std::unique_ptr<Evaluator>& backEvaluator = operatorStack.back();
245 moveBinaryOperator();
252 operatorStack.push_back(std::make_unique<OrOperator>());
258 while (!operatorStack.empty()) {
259 std::unique_ptr<Evaluator>& backEvaluator = operatorStack.back();
261 operatorStack.pop_back();
265 moveBinaryOperator();
273 while (!operatorStack.empty()) {
274 std::unique_ptr<Evaluator>& backEvaluator = operatorStack.back();
279 <<
"Should be impossible to get this error. Contact a Framework developer";
282 moveBinaryOperator();
289 if (!operatorStack.empty() || operandStack.size() != 1
U) {
290 throw cms::Exception(
"LogicError") <<
"Should be impossible to get this error. Contact a Framework developer";
292 std::unique_ptr<Evaluator>
temp =
std::move(operandStack.back());
293 operandStack.pop_back();
303 template <
typename Iterator>
304 class Grammar :
public qi::grammar<Iterator, ascii::space_type> {
316 pathName = !unaryOperator >> !binaryOperatorTest >> (+qi::char_(
"a-zA-Z0-9_"))[addPathName];
317 binaryOperand = (qi::lit(
'(')[addBeginParenthesis] >> expression >> qi::lit(
')')[addEndParenthesis]) |
318 (unaryOperator[addOperatorNot] >> binaryOperand) | pathName;
319 afterOperator = ascii::space | &qi::lit(
'(') | &qi::eoi;
320 unaryOperator = qi::lit(
"not") >> afterOperator;
322 binaryOperatorTest = (qi::lit(
"and") >> afterOperator) | (qi::lit(
"or") >> afterOperator);
324 (qi::lit(
"and") >> afterOperator)[addOperatorAnd] | (qi::lit(
"or") >> afterOperator)[addOperatorOr];
325 expression = binaryOperand % binaryOperator;
342 : evaluator_(
nullptr), verbose_(pset.getUntrackedParameter<
bool>(
"verbose")) {
345 LogAbsolute(
"PathStatusFilter") <<
"PathStatusFilter logicalExpression = " << logicalExpression;
348 if (logicalExpression.empty()) {
356 auto it = logicalExpression.cbegin();
357 if (!qi::phrase_parse(it, logicalExpression.cend(), grammar, ascii::space) || (it != logicalExpression.cend())) {
358 throw cms::Exception(
"Configuration") <<
"Syntax error in logical expression. Here is an example of how\n" 359 <<
"the syntax should look:\n" 360 <<
" \"path1 and not (path2 or not path3)\"\n" 361 <<
"The expression must contain alternating appearances of operands\n" 362 <<
"which are path names and binary operators which can be \'and\'\n" 363 <<
"or \'or\', with a path name at the beginning and end. There\n" 364 <<
"must be at least one path name. In addition to the alternating\n" 365 <<
"path names and binary operators, the unary operator \'not\' can\n" 366 <<
"be inserted before a path name or a begin parenthesis.\n" 367 <<
"Parentheses are allowed. Parentheses must come in matching pairs.\n" 368 <<
"Matching begin and end parentheses must contain a complete and\n" 369 <<
"syntactically correct logical expression. There must be at least\n" 370 <<
"one space or parenthesis between operators and path names. Extra\n" 371 <<
"space is ignored and OK. Path names can only contain upper and\n" 372 <<
"lower case letters, numbers, and underscores. A path name cannot\n" 373 <<
"be the same as an operator name.\n";
378 std::stringstream
out;
390 "Operands are path names. Operators in precedence order " 391 "\'not\', \'and\', and \'or\'. Parentheses allowed.");
392 desc.
addUntracked<
bool>(
"verbose",
false)->setComment(
"For debugging only");
393 descriptions.
add(
"pathStatusFilter", desc);
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
T getParameter(std::string const &) const
qi::rule< Iterator > pathName
void init(ConsumesCollector &iC) override
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
edm::propagate_const< std::unique_ptr< Evaluator > > operand_
void print(std::ostream &out, unsigned int indentation) const override
EvaluatorType type() const override
virtual bool evaluate(Event const &event) const
std::vector< std::unique_ptr< Evaluator > > operatorStack
bool evaluate(Event const &event) const override
void setLeft(std::unique_ptr< Evaluator > &&v) override
bool evaluate(Event const &event) const override
S & print(S &os, JobReport::InputFile const &f)
bool evaluate(Event const &event) const override
bool filter(StreamID, Event &, EventSetup const &) const final
EvaluatorType type() const override
edm::propagate_const< std::unique_ptr< Evaluator > > left_
static void fillDescriptions(ConfigurationDescriptions &)
void moveBinaryOperator()
#define DEFINE_FWK_MODULE(type)
Grammar(ShuntingYardAlgorithm *algorithm)
qi::rule< Iterator, ascii::space_type > expression
edm::propagate_const< std::unique_ptr< Evaluator > > right_
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
Operand(std::vector< char > const &pathName)
qi::rule< Iterator, ascii::space_type > binaryOperand
qi::rule< Iterator > unaryOperator
edm::propagate_const< std::unique_ptr< pathStatusExpression::Evaluator > > evaluator_
virtual void setRight(std::unique_ptr< Evaluator > &&)
void print(std::ostream &out, unsigned int indentation) const override
void init(ConsumesCollector &iC) override
ParameterDescriptionBase * add(U const &iLabel, T const &value)
void setLeft(std::unique_ptr< Evaluator > &&v) override
void init(ConsumesCollector &iC) override
void addPathName(std::vector< char > const &s)
void addBeginParenthesis()
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
qi::rule< Iterator > afterOperator
void setRight(std::unique_ptr< Evaluator > &&v) override
void add(std::string const &label, ParameterSetDescription const &psetDescription)
qi::rule< Iterator > binaryOperator
ShuntingYardAlgorithm * algorithm_
virtual void init(ConsumesCollector &)
qi::rule< Iterator > binaryOperatorTest
virtual void setLeft(std::unique_ptr< Evaluator > &&)
PathStatusFilter(ParameterSet const &)
std::vector< std::unique_ptr< Evaluator > > operandStack
EDGetTokenT< PathStatus > token_
EvaluatorType type() const override
virtual void print(std::ostream &out, unsigned int indentation) const
std::unique_ptr< Evaluator > finish()