ATLAS Offline Software
Loading...
Searching...
No Matches
ParsingInternals.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// ParsingInternals.h, (c) ATLAS Detector software
8// Author: Thomas Gillam (thomas.gillam@cern.ch)
9// ExpressionParsing library
11
12#ifndef PARSING_INTERNALS_H
13#define PARSING_INTERNALS_H
14
15// Define this to enable debugging
16//#define BOOST_SPIRIT_QI_DEBUG
17
18// on_error template signature changes when using this
19#ifndef BOOST_SPIRIT_USE_PHOENIX_V3
20#define BOOST_SPIRIT_USE_PHOENIX_V3
21#endif
22
23#include <boost/spirit/include/qi.hpp>
24#include <boost/variant/recursive_variant.hpp>
25#include <boost/variant/apply_visitor.hpp>
26#include <boost/fusion/include/adapt_struct.hpp>
27#include <boost/phoenix/function.hpp>
28
29#include <iostream>
30#include <string>
31#include <stdexcept>
32
36
37class EventContext;
38
39namespace ExpressionParsing
40{
41 namespace ast
42 {
43 struct nil {};
44 struct unaryexpr_;
45 struct expression;
46
47 typedef boost::variant<
48 nil
49 , double
50 , unsigned int
51 , bool
52 , std::string
53 , boost::recursive_wrapper<unaryexpr_>
54 , boost::recursive_wrapper<expression>
55 >
57
59 {
60 std::string operator_;
62 };
63
64 struct operation
65 {
66 std::string operator_;
68 };
69
71 {
73 std::list<operation> rest;
74 };
75
76 inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
77 }
78}
79
80BOOST_FUSION_ADAPT_STRUCT(
82 (std::string, operator_)
84 )
85
86BOOST_FUSION_ADAPT_STRUCT(
88 (std::string, operator_)
90 )
91
92BOOST_FUSION_ADAPT_STRUCT(
95 (std::list<ExpressionParsing::ast::operation>, rest)
96 )
97
98namespace ExpressionParsing
99{
100 enum byte_code
101 {
102 // Unary functions
103 op_neg,
104 op_not,
105 op_sum,
106 op_count,
107 op_abs,
108 op_sqrt,
109 op_cbrt,
110 op_sin,
111 op_cos,
112 op_tan,
113 op_asin,
114 op_acos,
115 op_atan,
116 op_sinh,
117 op_cosh,
118 op_tanh,
119 op_asinh,
120 op_acosh,
121 op_atanh,
122 op_log,
123 op_exp,
124
125 // Binary boolean operators
126 op_and,
127 op_or,
128
129 // Binary comparison operators
130 op_eq,
131 op_neq,
132 op_gt,
133 op_gte,
134 op_lt,
135 op_lte,
136
137 // Binary math operations
138 op_add,
139 op_sub,
140 op_pow,
141 op_mul,
142 op_div,
143
144 // push value into the stack
145 op_val
146 };
147
148 class VirtualMachine
149 {
150 public:
151 VirtualMachine(unsigned stackSize = 4096)
152 : m_stackSize(stackSize)
153 { }
154
155 StackElement execute(const EventContext& ctx, std::vector<StackElement> const& code) const;
156 private:
157 unsigned m_stackSize;
158 };
159
160
161 class Compiler
162 {
163 public:
164 typedef void result_type;
165
166 std::vector<StackElement>& code;
167 Compiler(std::vector<StackElement>& code, IProxyLoader *proxyLoader,
168 IUnitInterpreter *unitInterpreter)
169 : code(code), m_proxyLoader(proxyLoader), m_unitInterpreter(unitInterpreter) { }
170
171 void operator()(ast::nil) { BOOST_ASSERT(0); }
172 void operator()(unsigned int n);
173 void operator()(bool n);
174 void operator()(double n);
175 void operator()(const std::string &n);
176
177 void operator()(ast::operation const& x);
178 void operator()(ast::unaryexpr_ const& x);
179 void operator()(ast::expression const& x);
180
181 private:
182 IProxyLoader *m_proxyLoader;
183 IUnitInterpreter *m_unitInterpreter;
184 };
185
186 namespace qi = boost::spirit::qi;
187 namespace ascii = boost::spirit::ascii;
188
189 struct error_handler_
190 {
191 template <typename>
192 struct result { typedef void type; };
193
194 template <typename Iterator>
195 void operator()(
196 qi::info const& what
197 , Iterator err_pos, Iterator last) const
198 {
199 std::cout
200 << "Error! Expecting " << what
201 << " here: \"" << std::string(err_pos, last) << "\""
202 << std::endl;
203 }
204 };
205
206 boost::phoenix::function<error_handler_> const error_handler = error_handler_();
207
208 template <typename Iterator>
209 struct Grammar : qi::grammar<Iterator, ast::expression(), ascii::space_type>
210 {
211 Grammar() : Grammar::base_type(expression)
212 {
213 using qi::char_;
214 using qi::uint_;
215 using qi::double_;
216 using qi::bool_;
217 using qi::_2;
218 using qi::_3;
219 using qi::_4;
220 using qi::_val;
221 using qi::lexeme;
222 using qi::alpha;
223 using qi::alnum;
224
225 using qi::on_error;
226 using qi::fail;
227
228
229
230
231 expression = logical_expr.alias();
232
233 logical_expr = equality_expr >> *(
234 (qi::string("&&") > equality_expr)
235 | (qi::string("||") > equality_expr)
236 );
237
238 equality_expr = relational_expr >> *(
239 (qi::string("==") > relational_expr)
240 | (qi::string("!=") > relational_expr)
241 );
242
243 relational_expr = additive_expr >> *(
244 (qi::string(">=") > additive_expr)
245 | (qi::string("<=") > additive_expr)
246 | (qi::string(">") > additive_expr)
247 | (qi::string("<") > additive_expr)
248 );
249
250 additive_expr = multiplicative_expr >> *(
251 (char_('+') > multiplicative_expr)
252 | (char_('-') > multiplicative_expr)
253 );
254
255 multiplicative_expr = power_expr >> *(
256 (char_('*') > power_expr)
257 | (char_('/') > power_expr)
258 );
259
260 power_expr = unary_expr >> *(
261 (qi::string("**") > unary_expr)
262 );
263
264 unary_expr = unaryfunc_expr
265 | (qi::string("-") > unaryfunc_expr)
266 | (qi::string("+") > unaryfunc_expr)
267 | (qi::string("!") > unaryfunc_expr)
268 ;
269
270 //moved primary_expr to end so that function matches happen first
271 unaryfunc_expr =
272 ((qi::string("sum") >> &char_('(')) > primary_expr)
273 | ((qi::string("count") >> &char_('(')) > primary_expr)
274 | ((qi::string("abs") >> &char_('(')) > primary_expr)
275 | ((qi::string("sqrt") >> &char_('(')) > primary_expr)
276 | ((qi::string("cbrt") >> &char_('(')) > primary_expr)
277 | ((qi::string("asinh") >> &char_('(')) > primary_expr)
278 | ((qi::string("acosh") >> &char_('(')) > primary_expr)
279 | ((qi::string("atanh") >> &char_('(')) > primary_expr)
280 | ((qi::string("asin") >> &char_('(')) > primary_expr)
281 | ((qi::string("acos") >> &char_('(')) > primary_expr)
282 | ((qi::string("atan") >> &char_('(')) > primary_expr)
283 | ((qi::string("sinh") >> &char_('(')) > primary_expr)
284 | ((qi::string("cosh") >> &char_('(')) > primary_expr)
285 | ((qi::string("tanh") >> &char_('(')) > primary_expr)
286 | ((qi::string("sin") >> &char_('(')) > primary_expr)
287 | ((qi::string("cos") >> &char_('(')) > primary_expr)
288 | ((qi::string("tan") >> &char_('(')) > primary_expr)
289 | ((qi::string("log") >> &char_('(')) > primary_expr)
290 | ((qi::string("exp") >> &char_('(')) > primary_expr)
291 | primary_expr ;
292
293
294 primary_expr =
295 ('(' > expression > ')') // cppcheck-suppress compareBoolExpressionWithInt; false positive
296 | (uint_ >> !char_('.')) | double_ | bool_ | identifier
297 ;
298
299 identifier = lexeme[((alpha | char_('_') | char_('$') | char_('[') | char_(']') | char_('"') | char_('\''))
300 >> *(alnum | char_('.') | char_('_') | char_('$') | char_('[') | char_(']') | char_('"') | char_('\'')))];
301
302 // Debugging and error handling and reporting support.
303 BOOST_SPIRIT_DEBUG_NODES(
304 (expression)(equality_expr)(relational_expr)
305 (logical_expr)(additive_expr)(multiplicative_expr)
306 (unary_expr)(unaryfunc_expr)(primary_expr)
307 );
308
309 // Error handling
310 on_error<fail>(expression, error_handler(_4, _3, _2));
311 }
312
313
314 qi::rule<Iterator, ast::expression(), ascii::space_type>
315 expression, equality_expr, relational_expr,
316 logical_expr, additive_expr, multiplicative_expr, power_expr;
317
318 qi::rule<Iterator, ast::operand(), ascii::space_type>
319 unary_expr, unaryfunc_expr, primary_expr;
320
321 qi::rule<Iterator, std::string(), ascii::space_type> identifier;
322
323 qi::symbols<char> keywords;
324 };
325}
326
327
328#endif // PARSING_INTERNALS_H
#define x
boost::variant< nil, double, unsigned int, bool, std::string, boost::recursive_wrapper< unaryexpr_ >, boost::recursive_wrapper< expression > > operand
std::ostream & operator<<(std::ostream &out, nil)
Namespace holding all the expression evaluation code.
str expression
Definition HION12.py:53