CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 // -*- C++ -*- 00002 // $Id: Evaluator.cc,v 1.4 2010/07/20 17:00:49 garren Exp $ 00003 // --------------------------------------------------------------------------- 00004 00005 #include "CLHEP/Evaluator/defs.h" 00006 #include "CLHEP/Evaluator/Evaluator.h" 00007 00008 #include <iostream> 00009 #include <sstream> 00010 #include <cmath> // for std::pow() 00011 #include "stack.src" 00012 #include "string.src" 00013 #include "hash_map.src" 00014 #include <string.h> 00015 #include <ctype.h> 00016 #include <errno.h> 00017 #include <stdlib.h> // for strtod() 00018 00019 //--------------------------------------------------------------------------- 00020 // Fix non ISO C++ compliant cast from pointer to function 00021 // to void*, which is a pointer to an object 00022 typedef void (*voidfuncptr)(); 00023 struct Item { 00024 enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTION } what; 00025 double variable; 00026 string expression; 00027 // Fix non ISO C++ compliant cast from pointer to function 00028 // to void*, which is a pointer to an object 00029 //void *function; 00030 voidfuncptr function; 00031 00032 Item() : what(UNKNOWN), variable(0),expression(), function(0) {} 00033 Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {} 00034 Item(string x) : what(EXPRESSION),variable(0),expression(x),function(0) {} 00035 Item(voidfuncptr x) : what(FUNCTION), variable(0),expression(), function(x) {} 00036 }; 00037 00038 typedef char * pchar; 00039 typedef hash_map<string,Item> dic_type; 00040 00041 struct Struct { 00042 dic_type theDictionary; 00043 pchar theExpression; 00044 pchar thePosition; 00045 int theStatus; 00046 double theResult; 00047 }; 00048 00049 //--------------------------------------------------------------------------- 00050 #define EVAL HepTool::Evaluator 00051 00052 #define REMOVE_BLANKS \ 00053 for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \ 00054 for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break 00055 00056 #define SKIP_BLANKS \ 00057 for(;;pointer++) { \ 00058 c = (pointer > end) ? '\0' : *pointer; \ 00059 if (!isspace(c)) break; \ 00060 } 00061 00062 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS 00063 #define MAX_N_PAR 5 00064 00065 static const char sss[MAX_N_PAR+2] = "012345"; 00066 00067 enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT, 00068 PLUS, MINUS, UNARY_PLUS, UNARY_MINUS, MULT, DIV, POW, RBRA, VALUE }; 00069 00070 static int engine(pchar, pchar, double &, pchar &, const dic_type &); 00071 00072 static int variable(const string & name, double & result, 00073 const dic_type & dictionary) 00074 /*********************************************************************** 00075 * * 00076 * Name: variable Date: 03.10.00 * 00077 * Author: Evgeni Chernyaev Revised: * 00078 * * 00079 * Function: Finds value of the variable. * 00080 * This function is used by operand(). * 00081 * * 00082 * Parameters: * 00083 * name - name of the variable. * 00084 * result - value of the variable. * 00085 * dictionary - dictionary of available variables and functions. * 00086 * * 00087 ***********************************************************************/ 00088 { 00089 dic_type::const_iterator iter = dictionary.find(name); 00090 if (iter == dictionary.end()) 00091 return EVAL::ERROR_UNKNOWN_VARIABLE; 00092 Item item = iter->second; 00093 switch (item.what) { 00094 case Item::VARIABLE: 00095 result = item.variable; 00096 return EVAL::OK; 00097 case Item::EXPRESSION: { 00098 pchar exp_begin = (char *)(item.expression.c_str()); 00099 pchar exp_end = exp_begin + strlen(exp_begin) - 1; 00100 if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK) 00101 return EVAL::OK; 00102 } 00103 default: 00104 return EVAL::ERROR_CALCULATION_ERROR; 00105 } 00106 } 00107 00108 static int function(const string & name, stack<double> & par, 00109 double & result, const dic_type & dictionary) 00110 /*********************************************************************** 00111 * * 00112 * Name: function Date: 03.10.00 * 00113 * Author: Evgeni Chernyaev Revised: * 00114 * * 00115 * Function: Finds value of the function. * 00116 * This function is used by operand(). * 00117 * * 00118 * Parameters: * 00119 * name - name of the function. * 00120 * par - stack of parameters. * 00121 * result - value of the function. * 00122 * dictionary - dictionary of available variables and functions. * 00123 * * 00124 ***********************************************************************/ 00125 { 00126 int npar = par.size(); 00127 if (npar > MAX_N_PAR) return EVAL::ERROR_UNKNOWN_FUNCTION; 00128 00129 dic_type::const_iterator iter = dictionary.find(sss[npar]+name); 00130 if (iter == dictionary.end()) return EVAL::ERROR_UNKNOWN_FUNCTION; 00131 Item item = iter->second; 00132 00133 double pp[MAX_N_PAR]; 00134 for(int i=0; i<npar; i++) { pp[i] = par.top(); par.pop(); } 00135 errno = 0; 00136 if (item.function == 0) return EVAL::ERROR_CALCULATION_ERROR; 00137 switch (npar) { 00138 case 0: 00139 result = ((double (*)())item.function)(); 00140 break; 00141 case 1: 00142 result = ((double (*)(double))item.function)(pp[0]); 00143 break; 00144 case 2: 00145 result = ((double (*)(double,double))item.function)(pp[1], pp[0]); 00146 break; 00147 case 3: 00148 result = ((double (*)(double,double,double))item.function) 00149 (pp[2],pp[1],pp[0]); 00150 break; 00151 case 4: 00152 result = ((double (*)(double,double,double,double))item.function) 00153 (pp[3],pp[2],pp[1],pp[0]); 00154 break; 00155 case 5: 00156 result = ((double (*)(double,double,double,double,double))item.function) 00157 (pp[4],pp[3],pp[2],pp[1],pp[0]); 00158 break; 00159 } 00160 return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR; 00161 } 00162 00163 static int operand(pchar begin, pchar end, double & result, 00164 pchar & endp, const dic_type & dictionary) 00165 /*********************************************************************** 00166 * * 00167 * Name: operand Date: 03.10.00 * 00168 * Author: Evgeni Chernyaev Revised: * 00169 * * 00170 * Function: Finds value of the operand. The operand can be either * 00171 * a number or a variable or a function. * 00172 * This function is used by engine(). * 00173 * * 00174 * Parameters: * 00175 * begin - pointer to the first character of the operand. * 00176 * end - pointer to the last character of the character string. * 00177 * result - value of the operand. * 00178 * endp - pointer to the character where the evaluation stoped. * 00179 * dictionary - dictionary of available variables and functions. * 00180 * * 00181 ***********************************************************************/ 00182 { 00183 pchar pointer = begin; 00184 int EVAL_STATUS; 00185 char c; 00186 00187 // G E T N U M B E R 00188 00189 if (!isalpha(*pointer)) { 00190 errno = 0; 00191 result = strtod(pointer, (char **)(&pointer)); 00192 if (errno == 0) { 00193 EVAL_EXIT( EVAL::OK, --pointer ); 00194 }else{ 00195 EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin ); 00196 } 00197 } 00198 00199 // G E T N A M E 00200 00201 while(pointer <= end) { 00202 c = *pointer; 00203 if (c != '_' && !isalnum(c)) break; 00204 pointer++; 00205 } 00206 c = *pointer; 00207 *pointer = '\0'; 00208 string name(begin); 00209 *pointer = c; 00210 00211 // G E T V A R I A B L E 00212 00213 result = 0.0; 00214 SKIP_BLANKS; 00215 if (c != '(') { 00216 EVAL_STATUS = variable(name, result, dictionary); 00217 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin); 00218 } 00219 00220 // G E T F U N C T I O N 00221 00222 stack<pchar> pos; // position stack 00223 stack<double> par; // parameter stack 00224 double value; 00225 pchar par_begin = pointer+1, par_end; 00226 00227 for(;;pointer++) { 00228 c = (pointer > end) ? '\0' : *pointer; 00229 switch (c) { 00230 case '\0': 00231 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() ); 00232 case '(': 00233 pos.push(pointer); break; 00234 case ',': 00235 if (pos.size() == 1) { 00236 par_end = pointer-1; 00237 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary); 00238 if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING) 00239 { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); } 00240 if (EVAL_STATUS != EVAL::OK) 00241 { EVAL_EXIT( EVAL_STATUS, par_end ); } 00242 par.push(value); 00243 par_begin = pointer + 1; 00244 } 00245 break; 00246 case ')': 00247 if (pos.size() > 1) { 00248 pos.pop(); 00249 break; 00250 }else{ 00251 par_end = pointer-1; 00252 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary); 00253 switch (EVAL_STATUS) { 00254 case EVAL::OK: 00255 par.push(value); 00256 break; 00257 case EVAL::WARNING_BLANK_STRING: 00258 if (par.size() != 0) 00259 { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); } 00260 break; 00261 default: 00262 EVAL_EXIT( EVAL_STATUS, par_end ); 00263 } 00264 EVAL_STATUS = function(name, par, result, dictionary); 00265 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin); 00266 } 00267 } 00268 } 00269 } 00270 00271 /*********************************************************************** 00272 * * 00273 * Name: maker Date: 28.09.00 * 00274 * Author: Evgeni Chernyaev Revised: * 00275 * * 00276 * Function: Executes basic arithmetic operations on values in the top * 00277 * of the stack. Result is placed back into the stack. * 00278 * This function is used by engine(). * 00279 * * 00280 * Parameters: * 00281 * op - code of the operation. * 00282 * val - stack of values. * 00283 * * 00284 ***********************************************************************/ 00285 static int maker(int op, stack<double> & val) 00286 { 00287 if (val.size() < 2) return EVAL::ERROR_SYNTAX_ERROR; 00288 double val2 = val.top(); val.pop(); 00289 double val1 = val.top(); 00290 switch (op) { 00291 case OR: // operator || 00292 val.top() = (val1 || val2) ? 1. : 0.; 00293 return EVAL::OK; 00294 case AND: // operator && 00295 val.top() = (val1 && val2) ? 1. : 0.; 00296 return EVAL::OK; 00297 case EQ: // operator == 00298 val.top() = (val1 == val2) ? 1. : 0.; 00299 return EVAL::OK; 00300 case NE: // operator != 00301 val.top() = (val1 != val2) ? 1. : 0.; 00302 return EVAL::OK; 00303 case GE: // operator >= 00304 val.top() = (val1 >= val2) ? 1. : 0.; 00305 return EVAL::OK; 00306 case GT: // operator > 00307 val.top() = (val1 > val2) ? 1. : 0.; 00308 return EVAL::OK; 00309 case LE: // operator <= 00310 val.top() = (val1 <= val2) ? 1. : 0.; 00311 return EVAL::OK; 00312 case LT: // operator < 00313 val.top() = (val1 < val2) ? 1. : 0.; 00314 return EVAL::OK; 00315 case PLUS: // operator '+' 00316 val.top() = val1 + val2; 00317 return EVAL::OK; 00318 case MINUS: // operator '-' 00319 val.top() = val1 - val2; 00320 return EVAL::OK; 00321 case MULT: // operator '*' 00322 val.top() = val1 * val2; 00323 return EVAL::OK; 00324 case DIV: // operator '/' 00325 if (val2 == 0.0) return EVAL::ERROR_CALCULATION_ERROR; 00326 val.top() = val1 / val2; 00327 return EVAL::OK; 00328 case POW: // operator '^' (or '**') 00329 errno = 0; 00330 val.top() = std::pow(val1,val2); 00331 if (errno == 0) return EVAL::OK; 00332 case UNARY_PLUS: // unary operator '+' 00333 val.top() = val1 + val2; // val1 is zero 00334 return EVAL::OK; 00335 case UNARY_MINUS: // unary operator '-' 00336 val.top() = val1 - val2; // val1 is zero 00337 return EVAL::OK; 00338 default: 00339 return EVAL::ERROR_CALCULATION_ERROR; 00340 } 00341 } 00342 00343 /*********************************************************************** 00344 * * 00345 * Name: engine Date: 28.09.00 * 00346 * Author: Evgeni Chernyaev Revised: * 00347 * * 00348 * Function: Evaluates arithmetic expression. * 00349 * * 00350 * Parameters: * 00351 * begin - pointer to the character string with expression. * 00352 * end - pointer to the end of the character string (it is needed * 00353 * for recursive call of engine(), when there is no '\0'). * 00354 * result - result of the evaluation. * 00355 * endp - pointer to the character where the evaluation stoped. * 00356 * dictionary - dictionary of available variables and functions. * 00357 * * 00358 ***********************************************************************/ 00359 static int engine(pchar begin, pchar end, double & result, 00360 pchar & endp, const dic_type & dictionary) 00361 { 00362 enum SyntaxTableEntry { 00363 SyntaxError = 0, 00364 NumberVariableOrFunction = 1, 00365 UnaryPlusOrMinus = 2, 00366 AnyOperator = 3 00367 }; 00368 static const int SyntaxTable[19][19] = { 00369 //E ( || && == != >= > <= < + - u+ u- * / ^ ) V - current token 00370 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // E - previous 00371 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ( token 00372 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // || 00373 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // && 00374 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // == 00375 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // != 00376 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // >= 00377 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // > 00378 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // <= 00379 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // < 00380 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // + 00381 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // - 00382 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary + 00383 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary - 00384 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // * 00385 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // / 00386 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ^ 00387 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }, // ) 00388 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 } // V = {.,N,C} 00389 }; 00390 enum ActionTableEntry { 00391 UnbalancedParentheses = -1, 00392 ExpressionCompleted = 0, 00393 HigherPrecedenceOperator = 1, 00394 SamePrecedenceOperator = 2, 00395 CloseProcessedParenthesesOrExpression = 3, 00396 LowerPrecedenceOperator = 4 00397 }; 00398 static const int ActionTable[17][18] = { 00399 //E ( || && == != >= > <= < + - u+ u- * / ^ ) - current operator 00400 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, // E - top operator 00401 {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, // ( in stack 00402 { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // || 00403 { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // && 00404 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // == 00405 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // != 00406 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >= 00407 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // > 00408 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <= 00409 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // < 00410 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // + 00411 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // - 00412 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary + 00413 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary - 00414 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // * 00415 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // / 00416 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 } // ^ 00417 }; 00418 00419 stack<int> op; // operator stack 00420 stack<pchar> pos; // position stack 00421 stack<double> val; // value stack 00422 double value; 00423 pchar pointer = begin; 00424 int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS; 00425 char c; 00426 00427 op.push(0); pos.push(pointer); // push EOL to the stack 00428 SKIP_BLANKS; 00429 if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); } 00430 for(;;pointer++) { 00431 00432 // N E X T T O K E N 00433 00434 c = (pointer > end) ? '\0' : *pointer; 00435 if (isspace(c)) continue; // skip space, tab etc. 00436 switch (c) { 00437 case '\0': iCur = ENDL; break; 00438 case '(': iCur = LBRA; break; 00439 case '|': 00440 if (*(pointer+1) == '|') { 00441 pointer++; iCur = OR; break; 00442 }else{ 00443 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer ); 00444 } 00445 case '&': 00446 if (*(pointer+1) == '&') { 00447 pointer++; iCur = AND; break; 00448 }else{ 00449 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer ); 00450 } 00451 case '=': 00452 if (*(pointer+1) == '=') { 00453 pointer++; iCur = EQ; break; 00454 }else{ 00455 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer ); 00456 } 00457 case '!': 00458 if (*(pointer+1) == '=') { 00459 pointer++; iCur = NE; break; 00460 }else{ 00461 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer ); 00462 } 00463 case '>': 00464 if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; } 00465 break; 00466 case '<': 00467 if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; } 00468 break; 00469 case '+': iCur = PLUS; break; 00470 case '-': iCur = MINUS; break; 00471 case '*': 00472 if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; } 00473 break; 00474 case '/': iCur = DIV; break; 00475 case '^': iCur = POW; break; 00476 case ')': iCur = RBRA; break; 00477 default: 00478 if (c == '.' || isalnum(c)) { 00479 iCur = VALUE; break; 00480 }else{ 00481 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer ); 00482 } 00483 } 00484 00485 // S Y N T A X A N A L I S Y S 00486 00487 iWhat = SyntaxTable[iPrev][iCur]; 00488 iPrev = iCur; 00489 switch (iWhat) { 00490 case 0: // syntax error 00491 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); 00492 case 1: // operand: number, variable, function 00493 EVAL_STATUS = operand(pointer, end, value, pointer, dictionary); 00494 if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); } 00495 val.push(value); 00496 continue; 00497 case 2: // unary + or unary - 00498 val.push(0.0); 00499 if (iCur == PLUS) iCur = UNARY_PLUS; 00500 if (iCur == MINUS) iCur = UNARY_MINUS; 00501 // Note that for syntax purposes, ordinary + or - are fine. 00502 // Thus iPrev need not change when we encounter a unary minus or plus. 00503 case 3: default: // next operator 00504 break; 00505 } 00506 00507 // N E X T O P E R A T O R 00508 00509 for(;;) { 00510 if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); } 00511 iTop = op.top(); 00512 switch (ActionTable[iTop][iCur]) { 00513 case -1: // syntax error 00514 if (op.size() > 1) pointer = pos.top(); 00515 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer ); 00516 case 0: // last operation (assignment) 00517 if (val.size() == 1) { 00518 result = val.top(); 00519 EVAL_EXIT( EVAL::OK, pointer ); 00520 }else{ 00521 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); 00522 } 00523 case 1: // push current operator in stack 00524 op.push(iCur); pos.push(pointer); 00525 break; 00526 case 2: // execute top operator 00527 EVAL_STATUS = maker(iTop, val); // put current operator in stack 00528 if (EVAL_STATUS != EVAL::OK) { 00529 EVAL_EXIT( EVAL_STATUS, pos.top() ); 00530 } 00531 op.top() = iCur; pos.top() = pointer; 00532 break; 00533 case 3: // delete '(' from stack 00534 op.pop(); pos.pop(); 00535 break; 00536 case 4: default: // execute top operator and 00537 EVAL_STATUS = maker(iTop, val); // delete it from stack 00538 if (EVAL_STATUS != EVAL::OK) { // repete with the same iCur 00539 EVAL_EXIT( EVAL_STATUS, pos.top() ); 00540 } 00541 op.pop(); pos.pop(); 00542 continue; 00543 } 00544 break; 00545 } 00546 } 00547 } 00548 00549 //--------------------------------------------------------------------------- 00550 static void setItem(const char * prefix, const char * name, 00551 const Item & item, Struct * s) { 00552 00553 if (name == 0 || *name == '\0') { 00554 s->theStatus = EVAL::ERROR_NOT_A_NAME; 00555 return; 00556 } 00557 00558 // R E M O V E L E A D I N G A N D T R A I L I N G S P A C E S 00559 00560 const char * pointer; int n; REMOVE_BLANKS; 00561 00562 // C H E C K N A M E 00563 00564 if (n == 0) { 00565 s->theStatus = EVAL::ERROR_NOT_A_NAME; 00566 return; 00567 } 00568 for(int i=0; i<n; i++) { 00569 char c = *(pointer+i); 00570 if (c != '_' && !isalnum(c)) { 00571 s->theStatus = EVAL::ERROR_NOT_A_NAME; 00572 return; 00573 } 00574 } 00575 00576 // A D D I T E M T O T H E D I C T I O N A R Y 00577 00578 string item_name = prefix + string(pointer,n); 00579 dic_type::iterator iter = (s->theDictionary).find(item_name); 00580 if (iter != (s->theDictionary).end()) { 00581 iter->second = item; 00582 if (item_name == name) { 00583 s->theStatus = EVAL::WARNING_EXISTING_VARIABLE; 00584 }else{ 00585 s->theStatus = EVAL::WARNING_EXISTING_FUNCTION; 00586 } 00587 }else{ 00588 (s->theDictionary)[item_name] = item; 00589 s->theStatus = EVAL::OK; 00590 } 00591 } 00592 00593 //--------------------------------------------------------------------------- 00594 namespace HepTool { 00595 00596 //--------------------------------------------------------------------------- 00597 Evaluator::Evaluator() { 00598 Struct * s = new Struct(); 00599 p = (void *) s; 00600 s->theExpression = 0; 00601 s->thePosition = 0; 00602 s->theStatus = OK; 00603 s->theResult = 0.0; 00604 } 00605 00606 //--------------------------------------------------------------------------- 00607 Evaluator::~Evaluator() { 00608 delete (Struct *)(p); 00609 } 00610 00611 //--------------------------------------------------------------------------- 00612 double Evaluator::evaluate(const char * expression) { 00613 Struct * s = (Struct *)(p); 00614 if (s->theExpression != 0) { delete[] s->theExpression; } 00615 s->theExpression = 0; 00616 s->thePosition = 0; 00617 s->theStatus = WARNING_BLANK_STRING; 00618 s->theResult = 0.0; 00619 if (expression != 0) { 00620 s->theExpression = new char[strlen(expression)+1]; 00621 strcpy(s->theExpression, expression); 00622 s->theStatus = engine(s->theExpression, 00623 s->theExpression+strlen(expression)-1, 00624 s->theResult, 00625 s->thePosition, 00626 s->theDictionary); 00627 } 00628 return s->theResult; 00629 } 00630 00631 //--------------------------------------------------------------------------- 00632 int Evaluator::status() const { 00633 return ((Struct *)(p))->theStatus; 00634 } 00635 00636 //--------------------------------------------------------------------------- 00637 int Evaluator::error_position() const { 00638 return ((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression; 00639 } 00640 00641 //--------------------------------------------------------------------------- 00642 void Evaluator::print_error() const { 00643 Struct * s = (Struct *) p; 00644 if(s->theStatus != OK) { 00645 std::cerr << error_name() << std::endl; 00646 } 00647 return; 00648 } 00649 00650 //--------------------------------------------------------------------------- 00651 std::string Evaluator::error_name() const 00652 { 00653 char prefix[] = "Evaluator : "; 00654 std::ostringstream errn; 00655 Struct * s = (Struct *) p; 00656 switch (s->theStatus) { 00657 case ERROR_NOT_A_NAME: 00658 errn << prefix << "invalid name"; 00659 break; 00660 case ERROR_SYNTAX_ERROR: 00661 errn << prefix << "syntax error"; 00662 break; 00663 case ERROR_UNPAIRED_PARENTHESIS: 00664 errn << prefix << "unpaired parenthesis"; 00665 break; 00666 case ERROR_UNEXPECTED_SYMBOL: 00667 errn << prefix << "unexpected symbol"; 00668 break; 00669 case ERROR_UNKNOWN_VARIABLE: 00670 errn << prefix << "unknown variable"; 00671 break; 00672 case ERROR_UNKNOWN_FUNCTION: 00673 errn << prefix << "unknown function"; 00674 break; 00675 case ERROR_EMPTY_PARAMETER: 00676 errn << prefix << "empty parameter in function call"; 00677 break; 00678 case ERROR_CALCULATION_ERROR: 00679 errn << prefix << "calculation error"; 00680 break; 00681 default: 00682 errn << " "; 00683 } 00684 return errn.str(); 00685 } 00686 00687 //--------------------------------------------------------------------------- 00688 void Evaluator::setVariable(const char * name, double value) 00689 { setItem("", name, Item(value), (Struct *)p); } 00690 00691 void Evaluator::setVariable(const char * name, const char * expression) 00692 { setItem("", name, Item(expression), (Struct *)p); } 00693 00694 //--------------------------------------------------------------------------- 00695 // Fix non ISO C++ compliant cast from pointer to function 00696 // to void*, which is a pointer to an object 00697 void Evaluator::setFunction(const char * name, 00698 double (*fun)()) 00699 { setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); } 00700 00701 void Evaluator::setFunction(const char * name, 00702 double (*fun)(double)) 00703 { setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); } 00704 00705 void Evaluator::setFunction(const char * name, 00706 double (*fun)(double,double)) 00707 { setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); } 00708 00709 void Evaluator::setFunction(const char * name, 00710 double (*fun)(double,double,double)) 00711 { setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); } 00712 00713 void Evaluator::setFunction(const char * name, 00714 double (*fun)(double,double,double,double)) 00715 { setItem("4", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); } 00716 00717 void Evaluator::setFunction(const char * name, 00718 double (*fun)(double,double,double,double,double)) 00719 { setItem("5", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); } 00720 00721 //--------------------------------------------------------------------------- 00722 bool Evaluator::findVariable(const char * name) const { 00723 if (name == 0 || *name == '\0') return false; 00724 const char * pointer; int n; REMOVE_BLANKS; 00725 if (n == 0) return false; 00726 Struct * s = (Struct *)(p); 00727 return 00728 ((s->theDictionary).find(string(pointer,n)) == (s->theDictionary).end()) ? 00729 false : true; 00730 } 00731 00732 //--------------------------------------------------------------------------- 00733 bool Evaluator::findFunction(const char * name, int npar) const { 00734 if (name == 0 || *name == '\0') return false; 00735 if (npar < 0 || npar > MAX_N_PAR) return false; 00736 const char * pointer; int n; REMOVE_BLANKS; 00737 if (n == 0) return false; 00738 Struct * s = (Struct *)(p); 00739 return ((s->theDictionary).find(sss[npar]+string(pointer,n)) == 00740 (s->theDictionary).end()) ? false : true; 00741 } 00742 00743 //--------------------------------------------------------------------------- 00744 void Evaluator::removeVariable(const char * name) { 00745 if (name == 0 || *name == '\0') return; 00746 const char * pointer; int n; REMOVE_BLANKS; 00747 if (n == 0) return; 00748 Struct * s = (Struct *)(p); 00749 (s->theDictionary).erase(string(pointer,n)); 00750 } 00751 00752 //--------------------------------------------------------------------------- 00753 void Evaluator::removeFunction(const char * name, int npar) { 00754 if (name == 0 || *name == '\0') return; 00755 if (npar < 0 || npar > MAX_N_PAR) return; 00756 const char * pointer; int n; REMOVE_BLANKS; 00757 if (n == 0) return; 00758 Struct * s = (Struct *)(p); 00759 (s->theDictionary).erase(sss[npar]+string(pointer,n)); 00760 } 00761 00762 //--------------------------------------------------------------------------- 00763 void Evaluator::clear() { 00764 Struct * s = (Struct *) p; 00765 s->theDictionary.clear(); 00766 s->theExpression = 0; 00767 s->thePosition = 0; 00768 s->theStatus = OK; 00769 s->theResult = 0.0; 00770 } 00771 00772 //--------------------------------------------------------------------------- 00773 } // namespace HepTool