13 #include "hash_map.src" 50 #define EVAL HepTool::Evaluator 52 #define REMOVE_BLANKS \ 53 for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \ 54 for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break 58 c = (pointer > end) ? '\0' : *pointer; \ 59 if (!isspace(c)) break; \ 62 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS 65 static const char sss[
MAX_N_PAR+2] =
"012345";
67 enum {
ENDL,
LBRA,
OR,
AND,
EQ,
NE,
GE,
GT,
LE,
LT,
72 static int variable(
const string & name,
double & result,
89 dic_type::const_iterator iter = dictionary.find(name);
90 if (iter == dictionary.end())
91 return EVAL::ERROR_UNKNOWN_VARIABLE;
92 Item item = iter->second;
99 pchar exp_end = exp_begin + strlen(exp_begin) - 1;
100 if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
104 return EVAL::ERROR_CALCULATION_ERROR;
108 static 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;
153 (pp[3],pp[2],pp[1],pp[0]);
157 (pp[4],pp[3],pp[2],pp[1],pp[0]);
160 return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
163 static 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);
285 static 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;
333 val.top() = val1 + val2;
336 val.top() = val1 - val2;
339 return EVAL::ERROR_CALCULATION_ERROR;
359 static int engine(
pchar begin,
pchar end,
double & result,
362 enum SyntaxTableEntry {
364 NumberVariableOrFunction = 1,
365 UnaryPlusOrMinus = 2,
368 static const int SyntaxTable[19][19] = {
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 { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 },
387 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 },
388 { 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }
390 enum ActionTableEntry {
391 UnbalancedParentheses = -1,
392 ExpressionCompleted = 0,
393 HigherPrecedenceOperator = 1,
394 SamePrecedenceOperator = 2,
395 CloseProcessedParenthesesOrExpression = 3,
396 LowerPrecedenceOperator = 4
398 static const int ActionTable[17][18] = {
400 { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 },
401 {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 },
402 { 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 },
403 { 4, 1, 4, 2, 1, 1, 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, 2, 2, 1, 1, 1, 1, 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, 2, 2, 2, 2, 1, 1, 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, 2, 2, 1, 1, 1, 1, 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, 4, 4, 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, 2, 2, 1, 4 },
416 { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }
423 pchar pointer = begin;
424 int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
427 op.push(0); pos.push(pointer);
429 if (c ==
'\0') {
EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
434 c = (pointer > end) ?
'\0' : *pointer;
435 if (isspace(c))
continue;
437 case '\0': iCur =
ENDL;
break;
438 case '(': iCur =
LBRA;
break;
440 if (*(pointer+1) ==
'|') {
441 pointer++; iCur =
OR;
break;
443 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
446 if (*(pointer+1) ==
'&') {
447 pointer++; iCur =
AND;
break;
449 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
452 if (*(pointer+1) ==
'=') {
453 pointer++; iCur =
EQ;
break;
455 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
458 if (*(pointer+1) ==
'=') {
459 pointer++; iCur =
NE;
break;
461 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
464 if (*(pointer+1) ==
'=') { pointer++; iCur =
GE; }
else { iCur =
GT; }
467 if (*(pointer+1) ==
'=') { pointer++; iCur =
LE; }
else { iCur =
LT; }
469 case '+': iCur =
PLUS;
break;
470 case '-': iCur =
MINUS;
break;
472 if (*(pointer+1) ==
'*') { pointer++; iCur =
POW; }
else{ iCur =
MULT; }
474 case '/': iCur =
DIV;
break;
475 case '^': iCur =
POW;
break;
476 case ')': iCur =
RBRA;
break;
478 if (c ==
'.' || isalnum(c)) {
481 EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
487 iWhat = SyntaxTable[iPrev][iCur];
491 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
493 EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
494 if (EVAL_STATUS != EVAL::OK) {
EVAL_EXIT( EVAL_STATUS, pointer ); }
510 if (op.size() == 0) {
EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
512 switch (ActionTable[iTop][iCur]) {
514 if (op.size() > 1) pointer = pos.top();
515 EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
517 if (val.size() == 1) {
521 EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
524 op.push(iCur); pos.push(pointer);
527 EVAL_STATUS = maker(iTop, val);
528 if (EVAL_STATUS != EVAL::OK) {
531 op.top() = iCur; pos.top() = pointer;
537 EVAL_STATUS = maker(iTop, val);
538 if (EVAL_STATUS != EVAL::OK) {
550 static void setItem(
const char * prefix,
const char * name,
553 if (name == 0 || *name ==
'\0') {
568 for(
int i=0; i<
n; i++) {
569 char c = *(pointer+i);
570 if (c !=
'_' && !isalnum(c)) {
578 string item_name = prefix + string(pointer,n);
579 dic_type::iterator iter = (s->
theDictionary).find(item_name);
582 if (item_name == name) {
583 s->
theStatus = EVAL::WARNING_EXISTING_VARIABLE;
585 s->
theStatus = EVAL::WARNING_EXISTING_FUNCTION;
597 Evaluator::Evaluator() {
607 Evaluator::~Evaluator() {
619 if (expression != 0) {
632 int Evaluator::status()
const {
633 return ((
Struct *)(p))->theStatus;
637 int Evaluator::error_position()
const {
638 return ((
Struct *)(p))->thePosition - ((
Struct *)(p))->theExpression;
642 void Evaluator::print_error()
const {
645 std::cerr << error_name() << std::endl;
651 std::string Evaluator::error_name()
const 653 char prefix[] =
"Evaluator : ";
654 std::ostringstream errn;
657 case ERROR_NOT_A_NAME:
658 errn << prefix <<
"invalid name";
660 case ERROR_SYNTAX_ERROR:
661 errn << prefix <<
"syntax error";
663 case ERROR_UNPAIRED_PARENTHESIS:
664 errn << prefix <<
"unpaired parenthesis";
666 case ERROR_UNEXPECTED_SYMBOL:
667 errn << prefix <<
"unexpected symbol";
669 case ERROR_UNKNOWN_VARIABLE:
670 errn << prefix <<
"unknown variable";
672 case ERROR_UNKNOWN_FUNCTION:
673 errn << prefix <<
"unknown function";
675 case ERROR_EMPTY_PARAMETER:
676 errn << prefix <<
"empty parameter in function call";
678 case ERROR_CALCULATION_ERROR:
679 errn << prefix <<
"calculation error";
688 void Evaluator::setVariable(
const char * name,
double value)
689 { setItem(
"", name,
Item(value), (
Struct *)p); }
691 void Evaluator::setVariable(
const char * name,
const char *
expression)
692 { setItem(
"", name,
Item(expression), (
Struct *)p); }
697 void Evaluator::setFunction(
const char * name,
699 { setItem(
"0", name,
Item(reinterpret_cast<voidfuncptr>(fun)), (
Struct *)p); }
701 void Evaluator::setFunction(
const char * name,
702 double (*fun)(
double))
703 { setItem(
"1", name,
Item(reinterpret_cast<voidfuncptr>(fun)), (
Struct *)p); }
705 void Evaluator::setFunction(
const char * name,
706 double (*fun)(
double,
double))
707 { setItem(
"2", name,
Item(reinterpret_cast<voidfuncptr>(fun)), (
Struct *)p); }
709 void Evaluator::setFunction(
const char * name,
710 double (*fun)(
double,
double,
double))
711 { setItem(
"3", name,
Item(reinterpret_cast<voidfuncptr>(fun)), (
Struct *)p); }
713 void Evaluator::setFunction(
const char * name,
714 double (*fun)(
double,
double,
double,
double))
715 { setItem(
"4", name,
Item(reinterpret_cast<voidfuncptr>(fun)), (
Struct *)p); }
717 void Evaluator::setFunction(
const char * name,
718 double (*fun)(
double,
double,
double,
double,
double))
719 { setItem(
"5", name,
Item(reinterpret_cast<voidfuncptr>(fun)), (
Struct *)p); }
722 bool Evaluator::findVariable(
const char * name)
const {
723 if (name == 0 || *name ==
'\0')
return false;
725 if (n == 0)
return false;
733 bool Evaluator::findFunction(
const char * name,
int npar)
const {
734 if (name == 0 || *name ==
'\0')
return false;
735 if (npar < 0 || npar >
MAX_N_PAR)
return false;
737 if (n == 0)
return false;
739 return ((s->
theDictionary).find(sss[npar]+
string(pointer,n)) ==
744 void Evaluator::removeVariable(
const char * name) {
745 if (name == 0 || *name ==
'\0')
return;
753 void Evaluator::removeFunction(
const char * name,
int npar) {
754 if (name == 0 || *name ==
'\0')
return;
755 if (npar < 0 || npar >
MAX_N_PAR)
return;
763 void Evaluator::clear() {
hash_map< string, Item > dic_type
#define EVAL_EXIT(STATUS, POSITION)