ATLAS Offline Software
Loading...
Searching...
No Matches
SelectionExprParser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3*/
4
10
11#include <iostream>
12#include <regex>
13#include <string>
14
16
17namespace CP {
18using namespace msgSelectionHelpers;
19
21bool Separator::operator()(std::string::const_iterator& next,
22 const std::string::const_iterator& end,
23 std::string& tok) const {
24 if (next == end) {
25 return false;
26 }
27
28 static const std::regex base_regex(
29 "^( ?((?:[^|&()! ]+)|(?:&&)|(?:!)|(?:\\()|(?:\\))|(?:\\|\\|))).*");
30 std::smatch m;
31
32 if (std::regex_match(next, end, m, base_regex)) {
33 tok = m[2].str();
34 next += m[1].length();
35 } else {
36 std::smatch m2;
37 static const std::regex space_re{"^ +$"};
38 if (std::regex_match(next, end, m, space_re)) {
39 // only spaces left, we're done
40 return false;
41 }
42 throw std::runtime_error("Cannot tokenize: '" + std::string(next, end) +
43 "'");
44 }
45 return true;
46}
47
48Lexer::Lexer(const std::string& s) : m_string(s), m_tokenizer(m_string, {}) {
49 m_iterator = m_tokenizer.begin();
50}
51
53 if (m_iterator == m_tokenizer.end()) {
54 return Symbol{END, ""};
55 }
56 std::string t = *m_iterator;
57 Type type;
58 if (t == "&&")
59 type = AND;
60 else if (t == "||")
61 type = OR;
62 else if (t == "(")
63 type = LEFT;
64 else if (t == ")")
65 type = RIGHT;
66 else if (t == "!")
67 type = NOT;
68 else if (t == "true")
70 else if (t == "false")
72 else {
73 // check if variable is valid
74 const std::regex base_regex("^([^|()&! ]*)$");
75 std::smatch base_match;
76
77 if (!std::regex_match(t, base_match, base_regex)) {
78 throw std::runtime_error("illegal variable encountered");
79 } else {
80 type = VAR;
81 }
82 }
83
84 ++m_iterator;
85 return Symbol{type, std::move(t)};
86}
87
88} // namespace DetailSelectionExprParser
89
91 : m_lexer(std::move(lexer)), m_defaultToChar(defaultToChar) {}
92
94 std::unique_ptr<ISelectionReadAccessor>& accessor) {
95 std::unique_ptr<ISelectionReadAccessor> root{nullptr};
96 ANA_CHECK(expression(root));
97
98 if (m_symbol.type != Lexer::END) {
99 throw std::runtime_error(
100 "Not all symbols in expression were consumed. Check your expression.");
101 }
102
103 accessor = std::move(root);
104 return StatusCode::SUCCESS;
105}
106
108 std::unique_ptr<ISelectionReadAccessor>& root) {
109 ANA_CHECK(term(root));
110 while (m_symbol.type == Lexer::OR) {
111 std::unique_ptr<ISelectionReadAccessor> left = std::move(root);
112 ANA_CHECK(term(root));
113 std::unique_ptr<ISelectionReadAccessor> right = std::move(root);
114 root = std::make_unique<SelectionAccessorExprOr>(std::move(left),
115 std::move(right));
116 }
117 return StatusCode::SUCCESS;
118}
119
121 std::unique_ptr<ISelectionReadAccessor>& root) {
122 ANA_CHECK(factor(root));
123 std::vector<std::unique_ptr<ISelectionReadAccessor>> factors;
124 factors.push_back(std::move(root));
125
126 while (m_symbol.type == Lexer::AND) {
127 ANA_CHECK(factor(root));
128 factors.push_back(std::move(root));
129 }
130
131 if (factors.size() == 1) {
132 root = std::move(factors[0]);
133 } else {
134 root = std::make_unique<SelectionAccessorList>(std::move(factors));
135 }
136 return StatusCode::SUCCESS;
137}
138
140 std::unique_ptr<ISelectionReadAccessor>& root) {
141 m_symbol = m_lexer.nextSymbol();
142 if (m_symbol.type == Lexer::TRUE_LITERAL) {
143 root = std::make_unique<SelectionReadAccessorNull>(true);
144 m_symbol = m_lexer.nextSymbol();
145 } else if (m_symbol.type == Lexer::FALSE_LITERAL) {
146 root = std::make_unique<SelectionReadAccessorNull>(false);
147 m_symbol = m_lexer.nextSymbol();
148 } else if (m_symbol.type == Lexer::NOT) {
149 ANA_CHECK(factor(root));
150 std::unique_ptr<ISelectionReadAccessor> notEx =
151 std::make_unique<SelectionAccessorExprNot>(std::move(root));
152 root = std::move(notEx);
153 } else if (m_symbol.type == Lexer::LEFT) {
154 ANA_CHECK(expression(root));
155 if (m_symbol.type != Lexer::RIGHT) {
156 throw std::runtime_error(
157 "Missing closing bracket, check your expression.");
158 }
159 m_symbol = m_lexer.nextSymbol();
160
161 } else if (m_symbol.type == Lexer::VAR) {
163 m_symbol = m_lexer.nextSymbol();
164 } else {
165 throw std::runtime_error("Malformed expression.");
166 }
167
168 return StatusCode::SUCCESS;
169}
170
171} // namespace CP
#define ANA_CHECK(EXP)
check whether the given expression was successful
Lexer which turns a token stream into a stream of unambigous symbols to be used by a parser.
Type
Enum over the possible symbols that can be extracted from the token stream.
Lexer(const std::string &s)
Constructor from a strig.
Symbol nextSymbol()
Generate a new symbol from the token sequence.
bool operator()(std::string::const_iterator &next, const std::string::const_iterator &end, std::string &tok) const
Extracts the subsequent token from the input string iterator.
StatusCode term(std::unique_ptr< ISelectionReadAccessor > &root)
SelectionExprParser(DetailSelectionExprParser::Lexer lexer, bool defaultToChar=false)
Constructor for the parser which accepts a Lecer.
DetailSelectionExprParser::Lexer m_lexer
DetailSelectionExprParser::Lexer::Symbol m_symbol
StatusCode factor(std::unique_ptr< ISelectionReadAccessor > &root)
StatusCode expression(std::unique_ptr< ISelectionReadAccessor > &root)
StatusCode build(std::unique_ptr< ISelectionReadAccessor > &accessor)
Triggers the actual parsing of the expression.
Select isolated Photons, Electrons and Muons.
StatusCode makeSelectionReadAccessorVar(const std::string &name, std::unique_ptr< ISelectionReadAccessor > &accessor, bool defaultToChar)
Produces a simple ISelectionReadAccessor accessing the given decoration.
STL namespace.
Struct grouping together the type and original string representation of a symbol.