Geant4 Cross Reference |
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 431