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