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 
33  Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
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:
153  (pp[3],pp[2],pp[1],pp[0]);
154  break;
155  case 5:
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 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
638  return ((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression;
639 }
640 
641 //---------------------------------------------------------------------------
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;
664  errn << prefix << "unpaired parenthesis";
665  break;
667  errn << prefix << "unexpected symbol";
668  break;
670  errn << prefix << "unknown variable";
671  break;
673  errn << prefix << "unknown function";
674  break;
675  case ERROR_EMPTY_PARAMETER:
676  errn << prefix << "empty parameter in function call";
677  break;
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 //---------------------------------------------------------------------------
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
NE
@ NE
Definition: Evaluator.cc:67
double
#define double(obj)
Definition: excDblThrow.cc:32
HepTool::Evaluator::findFunction
bool findFunction(const char *name, int npar) const
Definition: Evaluator.cc:733
HepTool::Evaluator::ERROR_SYNTAX_ERROR
@ ERROR_SYNTAX_ERROR
Definition: CLHEP/Evaluator/Evaluator.h:45
GE
@ GE
Definition: Evaluator.cc:67
PLUS
@ PLUS
Definition: Evaluator.cc:68
HepTool::Evaluator::ERROR_NOT_A_NAME
@ ERROR_NOT_A_NAME
Definition: CLHEP/Evaluator/Evaluator.h:44
UNARY_MINUS
@ UNARY_MINUS
Definition: Evaluator.cc:68
HepTool::Evaluator::removeVariable
void removeVariable(const char *name)
Definition: Evaluator.cc:744
GT
@ GT
Definition: Evaluator.cc:67
Item::UNKNOWN
@ UNKNOWN
Definition: Evaluator.cc:24
HepTool::Evaluator::Evaluator
Evaluator()
Definition: Evaluator.cc:597
HepTool::Evaluator::ERROR_CALCULATION_ERROR
@ ERROR_CALCULATION_ERROR
Definition: CLHEP/Evaluator/Evaluator.h:51
voidfuncptr
void(* voidfuncptr)()
Definition: Evaluator.cc:22
HepTool::Evaluator::~Evaluator
~Evaluator()
Definition: Evaluator.cc:607
REMOVE_BLANKS
#define REMOVE_BLANKS
Definition: Evaluator.cc:52
HepTool::Evaluator::ERROR_UNEXPECTED_SYMBOL
@ ERROR_UNEXPECTED_SYMBOL
Definition: CLHEP/Evaluator/Evaluator.h:47
Item
Definition: Evaluator.cc:23
LT
@ LT
Definition: Evaluator.cc:67
OR
@ OR
Definition: Evaluator.cc:67
DIV
@ DIV
Definition: Evaluator.cc:68
Item::expression
string expression
Definition: Evaluator.cc:26
SKIP_BLANKS
#define SKIP_BLANKS
Definition: Evaluator.cc:56
HepTool::Evaluator::status
int status() const
Definition: Evaluator.cc:632
HepTool::Evaluator::clear
void clear()
Definition: Evaluator.cc:763
CLHEP::detail::n
n
Definition: Ranlux64Engine.cc:85
erase
user code seldom needs to call this function directly ZMerrno whether or not they are still recorded ZMerrno whether or not they are still since the user counter was last ZMerrno while ZMerrno ZMerrno while ZMerrno to note the handler and logger used when the exception was ZMthrow n etc The resulting pointer should generally be checked against in case ZMerrno does not go back as far as requested ZMerrno erase() Remove the most recently-recorded exception. This can be useful if
Item::Item
Item(double x)
Definition: Evaluator.cc:33
HepTool::Evaluator::ERROR_UNKNOWN_VARIABLE
@ ERROR_UNKNOWN_VARIABLE
Definition: CLHEP/Evaluator/Evaluator.h:48
Struct::theStatus
int theStatus
Definition: Evaluator.cc:45
POW
@ POW
Definition: Evaluator.cc:68
UNARY_PLUS
@ UNARY_PLUS
Definition: Evaluator.cc:68
LE
@ LE
Definition: Evaluator.cc:67
Struct::theDictionary
dic_type theDictionary
Definition: Evaluator.cc:42
prefix
any previously defined ZMexception may be used as the parent Oops is the exception s name as it is to appear in the log Such a quoted exception name string should for clarity be closely related to the actual name but as shown here might omit some package identifying baggage ExcTest is the logged message prefix(normally indicating the package, facility, or program giving rise to the message). 5) ZMexWARNING is the default severity level of ZMxOops.(See below for a complete list of possible severity levels and the intended significance of each.) 3. Constructing/throwing an instance of the new exception class --------------------------------------------------------------- This Exceptions package provides a facility
MULT
@ MULT
Definition: Evaluator.cc:68
Item::FUNCTION
@ FUNCTION
Definition: Evaluator.cc:24
Struct
Definition: Evaluator.cc:41
defs.h
void
We should separate methods that force the load of the Rotation class For practical that implies that methods like and that as in the ThreeVector class we separate the cc files Also again we have the rotation methods returning HepLorentzVector &rather than void
Definition: minorMergeIssues.doc:148
Struct::theExpression
pchar theExpression
Definition: Evaluator.cc:43
HepTool
Definition: CLHEP/Evaluator/Evaluator.h:10
result
this formatted text is the function s string result this method sends the formatted string s to the ostream destination specified when the logger was instantiated as its result
Definition: ZMthrow_event_sequence.txt:148
HepTool::Evaluator::setVariable
void setVariable(const char *name, double value)
Definition: Evaluator.cc:688
EVAL_EXIT
#define EVAL_EXIT(STATUS, POSITION)
Definition: Evaluator.cc:62
AND
@ AND
Definition: Evaluator.cc:67
HepTool::Evaluator::findVariable
bool findVariable(const char *name) const
Definition: Evaluator.cc:722
MAX_N_PAR
#define MAX_N_PAR
Definition: Evaluator.cc:63
HepTool::Evaluator::error_name
std::string error_name() const
Definition: Evaluator.cc:651
Item::Item
Item()
Definition: Evaluator.cc:32
HepTool::Evaluator::setFunction
void setFunction(const char *name, double(*fun)())
Definition: Evaluator.cc:697
dic_type
hash_map< string, Item > dic_type
Definition: Evaluator.cc:39
HepTool::Evaluator::ERROR_EMPTY_PARAMETER
@ ERROR_EMPTY_PARAMETER
Definition: CLHEP/Evaluator/Evaluator.h:50
Item::variable
double variable
Definition: Evaluator.cc:25
s
Methods applicble to containers of as in std::list< LorentzVector > s
Definition: keyMergeIssues.doc:328
Item::VARIABLE
@ VARIABLE
Definition: Evaluator.cc:24
HepTool::Evaluator::error_position
int error_position() const
Definition: Evaluator.cc:637
HepTool::Evaluator::OK
@ OK
Definition: CLHEP/Evaluator/Evaluator.h:40
Item::function
voidfuncptr function
Definition: Evaluator.cc:30
RBRA
@ RBRA
Definition: Evaluator.cc:68
i
long i
Definition: JamesRandomSeeding.txt:27
Struct::thePosition
pchar thePosition
Definition: Evaluator.cc:44
HepTool::Evaluator::ERROR_UNKNOWN_FUNCTION
@ ERROR_UNKNOWN_FUNCTION
Definition: CLHEP/Evaluator/Evaluator.h:49
ENDL
@ ENDL
Definition: Evaluator.cc:67
Struct::theResult
double theResult
Definition: Evaluator.cc:46
Item::Item
Item(string x)
Definition: Evaluator.cc:34
VALUE
@ VALUE
Definition: Evaluator.cc:68
HepTool::Evaluator::evaluate
double evaluate(const char *expression)
Definition: Evaluator.cc:612
x
any side effects of that construction would occur twice The semantics of throw x
Definition: whyZMthrowRethrows.txt:37
EQ
@ EQ
Definition: Evaluator.cc:67
Item::EXPRESSION
@ EXPRESSION
Definition: Evaluator.cc:24
Evaluator.h
HepTool::Evaluator::print_error
void print_error() const
Definition: Evaluator.cc:642
name
user code seldom needs to call this function directly ZMerrno whether or not they are still recorded ZMerrno whether or not they are still since the user counter was last ZMerrno name() gives the(string) name of the latest recorded exception
HepTool::Evaluator::WARNING_BLANK_STRING
@ WARNING_BLANK_STRING
Definition: CLHEP/Evaluator/Evaluator.h:43
pchar
char * pchar
Definition: Evaluator.cc:38
HepTool::Evaluator::ERROR_UNPAIRED_PARENTHESIS
@ ERROR_UNPAIRED_PARENTHESIS
Definition: CLHEP/Evaluator/Evaluator.h:46
LBRA
@ LBRA
Definition: Evaluator.cc:67
HepTool::Evaluator::removeFunction
void removeFunction(const char *name, int npar)
Definition: Evaluator.cc:753
MINUS
@ MINUS
Definition: Evaluator.cc:68
Item::what
enum Item::@3 what
Item::Item
Item(voidfuncptr x)
Definition: Evaluator.cc:35