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