Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/Evaluator.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

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