5 #include "CLHEP/Evaluator/Evaluator.h" 
   49 #define EVAL HepTool::Evaluator 
   51 #define REMOVE_BLANKS \ 
   52 for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \ 
   53 for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break 
   57   c = (pointer > end) ? '\0' : *pointer; \ 
   58   if (!isspace(c)) break;                \ 
   61 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS 
   66 enum { 
ENDL, 
LBRA, 
OR, 
AND, 
EQ, 
NE, 
GE, 
GT, 
LE, 
LT,
 
   88   dic_type::const_iterator iter = dictionary.find(name);
 
   89   if (iter == dictionary.end())
 
   90     return EVAL::ERROR_UNKNOWN_VARIABLE;
 
   91   Item item = iter->second;
 
   98     pchar exp_end   = exp_begin + strlen(exp_begin) - 1;
 
   99     if (
engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
 
  103     return EVAL::ERROR_CALCULATION_ERROR;
 
  107 static int function(
const string & 
name, stack<double> & par,
 
  108                     double & result, 
const dic_type & dictionary) 
 
  125   int npar = par.size();
 
  126   if (npar > 
MAX_N_PAR) 
return EVAL::ERROR_UNKNOWN_FUNCTION;
 
  128   dic_type::const_iterator iter = dictionary.find(
sss[npar]+
name);
 
  129   if (iter == dictionary.end()) 
return EVAL::ERROR_UNKNOWN_FUNCTION;
 
  130   Item item = iter->second;
 
  133   for(
int i=0; i<npar; i++) { pp[i] = par.top(); par.pop(); }
 
  135   if (item.
function == 0)       
return EVAL::ERROR_CALCULATION_ERROR;
 
  138     result = ((double (*)())item.
function)();
 
  141     result = ((double (*)(double))item.
function)(pp[0]);
 
  144     result = ((double (*)(double,double))item.
function)(pp[1], pp[0]);
 
  147     result = ((double (*)(double,double,double))item.
function)
 
  151     result = ((double (*)(double,double,double,double))item.
function)
 
  152       (pp[3],pp[2],pp[1],pp[0]);
 
  155     result = ((double (*)(double,double,double,double,double))item.
function)
 
  156       (pp[4],pp[3],pp[2],pp[1],pp[0]);
 
  159   return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
 
  182   pchar pointer = begin;
 
  188   if (!isalpha(*pointer)) {
 
  190     result = strtod(pointer, (
char **)(&pointer));
 
  194       EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
 
  200   while(pointer <= end) {
 
  202     if (c != 
'_' && !isalnum(c)) 
break;
 
  215     EVAL_STATUS = 
variable(name, result, dictionary);
 
  216     EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
 
  224   pchar         par_begin = pointer+1, par_end;
 
  227     c = (pointer > end) ? 
'\0' : *pointer;
 
  230       EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() ); 
 
  232       pos.push(pointer); 
break;
 
  234       if (pos.size() == 1) {
 
  236         EVAL_STATUS = 
engine(par_begin, par_end, value, par_end, dictionary);
 
  237         if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
 
  238           { 
EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
 
  239         if (EVAL_STATUS != EVAL::OK)
 
  242         par_begin = pointer + 1;
 
  246       if (pos.size() > 1) {
 
  251         EVAL_STATUS = 
engine(par_begin, par_end, value, par_end, dictionary);
 
  252         switch (EVAL_STATUS) {
 
  256         case EVAL::WARNING_BLANK_STRING:
 
  258             { 
EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
 
  263         EVAL_STATUS = 
function(
name, par, result, dictionary);
 
  264         EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
 
  284 static int maker(
int op, stack<double> & val)
 
  286   if (val.size() < 2) 
return EVAL::ERROR_SYNTAX_ERROR;
 
  287   double val2 = val.top(); val.pop();
 
  288   double val1 = val.top();
 
  291     val.top() = (val1 || val2) ? 1. : 0.;
 
  294     val.top() = (val1 && val2) ? 1. : 0.;
 
  297     val.top() = (val1 == val2) ? 1. : 0.;
 
  300     val.top() = (val1 != val2) ? 1. : 0.;
 
  303     val.top() = (val1 >= val2) ? 1. : 0.;
 
  306     val.top() = (val1 >  val2) ? 1. : 0.;
 
  309     val.top() = (val1 <= val2) ? 1. : 0.;
 
  312     val.top() = (val1 <  val2) ? 1. : 0.;
 
  315     val.top() = val1 + val2;
 
  318     val.top() = val1 - val2;
 
  321     val.top() = val1 * val2;
 
  324     if (val2 == 0.0) 
return EVAL::ERROR_CALCULATION_ERROR;
 
  325     val.top() = val1 / val2;
 
  329     val.top() = std::pow(val1,val2);
 
  330     if (errno == 0) 
return EVAL::OK;
 
  332     val.top() = val1 + val2;                    
 
  335     val.top() = val1 - val2;                    
 
  338     return EVAL::ERROR_CALCULATION_ERROR;
 
  361   enum SyntaxTableEntry {
 
  363     NumberVariableOrFunction = 1,
 
  364     UnaryPlusOrMinus = 2,
 
  367   static const int SyntaxTable[19][19] = {
 
  369     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  370     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  371     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  372     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  373     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  374     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  375     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  376     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  377     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  378     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  379     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  380     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  381     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  382     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  383     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  384     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  385     { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },   
 
  386     { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },   
 
  387     { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }    
 
  389   enum ActionTableEntry {
 
  390     UnbalancedParentheses = -1,
 
  391     ExpressionCompleted = 0,
 
  392     HigherPrecedenceOperator = 1,
 
  393     SamePrecedenceOperator = 2,
 
  394     CloseProcessedParenthesesOrExpression = 3,
 
  395     LowerPrecedenceOperator = 4
 
  397   static const int ActionTable[17][18] = {
 
  399     { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, 
 
  400     {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, 
 
  401     { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  402     { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  403     { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  404     { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  405     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  406     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  407     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  408     { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, 
 
  409     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, 
 
  410     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, 
 
  411     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, 
 
  412     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, 
 
  413     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, 
 
  414     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, 
 
  415     { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }  
 
  422   pchar         pointer = begin;
 
  423   int           iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
 
  426   op.push(0); pos.push(pointer);         
 
  428   if (c == 
'\0') { 
EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
 
  433     c = (pointer > end) ? 
'\0' : *pointer;
 
  434     if (isspace(c)) 
continue;            
 
  436     case '\0': iCur = 
ENDL; 
break;
 
  437     case '(':  iCur = 
LBRA; 
break;
 
  439       if (*(pointer+1) == 
'|') {
 
  440         pointer++; iCur = 
OR; 
break;
 
  442         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
 
  445       if (*(pointer+1) == 
'&') {
 
  446         pointer++; iCur = 
AND; 
break;
 
  448         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
 
  451       if (*(pointer+1) == 
'=') {
 
  452         pointer++; iCur = 
EQ; 
break;
 
  454         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
 
  457       if (*(pointer+1) == 
'=') {
 
  458         pointer++; iCur = 
NE; 
break;
 
  460         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
 
  463       if (*(pointer+1) == 
'=') { pointer++; iCur = 
GE; } 
else { iCur = 
GT; }
 
  466       if (*(pointer+1) == 
'=') { pointer++; iCur = 
LE; } 
else { iCur = 
LT; }
 
  468     case '+':  iCur = 
PLUS;  
break;
 
  469     case '-':  iCur = 
MINUS; 
break;
 
  471       if (*(pointer+1) == 
'*') { pointer++; iCur = 
POW; }
else{ iCur = 
MULT; }
 
  473     case '/':  iCur = 
DIV;  
break;
 
  474     case '^':  iCur = 
POW;  
break;
 
  475     case ')':  iCur = 
RBRA; 
break;
 
  477       if (c == 
'.' || isalnum(c)) {
 
  480         EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
 
  486     iWhat = SyntaxTable[iPrev][iCur];
 
  490       EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
 
  492       EVAL_STATUS = 
operand(pointer, end, value, pointer, dictionary);
 
  493       if (EVAL_STATUS != EVAL::OK) { 
EVAL_EXIT( EVAL_STATUS, pointer ); }
 
  509       if (op.size() == 0) { 
EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
 
  511       switch (ActionTable[iTop][iCur]) {
 
  513         if (op.size() > 1) pointer = pos.top();
 
  514         EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
 
  516         if (val.size() == 1) {
 
  520           EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
 
  523         op.push(iCur); pos.push(pointer);
 
  526         EVAL_STATUS = 
maker(iTop, val); 
 
  527         if (EVAL_STATUS != EVAL::OK) {
 
  530         op.top() = iCur; pos.top() = pointer;
 
  536         EVAL_STATUS = 
maker(iTop, val); 
 
  537         if (EVAL_STATUS != EVAL::OK) {  
 
  552   if (name == 0 || *name == 
'\0') {
 
  567   for(
int i=0; i<
n; i++) {
 
  568     char c = *(pointer+i);
 
  569     if (c != 
'_' && !isalnum(c)) {
 
  577   string item_name = prefix + string(pointer,n);
 
  578   dic_type::iterator iter = (s->
theDictionary).find(item_name);
 
  581     if (item_name == name) {
 
  582       s->
theStatus = EVAL::WARNING_EXISTING_VARIABLE;
 
  584       s->
theStatus = EVAL::WARNING_EXISTING_FUNCTION;
 
  596 Evaluator::Evaluator() {
 
  606 Evaluator::~Evaluator() {
 
  611 double Evaluator::evaluate(
const char * expression) {
 
  618   if (expression != 0) {
 
  631 int Evaluator::status()
 const {
 
  632   return ((
Struct *)(p))->theStatus;
 
  636 int Evaluator::error_position()
 const {
 
  637   return ((
Struct *)(p))->thePosition - ((
Struct *)(p))->theExpression;
 
  641 void Evaluator::print_error()
 const {
 
  644       std::cerr << error_name() << std::endl;
 
  650 std::string Evaluator::error_name()
 const 
  652   char prefix[] = 
"Evaluator : ";
 
  653   std::ostringstream errn;
 
  656   case ERROR_NOT_A_NAME:
 
  657     errn << prefix << 
"invalid name";
 
  659   case ERROR_SYNTAX_ERROR:
 
  660     errn << prefix << 
"syntax error";
 
  662   case ERROR_UNPAIRED_PARENTHESIS:
 
  663     errn << prefix << 
"unpaired parenthesis";
 
  665   case ERROR_UNEXPECTED_SYMBOL:
 
  666     errn << prefix << 
"unexpected symbol";
 
  668   case ERROR_UNKNOWN_VARIABLE:
 
  669     errn << prefix << 
"unknown variable";
 
  671   case ERROR_UNKNOWN_FUNCTION:
 
  672     errn << prefix << 
"unknown function";
 
  674   case ERROR_EMPTY_PARAMETER: 
 
  675     errn << prefix << 
"empty parameter in function call";
 
  677   case ERROR_CALCULATION_ERROR:
 
  678     errn << prefix << 
"calculation error";
 
  687 void Evaluator::setVariable(
const char * 
name, 
double value)
 
  690 void Evaluator::setVariable(
const char * name, 
const char * expression)
 
  696 void Evaluator::setFunction(
const char * name,
 
  700 void Evaluator::setFunction(
const char * name,
 
  701                             double (*fun)(
double))
 
  704 void Evaluator::setFunction(
const char * name,
 
  705                             double (*fun)(
double,
double))
 
  708 void Evaluator::setFunction(
const char * name,
 
  709                             double (*fun)(
double,
double,
double))
 
  712 void Evaluator::setFunction(
const char * name,
 
  713                             double (*fun)(
double,
double,
double,
double))
 
  716 void Evaluator::setFunction(
const char * name,
 
  717                             double (*fun)(
double,
double,
double,
double,
double))
 
  721 bool Evaluator::findVariable(
const char * name)
 const {
 
  722   if (name == 0 || *name == 
'\0') 
return false;
 
  724   if (n == 0) 
return false;
 
  732 bool Evaluator::findFunction(
const char * name, 
int npar)
 const {
 
  733   if (name == 0 || *name == 
'\0')    
return false;
 
  734   if (npar < 0  || npar > 
MAX_N_PAR) 
return false;
 
  736   if (n == 0) 
return false;
 
  743 void Evaluator::removeVariable(
const char * name) {
 
  744   if (name == 0 || *name == 
'\0') 
return;
 
  752 void Evaluator::removeFunction(
const char * name, 
int npar) {
 
  753   if (name == 0 || *name == 
'\0')    
return;
 
  754   if (npar < 0  || npar > 
MAX_N_PAR) 
return;
 
  762 void Evaluator::clear() {
 
static int engine(pchar, pchar, double &, pchar &, const dic_type &)
 
static void setItem(const char *prefix, const char *name, const Item &item, Struct *s)
 
static int operand(pchar begin, pchar end, double &result, pchar &endp, const dic_type &dictionary)
 
static int variable(const string &name, double &result, const dic_type &dictionary)
 
static int maker(int op, stack< double > &val)
 
#define EVAL_EXIT(STATUS, POSITION)
 
hash_map< string, Item > dic_type
 
static const char sss[MAX_N_PAR+2]
 
static const G4double pos