Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
42struct Struct {
47 double theResult;
48};
49
50//---------------------------------------------------------------------------
51#define EVAL HepTool::Evaluator
52
53#define REMOVE_BLANKS \
54for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
55for(n=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 int 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(int 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;
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 ((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
@ ERROR_UNPAIRED_PARENTHESIS
Definition: Evaluator.h:45
const char * name(G4int ptype)
Item()
Definition: Evaluator.cc:33
Item(double x)
Definition: Evaluator.cc:34
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
enum Item::@12 what
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