Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
Evaluator.cc
Go to the documentation of this file.
1// -*- C++ -*-
2// ---------------------------------------------------------------------------
3
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
17using std::string;
18using 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
23typedef void (*voidfuncptr)();
24struct Item {
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;
32
34 Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
37};
38
39using pchar = char *;
40using dic_type = std::unordered_map<string, Item>;
41
49
50//---------------------------------------------------------------------------
51#define EVAL HepTool::Evaluator
52
53#define REMOVE_BLANKS \
54for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
55for(n=(int)strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
56
57#define SKIP_BLANKS \
58for(;;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
66static const char sss[MAX_N_PAR+2] = "012345";
67
68enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
70
71static int engine(pchar, pchar, double &, pchar &, const dic_type &);
72
73static 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
111static 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
166static 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;
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 ***********************************************************************/
288static 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 ***********************************************************************/
363static 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
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//---------------------------------------------------------------------------
554static 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//---------------------------------------------------------------------------
598namespace HepTool {
599
600//---------------------------------------------------------------------------
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//---------------------------------------------------------------------------
612 delete (Struct *)(p);
613}
614
615//---------------------------------------------------------------------------
616double 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//---------------------------------------------------------------------------
636int Evaluator::status() const {
637 return ((Struct *)(p))->theStatus;
638}
639
640//---------------------------------------------------------------------------
642 return int(((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression);
643}
644
645//---------------------------------------------------------------------------
647 Struct * s = (Struct *) p;
648 if(s->theStatus != OK) {
649 std::cerr << error_name() << std::endl;
650 }
651 return;
652}
653
654//---------------------------------------------------------------------------
655std::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;
665 errn << prefix << "syntax error";
666 break;
668 errn << prefix << "unpaired parenthesis";
669 break;
671 errn << prefix << "unexpected symbol";
672 break;
674 errn << prefix << "unknown variable";
675 break;
677 errn << prefix << "unknown function";
678 break;
680 errn << prefix << "empty parameter in function call";
681 break;
683 errn << prefix << "calculation error";
684 break;
685 default:
686 errn << " ";
687 }
688 return errn.str();
689}
690
691//---------------------------------------------------------------------------
692void Evaluator::setVariable(const char * name, double value)
693{ setItem("", name, Item(value), (Struct *)p); }
694
695void 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
701void Evaluator::setFunction(const char * name,
702 double (*fun)())
703{ setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
704
705void Evaluator::setFunction(const char * name,
706 double (*fun)(double))
707{ setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
708
709void Evaluator::setFunction(const char * name,
710 double (*fun)(double,double))
711{ setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
712
713void Evaluator::setFunction(const char * name,
714 double (*fun)(double,double,double))
715{ setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
716
717void Evaluator::setFunction(const char * name,
718 double (*fun)(double,double,double,double))
719{ setItem("4", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
720
721void 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//---------------------------------------------------------------------------
726bool 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//---------------------------------------------------------------------------
737bool 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//---------------------------------------------------------------------------
748void 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//---------------------------------------------------------------------------
757void 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//---------------------------------------------------------------------------
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
std::unordered_map< string, Item > dic_type
Definition Evaluator.cc:40
#define EVAL_EXIT(STATUS, POSITION)
Definition Evaluator.cc:63
#define MAX_N_PAR
Definition Evaluator.cc:64
char * pchar
Definition Evaluator.cc:39
#define REMOVE_BLANKS
Definition Evaluator.cc:53
#define SKIP_BLANKS
Definition Evaluator.cc:57
void(* voidfuncptr)()
Definition Evaluator.cc:23
@ RBRA
Definition Evaluator.cc:69
@ LBRA
Definition Evaluator.cc:68
@ GT
Definition Evaluator.cc:68
@ MULT
Definition Evaluator.cc:69
@ ENDL
Definition Evaluator.cc:68
@ POW
Definition Evaluator.cc:69
@ UNARY_MINUS
Definition Evaluator.cc:69
@ LT
Definition Evaluator.cc:68
@ NE
Definition Evaluator.cc:68
@ GE
Definition Evaluator.cc:68
@ UNARY_PLUS
Definition Evaluator.cc:69
@ LE
Definition Evaluator.cc:68
@ DIV
Definition Evaluator.cc:69
@ AND
Definition Evaluator.cc:68
@ PLUS
Definition Evaluator.cc:69
@ OR
Definition Evaluator.cc:68
@ EQ
Definition Evaluator.cc:68
@ VALUE
Definition Evaluator.cc:69
@ MINUS
Definition Evaluator.cc:69
G4double(*)(G4double) function
int error_position() const
Definition Evaluator.cc:641
bool findFunction(const char *name, int npar) const
Definition Evaluator.cc:737
void print_error() const
Definition Evaluator.cc:646
double evaluate(const char *expression)
Definition Evaluator.cc:616
std::string error_name() const
Definition Evaluator.cc:655
void removeVariable(const char *name)
Definition Evaluator.cc:748
void removeFunction(const char *name, int npar)
Definition Evaluator.cc:757
void setFunction(const char *name, double(*fun)())
Definition Evaluator.cc:701
void setVariable(const char *name, double value)
Definition Evaluator.cc:692
int status() const
Definition Evaluator.cc:636
bool findVariable(const char *name) const
Definition Evaluator.cc:726
const char * name(G4int ptype)
Item()
Definition Evaluator.cc:33
Item(double x)
Definition Evaluator.cc:34
enum Item::@9 what
voidfuncptr function
Definition Evaluator.cc:31
string expression
Definition Evaluator.cc:27
Item(string x)
Definition Evaluator.cc:35
Item(voidfuncptr x)
Definition Evaluator.cc:36
double variable
Definition Evaluator.cc:26
@ VARIABLE
Definition Evaluator.cc:25
@ EXPRESSION
Definition Evaluator.cc:25
@ UNKNOWN
Definition Evaluator.cc:25
@ FUNCTION
Definition Evaluator.cc:25
pchar thePosition
Definition Evaluator.cc:45
pchar theExpression
Definition Evaluator.cc:44
int theStatus
Definition Evaluator.cc:46
dic_type theDictionary
Definition Evaluator.cc:43
double theResult
Definition Evaluator.cc:47