4#include "CLHEP/Evaluator/defs.h"
5#include "CLHEP/Evaluator/Evaluator.h"
12#include <unordered_map>
41using dic_type = std::unordered_map<string, Item>;
52#define EVAL HepTool::Evaluator
54#define REMOVE_BLANKS \
55for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
56for(n=(int)strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
60 c = (pointer > end) ? '\0' : *pointer; \
61 if (!isspace(c)) break; \
64#define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
67static const char sss[
MAX_N_PAR+2] =
"012345";
69enum {
ENDL,
LBRA,
OR,
AND,
EQ,
NE,
GE,
GT,
LE,
LT,
74static int variable(
const string & name,
double & result,
91 dic_type::const_iterator iter = dictionary.find(name);
92 if (iter == dictionary.end())
93 return EVAL::ERROR_UNKNOWN_VARIABLE;
94 Item item = iter->second;
101 pchar exp_end = exp_begin + strlen(exp_begin) - 1;
102 if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
105 return EVAL::ERROR_CALCULATION_ERROR;
108 return EVAL::ERROR_CALCULATION_ERROR;
115 #if __GNUC__ > 3 && __GNUC_MINOR__ > 6
116 #pragma GCC diagnostic push
117 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
120 #pragma GCC diagnostic push
121 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
124static int function(
const string & name, stack<double> & par,
125 double & result,
const dic_type & dictionary)
142 unsigned long npar = par.size();
143 if (npar >
MAX_N_PAR)
return EVAL::ERROR_UNKNOWN_FUNCTION;
145 dic_type::const_iterator iter = dictionary.find(sss[npar]+name);
146 if (iter == dictionary.end())
return EVAL::ERROR_UNKNOWN_FUNCTION;
147 Item item = iter->second;
150 for(
unsigned long i=0; i<npar; ++i) { pp[i] = par.top(); par.pop(); }
152 if (item.
function == 0)
return EVAL::ERROR_CALCULATION_ERROR;
169 (pp[3],pp[2],pp[1],pp[0]);
173 (pp[4],pp[3],pp[2],pp[1],pp[0]);
176 return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
179 #if __GNUC__ > 3 && __GNUC_MINOR__ > 6
180 #pragma GCC diagnostic pop
183 #pragma GCC diagnostic pop
187static int operand(
pchar begin,
pchar end,
double & result,
207 pchar pointer = begin;
213 if (!isalpha(*pointer)) {
215 result = strtod(pointer, (
char **)(&pointer));
219 EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
225 while(pointer <= end) {
227 if (c !=
'_' && !isalnum(c))
break;
240 EVAL_STATUS = variable(name, result, dictionary);
241 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
249 pchar par_begin = pointer+1, par_end;
252 c = (pointer > end) ?
'\0' : *pointer;
255 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() );
257 pos.push(pointer);
break;
259 if (pos.size() == 1) {
261 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
262 if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
263 {
EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
264 if (EVAL_STATUS != EVAL::OK)
267 par_begin = pointer + 1;
271 if (pos.size() > 1) {
276 EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
277 switch (EVAL_STATUS) {
281 case EVAL::WARNING_BLANK_STRING:
283 {
EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
288 EVAL_STATUS = function(name, par, result, dictionary);
289 EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
309static int maker(
int op, stack<double> & val)
311 if (val.size() < 2)
return EVAL::ERROR_SYNTAX_ERROR;
312 double val2 = val.top(); val.pop();
313 double val1 = val.top();
316 val.top() = (val1 || val2) ? 1. : 0.;
319 val.top() = (val1 && val2) ? 1. : 0.;
322 val.top() = (val1 == val2) ? 1. : 0.;
325 val.top() = (val1 != val2) ? 1. : 0.;
328 val.top() = (val1 >= val2) ? 1. : 0.;
331 val.top() = (val1 > val2) ? 1. : 0.;
334 val.top() = (val1 <= val2) ? 1. : 0.;
337 val.top() = (val1 < val2) ? 1. : 0.;
340 val.top() = val1 + val2;
343 val.top() = val1 - val2;
346 val.top() = val1 * val2;
349 if (val2 == 0.0)
return EVAL::ERROR_CALCULATION_ERROR;
350 val.top() = val1 / val2;
354 val.top() = std::pow(val1,val2);
355 if (errno == 0)
return EVAL::OK;
356 else return EVAL::ERROR_CALCULATION_ERROR;
358 val.top() = val1 + val2;
361 val.top() = val1 - val2;
364 return EVAL::ERROR_CALCULATION_ERROR;
384static int engine(
pchar begin,
pchar end,
double & result,
387 enum SyntaxTableEntry {
389 NumberVariableOrFunction = 1,
390 UnaryPlusOrMinus = 2,
393 static const int SyntaxTable[19][19] = {
395 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
396 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
397 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
398 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
399 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
400 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
401 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
402 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
403 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
404 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
405 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
406 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
407 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
408 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
409 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
410 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
411 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
412 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },
413 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }
415 enum ActionTableEntry {
416 UnbalancedParentheses = -1,
417 ExpressionCompleted = 0,
418 HigherPrecedenceOperator = 1,
419 SamePrecedenceOperator = 2,
420 CloseProcessedParenthesesOrExpression = 3,
421 LowerPrecedenceOperator = 4
423 static const int ActionTable[17][18] = {
425 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 },
426 {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 },
427 { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
428 { 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
429 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
430 { 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
431 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 },
432 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 },
433 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 },
434 { 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 },
435 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 },
436 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 },
437 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 },
438 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 },
439 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 },
440 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 },
441 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }
448 pchar pointer = begin;
449 int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
452 op.push(0); pos.push(pointer);
454 if (c ==
'\0') {
EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
459 c = (pointer > end) ?
'\0' : *pointer;
460 if (isspace(c))
continue;
462 case '\0': iCur =
ENDL;
break;
463 case '(': iCur =
LBRA;
break;
465 if (*(pointer+1) ==
'|') {
466 pointer++; iCur =
OR;
break;
468 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
471 if (*(pointer+1) ==
'&') {
472 pointer++; iCur =
AND;
break;
474 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
477 if (*(pointer+1) ==
'=') {
478 pointer++; iCur =
EQ;
break;
480 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
483 if (*(pointer+1) ==
'=') {
484 pointer++; iCur =
NE;
break;
486 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
489 if (*(pointer+1) ==
'=') { pointer++; iCur =
GE; }
else { iCur =
GT; }
492 if (*(pointer+1) ==
'=') { pointer++; iCur =
LE; }
else { iCur =
LT; }
494 case '+': iCur =
PLUS;
break;
495 case '-': iCur =
MINUS;
break;
497 if (*(pointer+1) ==
'*') { pointer++; iCur =
POW; }
else{ iCur =
MULT; }
499 case '/': iCur =
DIV;
break;
500 case '^': iCur =
POW;
break;
501 case ')': iCur =
RBRA;
break;
503 if (c ==
'.' || isalnum(c)) {
506 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
512 iWhat = SyntaxTable[iPrev][iCur];
516 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
518 EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
519 if (EVAL_STATUS != EVAL::OK) {
EVAL_EXIT( EVAL_STATUS, pointer ); }
535 if (op.size() == 0) {
EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
537 switch (ActionTable[iTop][iCur]) {
539 if (op.size() > 1) pointer = pos.top();
540 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
542 if (val.size() == 1) {
546 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
549 op.push(iCur); pos.push(pointer);
552 EVAL_STATUS = maker(iTop, val);
553 if (EVAL_STATUS != EVAL::OK) {
556 op.top() = iCur; pos.top() = pointer;
562 EVAL_STATUS = maker(iTop, val);
563 if (EVAL_STATUS != EVAL::OK) {
575static void setItem(
const char * prefix,
const char * name,
578 if (name == 0 || *name ==
'\0') {
593 for(
int i=0; i<
n; i++) {
594 char c = *(pointer+i);
595 if (c !=
'_' && !isalnum(c)) {
603 string item_name = prefix + string(pointer,n);
604 dic_type::iterator iter = (s->
theDictionary).find(item_name);
607 if (item_name == name) {
608 s->
theStatus = EVAL::WARNING_EXISTING_VARIABLE;
610 s->
theStatus = EVAL::WARNING_EXISTING_FUNCTION;
644 if (expression != 0) {
658 return ((
Struct *)(p))->theStatus;
663 return int(((
Struct *)(p))->thePosition - ((
Struct *)(p))->theExpression);
678 char prefix[] =
"Evaluator : ";
679 std::ostringstream errn;
683 errn << prefix <<
"invalid name";
686 errn << prefix <<
"syntax error";
689 errn << prefix <<
"unpaired parenthesis";
692 errn << prefix <<
"unexpected symbol";
695 errn << prefix <<
"unknown variable";
698 errn << prefix <<
"unknown function";
701 errn << prefix <<
"empty parameter in function call";
704 errn << prefix <<
"calculation error";
714{ setItem(
"", name,
Item(value), (
Struct *)p); }
717{ setItem(
"", name,
Item(expression), (
Struct *)p); }
727 double (*fun)(
double))
731 double (*fun)(
double,
double))
735 double (*fun)(
double,
double,
double))
739 double (*fun)(
double,
double,
double,
double))
743 double (*fun)(
double,
double,
double,
double,
double))
748 if (name == 0 || *name ==
'\0')
return false;
750 if (n == 0)
return false;
759 if (name == 0 || *name ==
'\0')
return false;
760 if (npar < 0 || npar >
MAX_N_PAR)
return false;
762 if (n == 0)
return false;
764 return ((s->
theDictionary).find(sss[npar]+
string(pointer,n)) ==
770 if (name == 0 || *name ==
'\0')
return;
779 if (name == 0 || *name ==
'\0')
return;
780 if (npar < 0 || npar >
MAX_N_PAR)
return;
std::unordered_map< string, Item > dic_type
#define EVAL_EXIT(STATUS, POSITION)