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