CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

Evaluator.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 // $Id: Evaluator.cc,v 1.4 2010/07/20 17:00:49 garren Exp $
3 // ---------------------------------------------------------------------------
4 
5 #include "CLHEP/Evaluator/defs.h"
7 
8 #include <iostream>
9 #include <sstream>
10 #include <cmath> // for std::pow()
11 #include "stack.src"
12 #include "string.src"
13 #include "hash_map.src"
14 #include <string.h>
15 #include <ctype.h>
16 #include <errno.h>
17 #include <stdlib.h> // for strtod()
18 
19 //---------------------------------------------------------------------------
20 // Fix non ISO C++ compliant cast from pointer to function
21 // to void*, which is a pointer to an object
22 typedef void (*voidfuncptr)();
23 struct Item {
25  double variable;
26  string expression;
27  // Fix non ISO C++ compliant cast from pointer to function
28  // to void*, which is a pointer to an object
29  //void *function;
30  voidfuncptr function;
31 
32  Item() : what(UNKNOWN), variable(0),expression(), function(0) {}
33  Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
34  Item(string x) : what(EXPRESSION),variable(0),expression(x),function(0) {}
35  Item(voidfuncptr x) : what(FUNCTION), variable(0),expression(), function(x) {}
36 };
37 
38 typedef char * pchar;
39 typedef hash_map<string,Item> dic_type;
40 
41 struct Struct {
45  int theStatus;
46  double theResult;
47 };
48 
49 //---------------------------------------------------------------------------
50 #define EVAL HepTool::Evaluator
51 
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
55 
56 #define SKIP_BLANKS \
57 for(;;pointer++) { \
58  c = (pointer > end) ? '\0' : *pointer; \
59  if (!isspace(c)) break; \
60 }
61 
62 #define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
63 #define MAX_N_PAR 5
64 
65 static const char sss[MAX_N_PAR+2] = "012345";
66 
67 enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
69 
70 static int engine(pchar, pchar, double &, pchar &, const dic_type &);
71 
72 static int variable(const string & name, double & result,
73  const dic_type & dictionary)
74 /***********************************************************************
75  * *
76  * Name: variable Date: 03.10.00 *
77  * Author: Evgeni Chernyaev Revised: *
78  * *
79  * Function: Finds value of the variable. *
80  * This function is used by operand(). *
81  * *
82  * Parameters: *
83  * name - name of the variable. *
84  * result - value of the variable. *
85  * dictionary - dictionary of available variables and functions. *
86  * *
87  ***********************************************************************/
88 {
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;
93  switch (item.what) {
94  case Item::VARIABLE:
95  result = item.variable;
96  return EVAL::OK;
97  case Item::EXPRESSION: {
98  pchar exp_begin = (char *)(item.expression.c_str());
99  pchar exp_end = exp_begin + strlen(exp_begin) - 1;
100  if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
101  return EVAL::OK;
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];
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  case UNARY_PLUS: // unary operator '+'
333  val.top() = val1 + val2; // val1 is zero
334  return EVAL::OK;
335  case UNARY_MINUS: // unary operator '-'
336  val.top() = val1 - val2; // val1 is zero
337  return EVAL::OK;
338  default:
339  return EVAL::ERROR_CALCULATION_ERROR;
340  }
341 }
342 
343 /***********************************************************************
344  * *
345  * Name: engine Date: 28.09.00 *
346  * Author: Evgeni Chernyaev Revised: *
347  * *
348  * Function: Evaluates arithmetic expression. *
349  * *
350  * Parameters: *
351  * begin - pointer to the character string with expression. *
352  * end - pointer to the end of the character string (it is needed *
353  * for recursive call of engine(), when there is no '\0'). *
354  * result - result of the evaluation. *
355  * endp - pointer to the character where the evaluation stoped. *
356  * dictionary - dictionary of available variables and functions. *
357  * *
358  ***********************************************************************/
359 static int engine(pchar begin, pchar end, double & result,
360  pchar & endp, const dic_type & dictionary)
361 {
362  enum SyntaxTableEntry {
363  SyntaxError = 0,
364  NumberVariableOrFunction = 1,
365  UnaryPlusOrMinus = 2,
366  AnyOperator = 3
367  };
368  static const int SyntaxTable[19][19] = {
369  //E ( || && == != >= > <= < + - u+ u- * / ^ ) V - current token
370  { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // E - previous
371  { 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ( token
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 }, // unary +
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 }, // *
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 } // V = {.,N,C}
389  };
390  enum ActionTableEntry {
391  UnbalancedParentheses = -1,
392  ExpressionCompleted = 0,
393  HigherPrecedenceOperator = 1,
394  SamePrecedenceOperator = 2,
395  CloseProcessedParenthesesOrExpression = 3,
396  LowerPrecedenceOperator = 4
397  };
398  static const int ActionTable[17][18] = {
399  //E ( || && == != >= > <= < + - u+ u- * / ^ ) - current operator
400  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, // E - top operator
401  {-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, // ( in stack
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 }, // unary +
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, 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 } // ^
417  };
418 
419  stack<int> op; // operator stack
420  stack<pchar> pos; // position stack
421  stack<double> val; // value stack
422  double value;
423  pchar pointer = begin;
424  int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
425  char c;
426 
427  op.push(0); pos.push(pointer); // push EOL to the stack
428  SKIP_BLANKS;
429  if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
430  for(;;pointer++) {
431 
432  // N E X T T O K E N
433 
434  c = (pointer > end) ? '\0' : *pointer;
435  if (isspace(c)) continue; // skip space, tab etc.
436  switch (c) {
437  case '\0': iCur = ENDL; break;
438  case '(': iCur = LBRA; break;
439  case '|':
440  if (*(pointer+1) == '|') {
441  pointer++; iCur = OR; break;
442  }else{
443  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
444  }
445  case '&':
446  if (*(pointer+1) == '&') {
447  pointer++; iCur = AND; break;
448  }else{
449  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
450  }
451  case '=':
452  if (*(pointer+1) == '=') {
453  pointer++; iCur = EQ; break;
454  }else{
455  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
456  }
457  case '!':
458  if (*(pointer+1) == '=') {
459  pointer++; iCur = NE; break;
460  }else{
461  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
462  }
463  case '>':
464  if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; }
465  break;
466  case '<':
467  if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; }
468  break;
469  case '+': iCur = PLUS; break;
470  case '-': iCur = MINUS; break;
471  case '*':
472  if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; }
473  break;
474  case '/': iCur = DIV; break;
475  case '^': iCur = POW; break;
476  case ')': iCur = RBRA; break;
477  default:
478  if (c == '.' || isalnum(c)) {
479  iCur = VALUE; break;
480  }else{
481  EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
482  }
483  }
484 
485  // S Y N T A X A N A L I S Y S
486 
487  iWhat = SyntaxTable[iPrev][iCur];
488  iPrev = iCur;
489  switch (iWhat) {
490  case 0: // syntax error
491  EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
492  case 1: // operand: number, variable, function
493  EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
494  if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); }
495  val.push(value);
496  continue;
497  case 2: // unary + or unary -
498  val.push(0.0);
499  if (iCur == PLUS) iCur = UNARY_PLUS;
500  if (iCur == MINUS) iCur = UNARY_MINUS;
501  // Note that for syntax purposes, ordinary + or - are fine.
502  // Thus iPrev need not change when we encounter a unary minus or plus.
503  case 3: default: // next operator
504  break;
505  }
506 
507  // N E X T O P E R A T O R
508 
509  for(;;) {
510  if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
511  iTop = op.top();
512  switch (ActionTable[iTop][iCur]) {
513  case -1: // syntax error
514  if (op.size() > 1) pointer = pos.top();
515  EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
516  case 0: // last operation (assignment)
517  if (val.size() == 1) {
518  result = val.top();
519  EVAL_EXIT( EVAL::OK, pointer );
520  }else{
521  EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
522  }
523  case 1: // push current operator in stack
524  op.push(iCur); pos.push(pointer);
525  break;
526  case 2: // execute top operator
527  EVAL_STATUS = maker(iTop, val); // put current operator in stack
528  if (EVAL_STATUS != EVAL::OK) {
529  EVAL_EXIT( EVAL_STATUS, pos.top() );
530  }
531  op.top() = iCur; pos.top() = pointer;
532  break;
533  case 3: // delete '(' from stack
534  op.pop(); pos.pop();
535  break;
536  case 4: default: // execute top operator and
537  EVAL_STATUS = maker(iTop, val); // delete it from stack
538  if (EVAL_STATUS != EVAL::OK) { // repete with the same iCur
539  EVAL_EXIT( EVAL_STATUS, pos.top() );
540  }
541  op.pop(); pos.pop();
542  continue;
543  }
544  break;
545  }
546  }
547 }
548 
549 //---------------------------------------------------------------------------
550 static void setItem(const char * prefix, const char * name,
551  const Item & item, Struct * s) {
552 
553  if (name == 0 || *name == '\0') {
554  s->theStatus = EVAL::ERROR_NOT_A_NAME;
555  return;
556  }
557 
558  // 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
559 
560  const char * pointer; int n; REMOVE_BLANKS;
561 
562  // C H E C K N A M E
563 
564  if (n == 0) {
565  s->theStatus = EVAL::ERROR_NOT_A_NAME;
566  return;
567  }
568  for(int i=0; i<n; i++) {
569  char c = *(pointer+i);
570  if (c != '_' && !isalnum(c)) {
571  s->theStatus = EVAL::ERROR_NOT_A_NAME;
572  return;
573  }
574  }
575 
576  // A D D I T E M T O T H E D I C T I O N A R Y
577 
578  string item_name = prefix + string(pointer,n);
579  dic_type::iterator iter = (s->theDictionary).find(item_name);
580  if (iter != (s->theDictionary).end()) {
581  iter->second = item;
582  if (item_name == name) {
583  s->theStatus = EVAL::WARNING_EXISTING_VARIABLE;
584  }else{
585  s->theStatus = EVAL::WARNING_EXISTING_FUNCTION;
586  }
587  }else{
588  (s->theDictionary)[item_name] = item;
589  s->theStatus = EVAL::OK;
590  }
591 }
592 
593 //---------------------------------------------------------------------------
594 namespace HepTool {
595 
596 //---------------------------------------------------------------------------
597 Evaluator::Evaluator() {
598  Struct * s = new Struct();
599  p = (void *) s;
600  s->theExpression = 0;
601  s->thePosition = 0;
602  s->theStatus = OK;
603  s->theResult = 0.0;
604 }
605 
606 //---------------------------------------------------------------------------
607 Evaluator::~Evaluator() {
608  delete (Struct *)(p);
609 }
610 
611 //---------------------------------------------------------------------------
612 double Evaluator::evaluate(const char * expression) {
613  Struct * s = (Struct *)(p);
614  if (s->theExpression != 0) { delete[] s->theExpression; }
615  s->theExpression = 0;
616  s->thePosition = 0;
617  s->theStatus = WARNING_BLANK_STRING;
618  s->theResult = 0.0;
619  if (expression != 0) {
620  s->theExpression = new char[strlen(expression)+1];
621  strcpy(s->theExpression, expression);
622  s->theStatus = engine(s->theExpression,
623  s->theExpression+strlen(expression)-1,
624  s->theResult,
625  s->thePosition,
626  s->theDictionary);
627  }
628  return s->theResult;
629 }
630 
631 //---------------------------------------------------------------------------
632 int Evaluator::status() const {
633  return ((Struct *)(p))->theStatus;
634 }
635 
636 //---------------------------------------------------------------------------
637 int Evaluator::error_position() const {
638  return ((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression;
639 }
640 
641 //---------------------------------------------------------------------------
642 void Evaluator::print_error() const {
643  Struct * s = (Struct *) p;
644  if(s->theStatus != OK) {
645  std::cerr << error_name() << std::endl;
646  }
647  return;
648 }
649 
650 //---------------------------------------------------------------------------
651 std::string Evaluator::error_name() const
652 {
653  char prefix[] = "Evaluator : ";
654  std::ostringstream errn;
655  Struct * s = (Struct *) p;
656  switch (s->theStatus) {
657  case ERROR_NOT_A_NAME:
658  errn << prefix << "invalid name";
659  break;
660  case ERROR_SYNTAX_ERROR:
661  errn << prefix << "syntax error";
662  break;
663  case ERROR_UNPAIRED_PARENTHESIS:
664  errn << prefix << "unpaired parenthesis";
665  break;
666  case ERROR_UNEXPECTED_SYMBOL:
667  errn << prefix << "unexpected symbol";
668  break;
669  case ERROR_UNKNOWN_VARIABLE:
670  errn << prefix << "unknown variable";
671  break;
672  case ERROR_UNKNOWN_FUNCTION:
673  errn << prefix << "unknown function";
674  break;
675  case ERROR_EMPTY_PARAMETER:
676  errn << prefix << "empty parameter in function call";
677  break;
678  case ERROR_CALCULATION_ERROR:
679  errn << prefix << "calculation error";
680  break;
681  default:
682  errn << " ";
683  }
684  return errn.str();
685 }
686 
687 //---------------------------------------------------------------------------
688 void Evaluator::setVariable(const char * name, double value)
689 { setItem("", name, Item(value), (Struct *)p); }
690 
691 void Evaluator::setVariable(const char * name, const char * expression)
692 { setItem("", name, Item(expression), (Struct *)p); }
693 
694 //---------------------------------------------------------------------------
695 // Fix non ISO C++ compliant cast from pointer to function
696 // to void*, which is a pointer to an object
697 void Evaluator::setFunction(const char * name,
698  double (*fun)())
699 { setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
700 
701 void Evaluator::setFunction(const char * name,
702  double (*fun)(double))
703 { setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
704 
705 void Evaluator::setFunction(const char * name,
706  double (*fun)(double,double))
707 { setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
708 
709 void Evaluator::setFunction(const char * name,
710  double (*fun)(double,double,double))
711 { setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
712 
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); }
716 
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); }
720 
721 //---------------------------------------------------------------------------
722 bool Evaluator::findVariable(const char * name) const {
723  if (name == 0 || *name == '\0') return false;
724  const char * pointer; int n; REMOVE_BLANKS;
725  if (n == 0) return false;
726  Struct * s = (Struct *)(p);
727  return
728  ((s->theDictionary).find(string(pointer,n)) == (s->theDictionary).end()) ?
729  false : true;
730 }
731 
732 //---------------------------------------------------------------------------
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;
736  const char * pointer; int n; REMOVE_BLANKS;
737  if (n == 0) return false;
738  Struct * s = (Struct *)(p);
739  return ((s->theDictionary).find(sss[npar]+string(pointer,n)) ==
740  (s->theDictionary).end()) ? false : true;
741 }
742 
743 //---------------------------------------------------------------------------
744 void Evaluator::removeVariable(const char * name) {
745  if (name == 0 || *name == '\0') return;
746  const char * pointer; int n; REMOVE_BLANKS;
747  if (n == 0) return;
748  Struct * s = (Struct *)(p);
749  (s->theDictionary).erase(string(pointer,n));
750 }
751 
752 //---------------------------------------------------------------------------
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;
756  const char * pointer; int n; REMOVE_BLANKS;
757  if (n == 0) return;
758  Struct * s = (Struct *)(p);
759  (s->theDictionary).erase(sss[npar]+string(pointer,n));
760 }
761 
762 //---------------------------------------------------------------------------
763 void Evaluator::clear() {
764  Struct * s = (Struct *) p;
765  s->theDictionary.clear();
766  s->theExpression = 0;
767  s->thePosition = 0;
768  s->theStatus = OK;
769  s->theResult = 0.0;
770 }
771 
772 //---------------------------------------------------------------------------
773 } // namespace HepTool
Definition: Evaluator.cc:67
Definition: Evaluator.cc:67
Definition: Evaluator.cc:67
#define double(obj)
Definition: excDblThrow.cc:32
Definition: Evaluator.cc:67
hash_map< string, Item > dic_type
Definition: Evaluator.cc:39
Definition: Evaluator.cc:68
Definition: Evaluator.cc:68
int theStatus
Definition: Evaluator.cc:45
string expression
Definition: Evaluator.cc:26
Definition: Evaluator.cc:67
dic_type theDictionary
Definition: Evaluator.cc:42
#define REMOVE_BLANKS
Definition: Evaluator.cc:52
pchar theExpression
Definition: Evaluator.cc:43
Item(double x)
Definition: Evaluator.cc:33
double variable
Definition: Evaluator.cc:25
Definition: Evaluator.cc:67
#define EVAL_EXIT(STATUS, POSITION)
Definition: Evaluator.cc:62
Definition: Evaluator.cc:67
double theResult
Definition: Evaluator.cc:46
Item(string x)
Definition: Evaluator.cc:34
voidfuncptr function
Definition: Evaluator.cc:30
#define MAX_N_PAR
Definition: Evaluator.cc:63
Item(voidfuncptr x)
Definition: Evaluator.cc:35
enum Item::@3 what
Item()
Definition: Evaluator.cc:32
void(* voidfuncptr)()
Definition: Evaluator.cc:22
pchar thePosition
Definition: Evaluator.cc:44
#define SKIP_BLANKS
Definition: Evaluator.cc:56
unsigned evaluate()
Definition: Evaluator.cc:67
char * pchar
Definition: Evaluator.cc:38