ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CexmcAST.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CexmcAST.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 /*
27  * =============================================================================
28  *
29  * Filename: CexmcAST.cc
30  *
31  * Description: abstract syntax tree for custom filter scripting language
32  *
33  * Version: 1.0
34  * Created: 17.07.2010 14:45:14
35  * Revision: none
36  * Compiler: gcc
37  *
38  * Author: Alexey Radkov (),
39  * Company: PNPI
40  *
41  * =============================================================================
42  */
43 
44 #ifdef CEXMC_USE_CUSTOM_FILTER
45 
46 #include <iostream>
47 #include <sstream>
48 #include <string>
49 #include <cmath>
50 #include <boost/variant/get.hpp>
51 #include <boost/format.hpp>
52 #include "CexmcAST.hh"
53 #include "CexmcException.hh"
54 
55 
56 namespace CexmcAST
57 {
58  void Subtree::Print( int level ) const
59  {
60  static const std::string opId[] =
61  { "UNINITIALIZED", "TOP", "u -", "!", "*", "/", "+", "-", "<", "<=",
62  ">", ">=", "=", "!=", "&", "|" };
63 
64  std::stringstream value;
65  const Operator * op( boost::get< Operator >( &type ) );
66 
67  if ( op )
68  {
69  value << "-op- " << opId[ op->type ];
70  }
71  else
72  {
73  const Function * fun( boost::get< Function >( &type ) );
74  value << "-fun- " << *fun;
75  }
76 
77  std::stringstream format;
78  format << "%|" << level * printIndent << "t|";
79  std::cout << boost::format( format.str() ) << value.str() << std::endl;
80 
81  for ( std::vector< Node >::const_iterator k( children.begin() );
82  k != children.end(); ++k )
83  {
84  const Subtree * subtree( boost::get< Subtree >( &*k ) );
85 
86  if ( subtree )
87  {
88  subtree->Print( level + 1 );
89  }
90  else
91  {
92  const Leaf * leaf( boost::get< Leaf >( &*k ) );
93  if ( leaf )
94  PrintLeaf( leaf, level + 1 );
95  }
96  }
97  }
98 
99 
100  void Subtree::PrintLeaf( const Leaf * leaf, int level ) const
101  {
102  const Variable * variable( NULL );
103  std::stringstream value;
104 
105  if ( ( variable = boost::get< Variable >( leaf ) ) )
106  {
107  value << variable->name;
108  if ( variable->index1 > 0 )
109  {
110  value << "[" << variable->index1;
111  if ( variable->index2 > 0 )
112  value << "," << variable->index2;
113  value << "]";
114  }
115  }
116  else
117  {
118  const Constant * constant( boost::get< Constant >( leaf ) );
119  const int * intConstant( boost::get< int >( constant ) );
120  const double * doubleConstant( boost::get< double >(
121  constant ) );
122 
123  value << ( intConstant ? *intConstant : *doubleConstant );
124  }
125 
126  std::stringstream format;
127  format << "%|" << level * printIndent << "t|";
128  std::cout << boost::format( format.str() ) << value.str() << std::endl;
129  }
130 
131 
132  BasicEval::~BasicEval()
133  {
134  }
135 
136 
137  bool BasicEval::operator()( const Subtree & ast ) const
138  {
139  ScalarValueType retval( GetScalarValue( ast ) );
140  int * intRetval( NULL );
141  double * doubleRetval( NULL );
142 
143  intRetval = boost::get< int >( &retval );
144 
145  if ( ! intRetval )
146  doubleRetval = boost::get< double >( &retval );
147 
148  return doubleRetval ? bool( *doubleRetval ) : bool( *intRetval );
149  }
150 
151 
152  BasicEval::ScalarValueType BasicEval::GetScalarValue(
153  const Node & node ) const
154  {
155  const Subtree * ast( boost::get< Subtree >( &node ) );
156 
157  if ( ast )
158  {
159  const Operator * op( boost::get< Operator >( &ast->type ) );
160  if ( op )
161  {
162  ScalarValueType left( 0 );
163  ScalarValueType right( 0 );
164  int * intLeft( NULL );
165  double * doubleLeft( NULL );
166  int * intRight( NULL );
167  double * doubleRight( NULL );
168  bool isDoubleRetval( false );
169 
170  if ( ast->children.size() > 0 )
171  {
172  left = GetScalarValue( ast->children[ 0 ] );
173  intLeft = boost::get< int >( &left );
174  if ( ! intLeft )
175  {
176  doubleLeft = boost::get< double >( &left );
177  if ( ! doubleLeft )
178  throw CexmcException( CexmcCFUnexpectedContext );
179  }
180  }
181 
182  switch ( op->type )
183  {
184  case And :
185  case Or :
186  break;
187  default :
188  if ( ast->children.size() > 1 )
189  {
190  right = GetScalarValue( ast->children[ 1 ] );
191  intRight = boost::get< int >( &right );
192  if ( ! intRight )
193  {
194  doubleRight = boost::get< double >( &right );
195  if ( ! doubleRight )
196  throw CexmcException(
197  CexmcCFUnexpectedContext );
198  }
199  }
200  isDoubleRetval = doubleLeft || doubleRight;
201  break;
202  }
203 
204  switch ( op->type )
205  {
206  case Uninitialized :
207  return 1;
208  case Top :
209  return left;
210  case UMinus :
211  if ( doubleLeft )
212  return - *doubleLeft;
213  else
214  return - *intLeft;
215  case Not :
216  if ( doubleLeft )
217  return ! *doubleLeft;
218  else
219  return ! *intLeft;
220  case Mult :
221  if ( isDoubleRetval )
222  return ( doubleLeft ? *doubleLeft : *intLeft ) *
223  ( doubleRight ? *doubleRight : *intRight );
224  else
225  return *intLeft * *intRight;
226  case Div :
227  if ( isDoubleRetval )
228  return ( doubleLeft ? *doubleLeft : *intLeft ) /
229  ( doubleRight ? *doubleRight : *intRight );
230  else
231  return *intLeft / *intRight;
232  case Plus :
233  if ( isDoubleRetval )
234  return ( doubleLeft ? *doubleLeft : *intLeft ) +
235  ( doubleRight ? *doubleRight : *intRight );
236  else
237  return *intLeft + *intRight;
238  case Minus :
239  if ( isDoubleRetval )
240  return ( doubleLeft ? *doubleLeft : *intLeft ) -
241  ( doubleRight ? *doubleRight : *intRight );
242  else
243  return *intLeft - *intRight;
244  case Less :
245  if ( isDoubleRetval )
246  return ( doubleLeft ? *doubleLeft : *intLeft ) <
247  ( doubleRight ? *doubleRight : *intRight );
248  else
249  return *intLeft < *intRight;
250  case LessEq :
251  if ( isDoubleRetval )
252  return ( doubleLeft ? *doubleLeft : *intLeft ) <=
253  ( doubleRight ? *doubleRight : *intRight );
254  else
255  return *intLeft <= *intRight;
256  case More :
257  if ( isDoubleRetval )
258  return ( doubleLeft ? *doubleLeft : *intLeft ) >
259  ( doubleRight ? *doubleRight : *intRight );
260  else
261  return *intLeft > *intRight;
262  case MoreEq :
263  if ( isDoubleRetval )
264  return ( doubleLeft ? *doubleLeft : *intLeft ) >=
265  ( doubleRight ? *doubleRight : *intRight );
266  else
267  return *intLeft >= *intRight;
268  case Eq :
269  if ( isDoubleRetval )
270  return ( doubleLeft ? *doubleLeft : *intLeft ) ==
271  ( doubleRight ? *doubleRight : *intRight );
272  else
273  return *intLeft == *intRight;
274  case NotEq :
275  if ( isDoubleRetval )
276  return ( doubleLeft ? *doubleLeft : *intLeft ) !=
277  ( doubleRight ? *doubleRight : *intRight );
278  else
279  return *intLeft != *intRight;
280  case And :
281  if ( doubleLeft )
282  {
283  if ( ! *doubleLeft )
284  return 0;
285  }
286  else
287  {
288  if ( ! *intLeft )
289  return 0;
290  }
291  right = GetScalarValue( ast->children[ 1 ] );
292  intRight = boost::get< int >( &right );
293  if ( ! intRight )
294  {
295  doubleRight = boost::get< double >( &right );
296  if ( ! doubleRight )
297  throw CexmcException( CexmcCFUnexpectedContext );
298  }
299  if ( doubleRight )
300  {
301  if ( *doubleRight )
302  return 1;
303  }
304  else
305  {
306  if ( *intRight )
307  return 1;
308  }
309  return 0;
310  case Or :
311  if ( doubleLeft )
312  {
313  if ( *doubleLeft )
314  return 1;
315  }
316  else
317  {
318  if ( *intLeft )
319  return 1;
320  }
321  right = GetScalarValue( ast->children[ 1 ] );
322  intRight = boost::get< int >( &right );
323  if ( ! intRight )
324  {
325  doubleRight = boost::get< double >( &right );
326  if ( ! doubleRight )
327  throw CexmcException( CexmcCFUnexpectedContext );
328  }
329  if ( doubleRight )
330  {
331  if ( *doubleRight )
332  return 1;
333  }
334  else
335  {
336  if ( *intRight )
337  return 1;
338  }
339  return 0;
340  default :
341  return 0;
342  }
343  }
344  else
345  {
346  return GetFunScalarValue( *ast );
347  }
348  }
349  else
350  {
351  const Leaf & leaf( boost::get< Leaf >( node ) );
352  const Constant * constant( boost::get< Constant >( &leaf ) );
353 
354  if ( constant )
355  {
356  return *constant;
357  }
358  else
359  {
360  const Variable & variable( boost::get< Variable >( leaf ) );
361  return GetVarScalarValue( variable );
362  }
363  }
364 
365  return 0;
366  }
367 
368 
369  BasicEval::ScalarValueType BasicEval::GetFunScalarValue(
370  const Subtree & ast ) const
371  {
372  bool evalResult( false );
373  ScalarValueType result( GetBasicFunScalarValue( ast, evalResult ) );
374 
375  if ( evalResult )
376  return result;
377 
378  throw CexmcException( CexmcCFUnexpectedFunction );
379 
380  return 0;
381  }
382 
383 
384  BasicEval::ScalarValueType BasicEval::GetVarScalarValue(
385  const Variable & ) const
386  {
387  throw CexmcException( CexmcCFUnexpectedVariable );
388 
389  return 0;
390  }
391 
392 
393  BasicEval::ScalarValueType BasicEval::GetBasicFunScalarValue(
394  const Subtree & ast, bool & result ) const
395  {
396  const Function & fun( boost::get< Function >( ast.type ) );
397 
398  result = true;
399 
400  ScalarValueType arg( GetScalarValue( ast.children[ 0 ] ) );
401  int * intArg( NULL );
402  double * doubleArg( NULL );
403 
404  intArg = boost::get< int >( &arg );
405  if ( ! intArg )
406  doubleArg = boost::get< double >( &arg );
407 
408  if ( fun == "Sqr" )
409  {
410  if ( doubleArg )
411  return *doubleArg * *doubleArg;
412  else
413  return *intArg * *intArg;
414  }
415  if ( fun == "Sqrt" )
416  {
417  if ( doubleArg )
418  return std::sqrt( *doubleArg );
419  else
420  return std::sqrt( *intArg );
421  }
422 
423  result = false;
424 
425  return 0;
426  }
427 }
428 
429 #endif
430