9#include "CLHEP/Evaluator/stack.icc"
10#include "CLHEP/Evaluator/string.icc"
11#include "CLHEP/Evaluator/hash_map.icc"
48#define EVAL HepTool::Evaluator
50#define REMOVE_BLANKS \
51for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
52for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
56 c = (pointer > end) ? '\0' : *pointer; \
57 if (!isspace(c)) break; \
60#define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
63static const char sss[
MAX_N_PAR+2] =
"012345";
65enum {
ENDL,
LBRA,
OR,
AND,
EQ,
NE,
GE,
GT,
LE,
LT,
70static int variable(
const string & name,
double & result,
87 dic_type::const_iterator iter = dictionary.find(name);
88 if (iter == dictionary.end())
89 return EVAL::ERROR_UNKNOWN_VARIABLE;
90 Item item = iter->second;
97 pchar exp_end = exp_begin + strlen(exp_begin) - 1;
98 if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
101 return EVAL::ERROR_CALCULATION_ERROR;
104 return EVAL::ERROR_CALCULATION_ERROR;
108static int function(
const string & name, stack<double> & par,
109 double & result,
const dic_type & dictionary)
126 int npar = par.size();
127 if (npar >
MAX_N_PAR)
return EVAL::ERROR_UNKNOWN_FUNCTION;
129 dic_type::const_iterator iter = dictionary.find(sss[npar]+name);
130 if (iter == dictionary.end())
return EVAL::ERROR_UNKNOWN_FUNCTION;
131 Item item = iter->second;
134 for(
int i=0; i<npar; i++) {
pp[i] = par.top(); par.pop(); }
136 if (item.
function == 0)
return EVAL::ERROR_CALCULATION_ERROR;
139 result = ((double (*)())item.
function)();
142 result = ((double (*)(double))item.
function)(pp[0]);
145 result = ((double (*)(double,double))item.
function)(pp[1], pp[0]);
148 result = ((double (*)(double,double,double))item.
function)
152 result = ((double (*)(double,double,double,double))item.
function)
153 (pp[3],pp[2],pp[1],pp[0]);
156 result = ((double (*)(double,double,double,double,double))item.
function)
157 (pp[4],pp[3],pp[2],pp[1],pp[0]);
160 return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
163static int operand(
pchar begin,
pchar end,
double & result,
183 pchar pointer = begin;
189 if (!isalpha(*pointer)) {
191 result = strtod(pointer, (
char **)(&pointer));
195 EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
201 while(pointer <= end) {
203 if (c !=
'_' && !isalnum(c))
break;
216 EVAL_STATUS = variable(name, result, dictionary);
217 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
225 pchar par_begin = pointer+1, par_end;
228 c = (pointer > end) ?
'\0' : *pointer;
231 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS,
pos.top() );
233 pos.push(pointer);
break;
235 if (
pos.size() == 1) {
237 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
238 if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
239 {
EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
240 if (EVAL_STATUS != EVAL::OK)
243 par_begin = pointer + 1;
247 if (
pos.size() > 1) {
252 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
253 switch (EVAL_STATUS) {
257 case EVAL::WARNING_BLANK_STRING:
259 {
EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
264 EVAL_STATUS =
function(name, par, result, dictionary);
265 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
285static int maker(
int op, stack<double> & val)
287 if (val.size() < 2)
return EVAL::ERROR_SYNTAX_ERROR;
288 double val2 = val.top(); val.pop();
289 double val1 = val.top();
292 val.top() = (val1 || val2) ? 1. : 0.;
295 val.top() = (val1 && val2) ? 1. : 0.;
298 val.top() = (val1 == val2) ? 1. : 0.;
301 val.top() = (val1 != val2) ? 1. : 0.;
304 val.top() = (val1 >= val2) ? 1. : 0.;
307 val.top() = (val1 > val2) ? 1. : 0.;
310 val.top() = (val1 <= val2) ? 1. : 0.;
313 val.top() = (val1 < val2) ? 1. : 0.;
316 val.top() = val1 + val2;
319 val.top() = val1 - val2;
322 val.top() = val1 * val2;
325 if (val2 == 0.0)
return EVAL::ERROR_CALCULATION_ERROR;
326 val.top() = val1 / val2;
330 val.top() = std::pow(val1,val2);
331 if (errno == 0)
return EVAL::OK;
332 else return EVAL::ERROR_CALCULATION_ERROR;
334 val.top() = val1 + val2;
337 val.top() = val1 - val2;
340 return EVAL::ERROR_CALCULATION_ERROR;
360static int engine(
pchar begin,
pchar end,
double & result,
363 enum SyntaxTableEntry {
365 NumberVariableOrFunction = 1,
366 UnaryPlusOrMinus = 2,
369 static const int SyntaxTable[19][19] = {
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 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
387 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
388 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },
389 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }
391 enum ActionTableEntry {
392 UnbalancedParentheses = -1,
393 ExpressionCompleted = 0,
394 HigherPrecedenceOperator = 1,
395 SamePrecedenceOperator = 2,
396 CloseProcessedParenthesesOrExpression = 3,
397 LowerPrecedenceOperator = 4
399 static const int ActionTable[17][18] = {
401 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 },
402 {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 },
403 { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
404 { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
405 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
406 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 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, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 },
410 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 },
411 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 },
412 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 },
413 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 },
414 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 },
415 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 },
416 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 },
417 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }
424 pchar pointer = begin;
425 int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
428 op.push(0);
pos.push(pointer);
430 if (c ==
'\0') {
EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
435 c = (pointer > end) ?
'\0' : *pointer;
436 if (isspace(c))
continue;
438 case '\0': iCur =
ENDL;
break;
439 case '(': iCur =
LBRA;
break;
441 if (*(pointer+1) ==
'|') {
442 pointer++; iCur =
OR;
break;
444 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
447 if (*(pointer+1) ==
'&') {
448 pointer++; iCur =
AND;
break;
450 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
453 if (*(pointer+1) ==
'=') {
454 pointer++; iCur =
EQ;
break;
456 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
459 if (*(pointer+1) ==
'=') {
460 pointer++; iCur =
NE;
break;
462 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
465 if (*(pointer+1) ==
'=') { pointer++; iCur =
GE; }
else { iCur =
GT; }
468 if (*(pointer+1) ==
'=') { pointer++; iCur =
LE; }
else { iCur =
LT; }
470 case '+': iCur =
PLUS;
break;
471 case '-': iCur =
MINUS;
break;
473 if (*(pointer+1) ==
'*') { pointer++; iCur =
POW; }
else{ iCur =
MULT; }
475 case '/': iCur =
DIV;
break;
476 case '^': iCur =
POW;
break;
477 case ')': iCur =
RBRA;
break;
479 if (c ==
'.' || isalnum(c)) {
482 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
488 iWhat = SyntaxTable[iPrev][iCur];
492 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
494 EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
495 if (EVAL_STATUS != EVAL::OK) {
EVAL_EXIT( EVAL_STATUS, pointer ); }
511 if (op.size() == 0) {
EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
513 switch (ActionTable[iTop][iCur]) {
515 if (op.size() > 1) pointer =
pos.top();
516 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
518 if (val.size() == 1) {
522 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
525 op.push(iCur);
pos.push(pointer);
528 EVAL_STATUS = maker(iTop, val);
529 if (EVAL_STATUS != EVAL::OK) {
532 op.top() = iCur;
pos.top() = pointer;
538 EVAL_STATUS = maker(iTop, val);
539 if (EVAL_STATUS != EVAL::OK) {
551static void setItem(
const char *
prefix,
const char * name,
554 if (name == 0 || *name ==
'\0') {
569 for(
int i=0; i<
n; i++) {
570 char c = *(pointer+i);
571 if (c !=
'_' && !isalnum(c)) {
579 string item_name =
prefix + string(pointer,n);
580 dic_type::iterator iter = (s->
theDictionary).find(item_name);
583 if (item_name == name) {
584 s->
theStatus = EVAL::WARNING_EXISTING_VARIABLE;
586 s->
theStatus = EVAL::WARNING_EXISTING_FUNCTION;
620 if (expression != 0) {
634 return ((
Struct *)(p))->theStatus;
639 return ((
Struct *)(p))->thePosition - ((
Struct *)(p))->theExpression;
654 char prefix[] =
"Evaluator : ";
655 std::ostringstream errn;
659 errn <<
prefix <<
"invalid name";
662 errn <<
prefix <<
"syntax error";
665 errn <<
prefix <<
"unpaired parenthesis";
668 errn <<
prefix <<
"unexpected symbol";
671 errn <<
prefix <<
"unknown variable";
674 errn <<
prefix <<
"unknown function";
677 errn <<
prefix <<
"empty parameter in function call";
680 errn <<
prefix <<
"calculation error";
690{ setItem(
"", name,
Item(value), (
Struct *)p); }
693{ setItem(
"", name,
Item(expression), (
Struct *)p); }
703 double (*fun)(
double))
707 double (*fun)(
double,
double))
711 double (*fun)(
double,
double,
double))
715 double (*fun)(
double,
double,
double,
double))
719 double (*fun)(
double,
double,
double,
double,
double))
724 if (name == 0 || *name ==
'\0')
return false;
726 if (n == 0)
return false;
735 if (name == 0 || *name ==
'\0')
return false;
736 if (npar < 0 || npar >
MAX_N_PAR)
return false;
738 if (n == 0)
return false;
740 return ((s->
theDictionary).find(sss[npar]+
string(pointer,n)) ==
746 if (name == 0 || *name ==
'\0')
return;
755 if (name == 0 || *name ==
'\0')
return;
756 if (npar < 0 || npar >
MAX_N_PAR)
return;
#define EVAL_EXIT(STATUS, POSITION)
hash_map< string, Item > dic_type
G4double(* function)(G4double)
const char * name(G4int ptype)