ATLAS Offline Software
ParsingInternals.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 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 
37 namespace 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 
56  struct unaryexpr_
57  {
58  std::string operator_;
60  };
61 
62  struct operation
63  {
64  std::string operator_;
66  };
67 
68  struct expression
69  {
71  std::list<operation> rest;
72  };
73 
74  inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
75  }
76 }
77 
78 BOOST_FUSION_ADAPT_STRUCT(
80  (std::string, operator_)
82  )
83 
84 BOOST_FUSION_ADAPT_STRUCT(
86  (std::string, operator_)
88  )
89 
90 BOOST_FUSION_ADAPT_STRUCT(
93  (std::list<ExpressionParsing::ast::operation>, rest)
94  )
95 
96 namespace 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  // cppcheck-suppress compareBoolExpressionWithInt; false positive
294  ('(' > expression > ')')
295  | (uint_ >> !char_('.')) | double_ | bool_ | identifier
296  ;
297 
298  identifier = lexeme[((alpha | char_('_') | char_('$') | char_('[') | char_(']') | char_('"') | char_('\''))
299  >> *(alnum | char_('.') | char_('_') | char_('$') | char_('[') | char_(']') | char_('"') | char_('\'')))];
300 
301  // Debugging and error handling and reporting support.
302  BOOST_SPIRIT_DEBUG_NODES(
303  (expression)(equality_expr)(relational_expr)
304  (logical_expr)(additive_expr)(multiplicative_expr)
305  (unary_expr)(unaryfunc_expr)(primary_expr)
306  );
307 
308  // Error handling
309  on_error<fail>(expression, error_handler(_4, _3, _2));
310  }
311 
312 
313  qi::rule<Iterator, ast::expression(), ascii::space_type>
314  expression, equality_expr, relational_expr,
315  logical_expr, additive_expr, multiplicative_expr, power_expr;
316 
317  qi::rule<Iterator, ast::operand(), ascii::space_type>
318  unary_expr, unaryfunc_expr, primary_expr;
319 
320  qi::rule<Iterator, std::string(), ascii::space_type> identifier;
321 
322  qi::symbols<char> keywords;
323  };
324 }
325 
326 
327 #endif // PARSING_INTERNALS_H
grepfile.info
info
Definition: grepfile.py:38
StackElement.h
beamspotnt.ascii
ascii
Definition: bin/beamspotnt.py:1476
ExpressionParsing::ast::operation::operator_
std::string operator_
Definition: ParsingInternals.h:64
han_lark_tester.grammar
grammar
Definition: han_lark_tester.py:39
ExpressionParsing::ast::unaryexpr_::operand_
operand operand_
Definition: ParsingInternals.h:59
get_generator_info.result
result
Definition: get_generator_info.py:21
ExpressionParsing::ast::operator<<
std::ostream & operator<<(std::ostream &out, nil)
Definition: ParsingInternals.h:74
StackElement
void * StackElement
One element of a stack trace.
Definition: stackstash.h:74
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
mc.keywords
keywords
Definition: mc.Herwig7_Dijet.py:8
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
xAOD::identifier
identifier
Definition: UncalibratedMeasurement_v1.cxx:15
x
#define x
LArG4FSStartPointFilterLegacy.execute
execute
Definition: LArG4FSStartPointFilterLegacy.py:20
ExpressionParsing::ast::unaryexpr_
Definition: ParsingInternals.h:57
ExpressionParsing::ast::nil
Definition: ParsingInternals.h:41
HION12.expression
string expression
Definition: HION12.py:56
ExpressionParsing::ast::expression
Definition: ParsingInternals.h:69
beamspotman.n
n
Definition: beamspotman.py:731
ExpressionParsing
Namespace holding all the expression evaluation code.
Definition: ExpressionParser.h:26
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
python.ExitCodes.what
def what(code)
Definition: ExitCodes.py:73
pmontree.code
code
Definition: pmontree.py:443
ExpressionParsing::ast::operation::operand_
operand operand_
Definition: ParsingInternals.h:65
ExpressionParsing::ast::expression::rest
std::list< operation > rest
Definition: ParsingInternals.h:71
ExpressionParsing::ast::operation
Definition: ParsingInternals.h:63
ExpressionParsing::ast::unaryexpr_::operator_
std::string operator_
Definition: ParsingInternals.h:58
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
DeMoScan.first
bool first
Definition: DeMoScan.py:534
ExpressionParsing::ast::operand
boost::variant< nil, double, unsigned int, bool, std::string, boost::recursive_wrapper< unaryexpr_ >, boost::recursive_wrapper< expression > > operand
Definition: ParsingInternals.h:43
ExpressionParsing::ast::expression::first
operand first
Definition: ParsingInternals.h:70
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
IProxyLoader.h
IUnitInterpreter.h
beamspotman.fail
def fail(message)
Definition: beamspotman.py:201