ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Evaluator.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Evaluator.cc
1 // -*- C++ -*-
2 // ---------------------------------------------------------------------------
3 
5 
6 #include <iostream>
7 #include <sstream>
8 #include <cmath> // for std::pow()
9 #include "CLHEP/Evaluator/stack.icc"
10 #include "CLHEP/Evaluator/string.icc"
11 #include "CLHEP/Evaluator/hash_map.icc"
12 #include <string.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <stdlib.h> // for strtod()
16 
17 //---------------------------------------------------------------------------
18 // Fix non ISO C++ compliant cast from pointer to function
19 // to void*, which is a pointer to an object
20 typedef void (*voidfuncptr)();
21 struct Item {
23  double variable;
24  string expression;
25  // Fix non ISO C++ compliant cast from pointer to function
26  // to void*, which is a pointer to an object
27  //void *function;
28  voidfuncptr function;
29 
31  Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
32  Item(string x) : what(EXPRESSION),variable(0),expression(x),function(0) {}
34 };
35 
36 typedef char * pchar;
37 typedef hash_map<string,Item> dic_type;
38 
39 struct Struct {
43  int theStatus;
44  double theResult;
45 };
46 
47 //---------------------------------------------------------------------------
48 #define EVAL HepTool::Evaluator
49 
50 #define REMOVE_BLANKS \
51 for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
52 for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
53 
54 #define SKIP_BLANKS \
55 for(;;pointer++) { \
56  c = (pointer > end) ? '\0' : *pointer; \
57  if (!isspace(c)) break; \
58 }
59 
60 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
61 #define MAX_N_PAR 5
62 
63 static const char sss[MAX_N_PAR+2] = "012345";
64 
65 enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
67 
68 static int engine(pchar, pchar, double &, pchar &, const dic_type &);
69 
70 static int variable(const string & name, double & result,
71  const dic_type & dictionary)
72 /***********************************************************************
73  * *
74  * Name: variable Date: 03.10.00 *
75  * Author: Evgeni Chernyaev Revised: *
76  * *
77  * Function: Finds value of the variable. *
78  * This function is used by operand(). *
79  * *
80  * Parameters: *
81  * name - name of the variable. *
82  * result - value of the variable. *
83  * dictionary - dictionary of available variables and functions. *
84  * *
85  ***********************************************************************/
86 {
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;
91  switch (item.what) {
92  case Item::VARIABLE:
93  result = item.variable;
94  return EVAL::OK;
95  case Item::EXPRESSION: {
96  pchar exp_begin = (char *)(item.expression.c_str());
97  pchar exp_end = exp_begin + strlen(exp_begin) - 1;
98  if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
99  return EVAL::OK;
100  else
101  return EVAL::ERROR_CALCULATION_ERROR;
102  }
103  default:
104  return EVAL::ERROR_CALCULATION_ERROR;
105  }
106 }
107 
108 static int function(const string & name, stack<double> & par,
109  double & result, const dic_type & dictionary)
110 /***********************************************************************
111  * *
112  * Name: function Date: 03.10.00 *
113  * Author: Evgeni Chernyaev Revised: *
114  * *
115  * Function: Finds value of the function. *
116  * This function is used by operand(). *
117  * *
118  * Parameters: *
119  * name - name of the function. *
120  * par - stack of parameters. *
121  * result - value of the function. *
122  * dictionary - dictionary of available variables and functions. *
123  * *
124  ***********************************************************************/
125 {
126  int npar = par.size();
127  if (npar > MAX_N_PAR) return EVAL::ERROR_UNKNOWN_FUNCTION;
128 
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;
132 
133  double pp[MAX_N_PAR] = {0.0};
134  for(int i=0; i<npar; i++) { pp[i] = par.top(); par.pop(); }
135  errno = 0;
136  if (item.function == 0) return EVAL::ERROR_CALCULATION_ERROR;
137  switch (npar) {
138  case 0:
139  result = ((double (*)())item.function)();
140  break;
141  case 1:
142  result = ((double (*)(double))item.function)(pp[0]);
143  break;
144  case 2:
145  result = ((double (*)(double,double))item.function)(pp[1], pp[0]);
146  break;
147  case 3:
148  result = ((double (*)(double,double,double))item.function)
149  (pp[2],pp[1],pp[0]);
150  break;
151  case 4:
152  result = ((double (*)(double,double,double,double))item.function)
153  (pp[3],pp[2],pp[1],pp[0]);
154  break;
155  case 5:
156  result = ((double (*)(double,double,double,double,double))item.function)
157  (pp[4],pp[3],pp[2],pp[1],pp[0]);
158  break;
159  }
160  return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
161 }
162 
163 static int operand(pchar begin, pchar end, double & result,
164  pchar & endp, const dic_type & dictionary)
165 /***********************************************************************
166  * *
167  * Name: operand Date: 03.10.00 *
168  * Author: Evgeni Chernyaev Revised: *
169  * *
170  * Function: Finds value of the operand. The operand can be either *
171  * a number or a variable or a function. *
172  * This function is used by engine(). *
173  * *
174  * Parameters: *
175  * begin - pointer to the first character of the operand. *
176  * end - pointer to the last character of the character string. *
177  * result - value of the operand. *
178  * endp - pointer to the character where the evaluation stoped. *
179  * dictionary - dictionary of available variables and functions. *
180  * *
181  ***********************************************************************/
182 {
183  pchar pointer = begin;
184  int EVAL_STATUS;
185  char c;
186 
187  // G E T N U M B E R
188 
189  if (!isalpha(*pointer)) {
190  errno = 0;
191  result = strtod(pointer, (char **)(&pointer));
192  if (errno == 0) {
193  EVAL_EXIT( EVAL::OK, --pointer );
194  }else{
195  EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
196  }
197  }
198 
199  // G E T N A M E
200 
201  while(pointer <= end) {
202  c = *pointer;
203  if (c != '_' && !isalnum(c)) break;
204  pointer++;
205  }
206  c = *pointer;
207  *pointer = '\0';
208  string name(begin);
209  *pointer = c;
210 
211  // G E T V A R I A B L E
212 
213  result = 0.0;
214  SKIP_BLANKS;
215  if (c != '(') {
216  EVAL_STATUS = variable(name, result, dictionary);
217  EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
218  }
219 
220  // G E T F U N C T I O N
221 
222  stack<pchar> pos; // position stack
223  stack<double> par; // parameter stack
224  double value;
225  pchar par_begin = pointer+1, par_end;
226 
227  for(;;pointer++) {
228  c = (pointer > end) ? '\0' : *pointer;
229  switch (c) {
230  case '\0':
231  EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() );
232  case '(':
233  pos.push(pointer); break;
234  case ',':
235  if (pos.size() == 1) {
236  par_end = pointer-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)
241  { EVAL_EXIT( EVAL_STATUS, par_end ); }
242  par.push(value);
243  par_begin = pointer + 1;
244  }
245  break;
246  case ')':
247  if (pos.size() > 1) {
248  pos.pop();
249  break;
250  }else{
251  par_end = pointer-1;
252  EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
253  switch (EVAL_STATUS) {
254  case EVAL::OK:
255  par.push(value);
256  break;
257  case EVAL::WARNING_BLANK_STRING:
258  if (par.size() != 0)
259  { EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
260  break;
261  default:
262  EVAL_EXIT( EVAL_STATUS, par_end );
263  }
264  EVAL_STATUS = function(name, par, result, dictionary);
265  EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
266  }
267  }
268  }
269 }
270 
271 /***********************************************************************
272  * *
273  * Name: maker Date: 28.09.00 *
274  * Author: Evgeni Chernyaev Revised: *
275  * *
276  * Function: Executes basic arithmetic operations on values in the top *
277  * of the stack. Result is placed back into the stack. *
278  * This function is used by engine(). *
279  * *
280  * Parameters: *
281  * op - code of the operation. *
282  * val - stack of values. *
283  * *
284  ***********************************************************************/
285 static int maker(int op, stack<double> & val)
286 {
287  if (val.size() < 2) return EVAL::ERROR_SYNTAX_ERROR;
288  double val2 = val.top(); val.pop();
289  double val1 = val.top();
290  switch (op) {
291  case OR: // operator ||
292  val.top() = (val1 || val2) ? 1. : 0.;
293  return EVAL::OK;
294  case AND: // operator &&
295  val.top() = (val1 && val2) ? 1. : 0.;
296  return EVAL::OK;
297  case EQ: // operator ==
298  val.top() = (val1 == val2) ? 1. : 0.;
299  return EVAL::OK;
300  case NE: // operator !=
301  val.top() = (val1 != val2) ? 1. : 0.;
302  return EVAL::OK;
303  case GE: // operator >=
304  val.top() = (val1 >= val2) ? 1. : 0.;
305  return EVAL::OK;
306  case GT: // operator >
307  val.top() = (val1 > val2) ? 1. : 0.;
308  return EVAL::OK;
309  case LE: // operator <=
310  val.top() = (val1 <= val2) ? 1. : 0.;
311  return EVAL::OK;
312  case LT: // operator <
313  val.top() = (val1 < val2) ? 1. : 0.;
314  return EVAL::OK;
315  case PLUS: // operator '+'
316  val.top() = val1 + val2;
317  return EVAL::OK;
318  case MINUS: // operator '-'
319  val.top() = val1 - val2;
320  return EVAL::OK;
321  case MULT: // operator '*'
322  val.top() = val1 * val2;
323  return EVAL::OK;
324  case DIV: // operator '/'
325  if (val2 == 0.0) return EVAL::ERROR_CALCULATION_ERROR;
326  val.top() = val1 / val2;
327  return EVAL::OK;
328  case POW: // operator '^' (or '**')
329  errno = 0;
330  val.top() = std::pow(val1,val2);
331  if (errno == 0) return EVAL::OK;
332  else return EVAL::ERROR_CALCULATION_ERROR;
333  case UNARY_PLUS: // unary operator '+'
334  val.top() = val1 + val2; // val1 is zero
335  return EVAL::OK;
336  case UNARY_MINUS: // unary operator '-'
337  val.top() = val1 - val2; // val1 is zero
338  return EVAL::OK;
339  default:
340  return EVAL::ERROR_CALCULATION_ERROR;
341  }
342 }
343 
344 /***********************************************************************
345  * *
346  * Name: engine Date: 28.09.00 *
347  * Author: Evgeni Chernyaev Revised: *
348  * *
349  * Function: Evaluates arithmetic expression. *
350  * *
351  * Parameters: *
352  * begin - pointer to the character string with expression. *
353  * end - pointer to the end of the character string (it is needed *
354  * for recursive call of engine(), when there is no '\0'). *
355  * result - result of the evaluation. *
356  * endp - pointer to the character where the evaluation stoped. *
357  * dictionary - dictionary of available variables and functions. *
358  * *
359  ***********************************************************************/
360 static int engine(pchar begin, pchar end, double & result,
361  pchar & endp, const dic_type & dictionary)
362 {
363  enum SyntaxTableEntry {
364  SyntaxError = 0,
365  NumberVariableOrFunction = 1,
366  UnaryPlusOrMinus = 2,
367  AnyOperator = 3
368  };
369  static const int SyntaxTable[19][19] = {
370  //E ( || && == != >= > <= < + - u+ u- * / ^ ) V - current token
371  { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // E - previous
372  { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ( token
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 }, // unary +
384  { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary -
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 } // V = {.,N,C}
390  };
391  enum ActionTableEntry {
392  UnbalancedParentheses = -1,
393  ExpressionCompleted = 0,
394  HigherPrecedenceOperator = 1,
395  SamePrecedenceOperator = 2,
396  CloseProcessedParenthesesOrExpression = 3,
397  LowerPrecedenceOperator = 4
398  };
399  static const int ActionTable[17][18] = {
400  //E ( || && == != >= > <= < + - u+ u- * / ^ ) - current operator
401  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, // E - top operator
402  {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, // ( in stack
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 }, // unary +
414  { 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 4 }, // unary -
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 } // ^
418  };
419 
420  stack<int> op; // operator stack
421  stack<pchar> pos; // position stack
422  stack<double> val; // value stack
423  double value;
424  pchar pointer = begin;
425  int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
426  char c;
427 
428  op.push(0); pos.push(pointer); // push EOL to the stack
429  SKIP_BLANKS;
430  if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
431  for(;;pointer++) {
432 
433  // N E X T T O K E N
434 
435  c = (pointer > end) ? '\0' : *pointer;
436  if (isspace(c)) continue; // skip space, tab etc.
437  switch (c) {
438  case '\0': iCur = ENDL; break;
439  case '(': iCur = LBRA; break;
440  case '|':
441  if (*(pointer+1) == '|') {
442  pointer++; iCur = OR; break;
443  }else{
444  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
445  }
446  case '&':
447  if (*(pointer+1) == '&') {
448  pointer++; iCur = AND; break;
449  }else{
450  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
451  }
452  case '=':
453  if (*(pointer+1) == '=') {
454  pointer++; iCur = EQ; break;
455  }else{
456  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
457  }
458  case '!':
459  if (*(pointer+1) == '=') {
460  pointer++; iCur = NE; break;
461  }else{
462  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
463  }
464  case '>':
465  if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; }
466  break;
467  case '<':
468  if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; }
469  break;
470  case '+': iCur = PLUS; break;
471  case '-': iCur = MINUS; break;
472  case '*':
473  if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; }
474  break;
475  case '/': iCur = DIV; break;
476  case '^': iCur = POW; break;
477  case ')': iCur = RBRA; break;
478  default:
479  if (c == '.' || isalnum(c)) {
480  iCur = VALUE; break;
481  }else{
482  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
483  }
484  }
485 
486  // S Y N T A X A N A L I S Y S
487 
488  iWhat = SyntaxTable[iPrev][iCur];
489  iPrev = iCur;
490  switch (iWhat) {
491  case 0: // syntax error
492  EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
493  case 1: // operand: number, variable, function
494  EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
495  if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); }
496  val.push(value);
497  continue;
498  case 2: // unary + or unary -
499  val.push(0.0);
500  if (iCur == PLUS) iCur = UNARY_PLUS;
501  if (iCur == MINUS) iCur = UNARY_MINUS;
502  // Note that for syntax purposes, ordinary + or - are fine.
503  // Thus iPrev need not change when we encounter a unary minus or plus.
504  case 3: default: // next operator
505  break;
506  }
507 
508  // N E X T O P E R A T O R
509 
510  for(;;) {
511  if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
512  iTop = op.top();
513  switch (ActionTable[iTop][iCur]) {
514  case -1: // syntax error
515  if (op.size() > 1) pointer = pos.top();
516  EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
517  case 0: // last operation (assignment)
518  if (val.size() == 1) {
519  result = val.top();
520  EVAL_EXIT( EVAL::OK, pointer );
521  }else{
522  EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
523  }
524  case 1: // push current operator in stack
525  op.push(iCur); pos.push(pointer);
526  break;
527  case 2: // execute top operator
528  EVAL_STATUS = maker(iTop, val); // put current operator in stack
529  if (EVAL_STATUS != EVAL::OK) {
530  EVAL_EXIT( EVAL_STATUS, pos.top() );
531  }
532  op.top() = iCur; pos.top() = pointer;
533  break;
534  case 3: // delete '(' from stack
535  op.pop(); pos.pop();
536  break;
537  case 4: default: // execute top operator and
538  EVAL_STATUS = maker(iTop, val); // delete it from stack
539  if (EVAL_STATUS != EVAL::OK) { // repete with the same iCur
540  EVAL_EXIT( EVAL_STATUS, pos.top() );
541  }
542  op.pop(); pos.pop();
543  continue;
544  }
545  break;
546  }
547  }
548 }
549 
550 //---------------------------------------------------------------------------
551 static void setItem(const char * prefix, const char * name,
552  const Item & item, Struct * s) {
553 
554  if (name == 0 || *name == '\0') {
555  s->theStatus = EVAL::ERROR_NOT_A_NAME;
556  return;
557  }
558 
559  // 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
560 
561  const char * pointer; int n; REMOVE_BLANKS;
562 
563  // C H E C K N A M E
564 
565  if (n == 0) {
566  s->theStatus = EVAL::ERROR_NOT_A_NAME;
567  return;
568  }
569  for(int i=0; i<n; i++) {
570  char c = *(pointer+i);
571  if (c != '_' && !isalnum(c)) {
572  s->theStatus = EVAL::ERROR_NOT_A_NAME;
573  return;
574  }
575  }
576 
577  // A D D I T E M T O T H E D I C T I O N A R Y
578 
579  string item_name = prefix + string(pointer,n);
580  dic_type::iterator iter = (s->theDictionary).find(item_name);
581  if (iter != (s->theDictionary).end()) {
582  iter->second = item;
583  if (item_name == name) {
584  s->theStatus = EVAL::WARNING_EXISTING_VARIABLE;
585  }else{
586  s->theStatus = EVAL::WARNING_EXISTING_FUNCTION;
587  }
588  }else{
589  (s->theDictionary)[item_name] = item;
590  s->theStatus = EVAL::OK;
591  }
592 }
593 
594 //---------------------------------------------------------------------------
595 namespace HepTool {
596 
597 //---------------------------------------------------------------------------
599  Struct * s = new Struct();
600  p = (void *) s;
601  s->theExpression = 0;
602  s->thePosition = 0;
603  s->theStatus = OK;
604  s->theResult = 0.0;
605 }
606 
607 //---------------------------------------------------------------------------
609  delete (Struct *)(p);
610 }
611 
612 //---------------------------------------------------------------------------
613 double Evaluator::evaluate(const char * expression) {
614  Struct * s = (Struct *)(p);
615  if (s->theExpression != 0) { delete[] s->theExpression; }
616  s->theExpression = 0;
617  s->thePosition = 0;
619  s->theResult = 0.0;
620  if (expression != 0) {
621  s->theExpression = new char[strlen(expression)+1];
622  strcpy(s->theExpression, expression);
624  s->theExpression+strlen(expression)-1,
625  s->theResult,
626  s->thePosition,
627  s->theDictionary);
628  }
629  return s->theResult;
630 }
631 
632 //---------------------------------------------------------------------------
633 int Evaluator::status() const {
634  return ((Struct *)(p))->theStatus;
635 }
636 
637 //---------------------------------------------------------------------------
639  return ((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression;
640 }
641 
642 //---------------------------------------------------------------------------
644  Struct * s = (Struct *) p;
645  if(s->theStatus != OK) {
646  std::cerr << error_name() << std::endl;
647  }
648  return;
649 }
650 
651 //---------------------------------------------------------------------------
652 std::string Evaluator::error_name() const
653 {
654  char prefix[] = "Evaluator : ";
655  std::ostringstream errn;
656  Struct * s = (Struct *) p;
657  switch (s->theStatus) {
658  case ERROR_NOT_A_NAME:
659  errn << prefix << "invalid name";
660  break;
661  case ERROR_SYNTAX_ERROR:
662  errn << prefix << "syntax error";
663  break;
665  errn << prefix << "unpaired parenthesis";
666  break;
668  errn << prefix << "unexpected symbol";
669  break;
671  errn << prefix << "unknown variable";
672  break;
674  errn << prefix << "unknown function";
675  break;
676  case ERROR_EMPTY_PARAMETER:
677  errn << prefix << "empty parameter in function call";
678  break;
680  errn << prefix << "calculation error";
681  break;
682  default:
683  errn << " ";
684  }
685  return errn.str();
686 }
687 
688 //---------------------------------------------------------------------------
689 void Evaluator::setVariable(const char * name, double value)
690 { setItem("", name, Item(value), (Struct *)p); }
691 
692 void Evaluator::setVariable(const char * name, const char * expression)
693 { setItem("", name, Item(expression), (Struct *)p); }
694 
695 //---------------------------------------------------------------------------
696 // Fix non ISO C++ compliant cast from pointer to function
697 // to void*, which is a pointer to an object
698 void Evaluator::setFunction(const char * name,
699  double (*fun)())
700 { setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
701 
702 void Evaluator::setFunction(const char * name,
703  double (*fun)(double))
704 { setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
705 
706 void Evaluator::setFunction(const char * name,
707  double (*fun)(double,double))
708 { setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
709 
710 void Evaluator::setFunction(const char * name,
711  double (*fun)(double,double,double))
712 { setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
713 
714 void Evaluator::setFunction(const char * name,
715  double (*fun)(double,double,double,double))
716 { setItem("4", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
717 
718 void Evaluator::setFunction(const char * name,
719  double (*fun)(double,double,double,double,double))
720 { setItem("5", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
721 
722 //---------------------------------------------------------------------------
723 bool Evaluator::findVariable(const char * name) const {
724  if (name == 0 || *name == '\0') return false;
725  const char * pointer; int n; REMOVE_BLANKS;
726  if (n == 0) return false;
727  Struct * s = (Struct *)(p);
728  return
729  ((s->theDictionary).find(string(pointer,n)) == (s->theDictionary).end()) ?
730  false : true;
731 }
732 
733 //---------------------------------------------------------------------------
734 bool Evaluator::findFunction(const char * name, int npar) const {
735  if (name == 0 || *name == '\0') return false;
736  if (npar < 0 || npar > MAX_N_PAR) return false;
737  const char * pointer; int n; REMOVE_BLANKS;
738  if (n == 0) return false;
739  Struct * s = (Struct *)(p);
740  return ((s->theDictionary).find(sss[npar]+string(pointer,n)) ==
741  (s->theDictionary).end()) ? false : true;
742 }
743 
744 //---------------------------------------------------------------------------
745 void Evaluator::removeVariable(const char * name) {
746  if (name == 0 || *name == '\0') return;
747  const char * pointer; int n; REMOVE_BLANKS;
748  if (n == 0) return;
749  Struct * s = (Struct *)(p);
750  (s->theDictionary).erase(string(pointer,n));
751 }
752 
753 //---------------------------------------------------------------------------
754 void Evaluator::removeFunction(const char * name, int npar) {
755  if (name == 0 || *name == '\0') return;
756  if (npar < 0 || npar > MAX_N_PAR) return;
757  const char * pointer; int n; REMOVE_BLANKS;
758  if (n == 0) return;
759  Struct * s = (Struct *)(p);
760  (s->theDictionary).erase(sss[npar]+string(pointer,n));
761 }
762 
763 //---------------------------------------------------------------------------
765  Struct * s = (Struct *) p;
766  s->theDictionary.clear();
767  s->theExpression = 0;
768  s->thePosition = 0;
769  s->theStatus = OK;
770  s->theResult = 0.0;
771 }
772 
773 //---------------------------------------------------------------------------
774 } // namespace HepTool