Import Geant4 9.5.0 source tree
This commit is contained in:
+772
@@ -0,0 +1,772 @@
|
||||
// -*- C++ -*-
|
||||
// $Id:$
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include "CLHEP/Evaluator/Evaluator.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cmath> // for std::pow()
|
||||
#include "CLHEP/Evaluator/stack.icc"
|
||||
#include "CLHEP/Evaluator/string.icc"
|
||||
#include "CLHEP/Evaluator/hash_map.icc"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h> // for strtod()
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Fix non ISO C++ compliant cast from pointer to function
|
||||
// to void*, which is a pointer to an object
|
||||
typedef void (*voidfuncptr)();
|
||||
struct Item {
|
||||
enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTION } what;
|
||||
double variable;
|
||||
string expression;
|
||||
// Fix non ISO C++ compliant cast from pointer to function
|
||||
// to void*, which is a pointer to an object
|
||||
//void *function;
|
||||
voidfuncptr function;
|
||||
|
||||
Item() : what(UNKNOWN), variable(0),expression(), function(0) {}
|
||||
Item(double x) : what(VARIABLE), variable(x),expression(), function(0) {}
|
||||
Item(string x) : what(EXPRESSION),variable(0),expression(x),function(0) {}
|
||||
Item(voidfuncptr x) : what(FUNCTION), variable(0),expression(), function(x) {}
|
||||
};
|
||||
|
||||
typedef char * pchar;
|
||||
typedef hash_map<string,Item> dic_type;
|
||||
|
||||
struct Struct {
|
||||
dic_type theDictionary;
|
||||
pchar theExpression;
|
||||
pchar thePosition;
|
||||
int theStatus;
|
||||
double theResult;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#define EVAL HepTool::Evaluator
|
||||
|
||||
#define REMOVE_BLANKS \
|
||||
for(pointer=name;;pointer++) if (!isspace(*pointer)) break; \
|
||||
for(n=strlen(pointer);n>0;n--) if (!isspace(*(pointer+n-1))) break
|
||||
|
||||
#define SKIP_BLANKS \
|
||||
for(;;pointer++) { \
|
||||
c = (pointer > end) ? '\0' : *pointer; \
|
||||
if (!isspace(c)) break; \
|
||||
}
|
||||
|
||||
#define EVAL_EXIT(STATUS,POSITION) endp = POSITION; return STATUS
|
||||
#define MAX_N_PAR 5
|
||||
|
||||
static const char sss[MAX_N_PAR+2] = "012345";
|
||||
|
||||
enum { ENDL, LBRA, OR, AND, EQ, NE, GE, GT, LE, LT,
|
||||
PLUS, MINUS, UNARY_PLUS, UNARY_MINUS, MULT, DIV, POW, RBRA, VALUE };
|
||||
|
||||
static int engine(pchar, pchar, double &, pchar &, const dic_type &);
|
||||
|
||||
static int variable(const string & name, double & result,
|
||||
const dic_type & dictionary)
|
||||
/***********************************************************************
|
||||
* *
|
||||
* Name: variable Date: 03.10.00 *
|
||||
* Author: Evgeni Chernyaev Revised: *
|
||||
* *
|
||||
* Function: Finds value of the variable. *
|
||||
* This function is used by operand(). *
|
||||
* *
|
||||
* Parameters: *
|
||||
* name - name of the variable. *
|
||||
* result - value of the variable. *
|
||||
* dictionary - dictionary of available variables and functions. *
|
||||
* *
|
||||
***********************************************************************/
|
||||
{
|
||||
dic_type::const_iterator iter = dictionary.find(name);
|
||||
if (iter == dictionary.end())
|
||||
return EVAL::ERROR_UNKNOWN_VARIABLE;
|
||||
Item item = iter->second;
|
||||
switch (item.what) {
|
||||
case Item::VARIABLE:
|
||||
result = item.variable;
|
||||
return EVAL::OK;
|
||||
case Item::EXPRESSION: {
|
||||
pchar exp_begin = (char *)(item.expression.c_str());
|
||||
pchar exp_end = exp_begin + strlen(exp_begin) - 1;
|
||||
if (engine(exp_begin, exp_end, result, exp_end, dictionary) == EVAL::OK)
|
||||
return EVAL::OK;
|
||||
}
|
||||
default:
|
||||
return EVAL::ERROR_CALCULATION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static int function(const string & name, stack<double> & par,
|
||||
double & result, const dic_type & dictionary)
|
||||
/***********************************************************************
|
||||
* *
|
||||
* Name: function Date: 03.10.00 *
|
||||
* Author: Evgeni Chernyaev Revised: *
|
||||
* *
|
||||
* Function: Finds value of the function. *
|
||||
* This function is used by operand(). *
|
||||
* *
|
||||
* Parameters: *
|
||||
* name - name of the function. *
|
||||
* par - stack of parameters. *
|
||||
* result - value of the function. *
|
||||
* dictionary - dictionary of available variables and functions. *
|
||||
* *
|
||||
***********************************************************************/
|
||||
{
|
||||
int npar = par.size();
|
||||
if (npar > MAX_N_PAR) return EVAL::ERROR_UNKNOWN_FUNCTION;
|
||||
|
||||
dic_type::const_iterator iter = dictionary.find(sss[npar]+name);
|
||||
if (iter == dictionary.end()) return EVAL::ERROR_UNKNOWN_FUNCTION;
|
||||
Item item = iter->second;
|
||||
|
||||
double pp[MAX_N_PAR];
|
||||
for(int i=0; i<npar; i++) { pp[i] = par.top(); par.pop(); }
|
||||
errno = 0;
|
||||
if (item.function == 0) return EVAL::ERROR_CALCULATION_ERROR;
|
||||
switch (npar) {
|
||||
case 0:
|
||||
result = ((double (*)())item.function)();
|
||||
break;
|
||||
case 1:
|
||||
result = ((double (*)(double))item.function)(pp[0]);
|
||||
break;
|
||||
case 2:
|
||||
result = ((double (*)(double,double))item.function)(pp[1], pp[0]);
|
||||
break;
|
||||
case 3:
|
||||
result = ((double (*)(double,double,double))item.function)
|
||||
(pp[2],pp[1],pp[0]);
|
||||
break;
|
||||
case 4:
|
||||
result = ((double (*)(double,double,double,double))item.function)
|
||||
(pp[3],pp[2],pp[1],pp[0]);
|
||||
break;
|
||||
case 5:
|
||||
result = ((double (*)(double,double,double,double,double))item.function)
|
||||
(pp[4],pp[3],pp[2],pp[1],pp[0]);
|
||||
break;
|
||||
}
|
||||
return (errno == 0) ? EVAL::OK : EVAL::ERROR_CALCULATION_ERROR;
|
||||
}
|
||||
|
||||
static int operand(pchar begin, pchar end, double & result,
|
||||
pchar & endp, const dic_type & dictionary)
|
||||
/***********************************************************************
|
||||
* *
|
||||
* Name: operand Date: 03.10.00 *
|
||||
* Author: Evgeni Chernyaev Revised: *
|
||||
* *
|
||||
* Function: Finds value of the operand. The operand can be either *
|
||||
* a number or a variable or a function. *
|
||||
* This function is used by engine(). *
|
||||
* *
|
||||
* Parameters: *
|
||||
* begin - pointer to the first character of the operand. *
|
||||
* end - pointer to the last character of the character string. *
|
||||
* result - value of the operand. *
|
||||
* endp - pointer to the character where the evaluation stoped. *
|
||||
* dictionary - dictionary of available variables and functions. *
|
||||
* *
|
||||
***********************************************************************/
|
||||
{
|
||||
pchar pointer = begin;
|
||||
int EVAL_STATUS;
|
||||
char c;
|
||||
|
||||
// G E T N U M B E R
|
||||
|
||||
if (!isalpha(*pointer)) {
|
||||
errno = 0;
|
||||
result = strtod(pointer, (char **)(&pointer));
|
||||
if (errno == 0) {
|
||||
EVAL_EXIT( EVAL::OK, --pointer );
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_CALCULATION_ERROR, begin );
|
||||
}
|
||||
}
|
||||
|
||||
// G E T N A M E
|
||||
|
||||
while(pointer <= end) {
|
||||
c = *pointer;
|
||||
if (c != '_' && !isalnum(c)) break;
|
||||
pointer++;
|
||||
}
|
||||
c = *pointer;
|
||||
*pointer = '\0';
|
||||
string name(begin);
|
||||
*pointer = c;
|
||||
|
||||
// G E T V A R I A B L E
|
||||
|
||||
result = 0.0;
|
||||
SKIP_BLANKS;
|
||||
if (c != '(') {
|
||||
EVAL_STATUS = variable(name, result, dictionary);
|
||||
EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? --pointer : begin);
|
||||
}
|
||||
|
||||
// G E T F U N C T I O N
|
||||
|
||||
stack<pchar> pos; // position stack
|
||||
stack<double> par; // parameter stack
|
||||
double value;
|
||||
pchar par_begin = pointer+1, par_end;
|
||||
|
||||
for(;;pointer++) {
|
||||
c = (pointer > end) ? '\0' : *pointer;
|
||||
switch (c) {
|
||||
case '\0':
|
||||
EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pos.top() );
|
||||
case '(':
|
||||
pos.push(pointer); break;
|
||||
case ',':
|
||||
if (pos.size() == 1) {
|
||||
par_end = pointer-1;
|
||||
EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
|
||||
if (EVAL_STATUS == EVAL::WARNING_BLANK_STRING)
|
||||
{ EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
|
||||
if (EVAL_STATUS != EVAL::OK)
|
||||
{ EVAL_EXIT( EVAL_STATUS, par_end ); }
|
||||
par.push(value);
|
||||
par_begin = pointer + 1;
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
if (pos.size() > 1) {
|
||||
pos.pop();
|
||||
break;
|
||||
}else{
|
||||
par_end = pointer-1;
|
||||
EVAL_STATUS = engine(par_begin, par_end, value, par_end, dictionary);
|
||||
switch (EVAL_STATUS) {
|
||||
case EVAL::OK:
|
||||
par.push(value);
|
||||
break;
|
||||
case EVAL::WARNING_BLANK_STRING:
|
||||
if (par.size() != 0)
|
||||
{ EVAL_EXIT( EVAL::ERROR_EMPTY_PARAMETER, --par_end ); }
|
||||
break;
|
||||
default:
|
||||
EVAL_EXIT( EVAL_STATUS, par_end );
|
||||
}
|
||||
EVAL_STATUS = function(name, par, result, dictionary);
|
||||
EVAL_EXIT( EVAL_STATUS, (EVAL_STATUS == EVAL::OK) ? pointer : begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* *
|
||||
* Name: maker Date: 28.09.00 *
|
||||
* Author: Evgeni Chernyaev Revised: *
|
||||
* *
|
||||
* Function: Executes basic arithmetic operations on values in the top *
|
||||
* of the stack. Result is placed back into the stack. *
|
||||
* This function is used by engine(). *
|
||||
* *
|
||||
* Parameters: *
|
||||
* op - code of the operation. *
|
||||
* val - stack of values. *
|
||||
* *
|
||||
***********************************************************************/
|
||||
static int maker(int op, stack<double> & val)
|
||||
{
|
||||
if (val.size() < 2) return EVAL::ERROR_SYNTAX_ERROR;
|
||||
double val2 = val.top(); val.pop();
|
||||
double val1 = val.top();
|
||||
switch (op) {
|
||||
case OR: // operator ||
|
||||
val.top() = (val1 || val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case AND: // operator &&
|
||||
val.top() = (val1 && val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case EQ: // operator ==
|
||||
val.top() = (val1 == val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case NE: // operator !=
|
||||
val.top() = (val1 != val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case GE: // operator >=
|
||||
val.top() = (val1 >= val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case GT: // operator >
|
||||
val.top() = (val1 > val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case LE: // operator <=
|
||||
val.top() = (val1 <= val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case LT: // operator <
|
||||
val.top() = (val1 < val2) ? 1. : 0.;
|
||||
return EVAL::OK;
|
||||
case PLUS: // operator '+'
|
||||
val.top() = val1 + val2;
|
||||
return EVAL::OK;
|
||||
case MINUS: // operator '-'
|
||||
val.top() = val1 - val2;
|
||||
return EVAL::OK;
|
||||
case MULT: // operator '*'
|
||||
val.top() = val1 * val2;
|
||||
return EVAL::OK;
|
||||
case DIV: // operator '/'
|
||||
if (val2 == 0.0) return EVAL::ERROR_CALCULATION_ERROR;
|
||||
val.top() = val1 / val2;
|
||||
return EVAL::OK;
|
||||
case POW: // operator '^' (or '**')
|
||||
errno = 0;
|
||||
val.top() = std::pow(val1,val2);
|
||||
if (errno == 0) return EVAL::OK;
|
||||
case UNARY_PLUS: // unary operator '+'
|
||||
val.top() = val1 + val2; // val1 is zero
|
||||
return EVAL::OK;
|
||||
case UNARY_MINUS: // unary operator '-'
|
||||
val.top() = val1 - val2; // val1 is zero
|
||||
return EVAL::OK;
|
||||
default:
|
||||
return EVAL::ERROR_CALCULATION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* *
|
||||
* Name: engine Date: 28.09.00 *
|
||||
* Author: Evgeni Chernyaev Revised: *
|
||||
* *
|
||||
* Function: Evaluates arithmetic expression. *
|
||||
* *
|
||||
* Parameters: *
|
||||
* begin - pointer to the character string with expression. *
|
||||
* end - pointer to the end of the character string (it is needed *
|
||||
* for recursive call of engine(), when there is no '\0'). *
|
||||
* result - result of the evaluation. *
|
||||
* endp - pointer to the character where the evaluation stoped. *
|
||||
* dictionary - dictionary of available variables and functions. *
|
||||
* *
|
||||
***********************************************************************/
|
||||
static int engine(pchar begin, pchar end, double & result,
|
||||
pchar & endp, const dic_type & dictionary)
|
||||
{
|
||||
enum SyntaxTableEntry {
|
||||
SyntaxError = 0,
|
||||
NumberVariableOrFunction = 1,
|
||||
UnaryPlusOrMinus = 2,
|
||||
AnyOperator = 3
|
||||
};
|
||||
static const int SyntaxTable[19][19] = {
|
||||
//E ( || && == != >= > <= < + - u+ u- * / ^ ) V - current token
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // E - previous
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ( token
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ||
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // &&
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ==
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // !=
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // >=
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // >
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // <=
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // <
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // +
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // -
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary +
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // unary -
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // *
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // /
|
||||
{ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1 }, // ^
|
||||
{ 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 }, // )
|
||||
{ 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0 } // V = {.,N,C}
|
||||
};
|
||||
enum ActionTableEntry {
|
||||
UnbalancedParentheses = -1,
|
||||
ExpressionCompleted = 0,
|
||||
HigherPrecedenceOperator = 1,
|
||||
SamePrecedenceOperator = 2,
|
||||
CloseProcessedParenthesesOrExpression = 3,
|
||||
LowerPrecedenceOperator = 4
|
||||
};
|
||||
static const int ActionTable[17][18] = {
|
||||
//E ( || && == != >= > <= < + - u+ u- * / ^ ) - current operator
|
||||
{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1 }, // E - top operator
|
||||
{-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }, // ( in stack
|
||||
{ 4, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // ||
|
||||
{ 4, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // &&
|
||||
{ 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // ==
|
||||
{ 4, 1, 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4 }, // !=
|
||||
{ 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >=
|
||||
{ 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // >
|
||||
{ 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <=
|
||||
{ 4, 1, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 4 }, // <
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // +
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 1, 1, 1, 1, 1, 4 }, // -
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }, // unary +
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 }, // unary -
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // *
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 2, 1, 4 }, // /
|
||||
{ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 4 } // ^
|
||||
};
|
||||
|
||||
stack<int> op; // operator stack
|
||||
stack<pchar> pos; // position stack
|
||||
stack<double> val; // value stack
|
||||
double value;
|
||||
pchar pointer = begin;
|
||||
int iWhat, iCur, iPrev = 0, iTop, EVAL_STATUS;
|
||||
char c;
|
||||
|
||||
op.push(0); pos.push(pointer); // push EOL to the stack
|
||||
SKIP_BLANKS;
|
||||
if (c == '\0') { EVAL_EXIT( EVAL::WARNING_BLANK_STRING, begin ); }
|
||||
for(;;pointer++) {
|
||||
|
||||
// N E X T T O K E N
|
||||
|
||||
c = (pointer > end) ? '\0' : *pointer;
|
||||
if (isspace(c)) continue; // skip space, tab etc.
|
||||
switch (c) {
|
||||
case '\0': iCur = ENDL; break;
|
||||
case '(': iCur = LBRA; break;
|
||||
case '|':
|
||||
if (*(pointer+1) == '|') {
|
||||
pointer++; iCur = OR; break;
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
|
||||
}
|
||||
case '&':
|
||||
if (*(pointer+1) == '&') {
|
||||
pointer++; iCur = AND; break;
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
|
||||
}
|
||||
case '=':
|
||||
if (*(pointer+1) == '=') {
|
||||
pointer++; iCur = EQ; break;
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
|
||||
}
|
||||
case '!':
|
||||
if (*(pointer+1) == '=') {
|
||||
pointer++; iCur = NE; break;
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
|
||||
}
|
||||
case '>':
|
||||
if (*(pointer+1) == '=') { pointer++; iCur = GE; } else { iCur = GT; }
|
||||
break;
|
||||
case '<':
|
||||
if (*(pointer+1) == '=') { pointer++; iCur = LE; } else { iCur = LT; }
|
||||
break;
|
||||
case '+': iCur = PLUS; break;
|
||||
case '-': iCur = MINUS; break;
|
||||
case '*':
|
||||
if (*(pointer+1) == '*') { pointer++; iCur = POW; }else{ iCur = MULT; }
|
||||
break;
|
||||
case '/': iCur = DIV; break;
|
||||
case '^': iCur = POW; break;
|
||||
case ')': iCur = RBRA; break;
|
||||
default:
|
||||
if (c == '.' || isalnum(c)) {
|
||||
iCur = VALUE; break;
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_UNEXPECTED_SYMBOL, pointer );
|
||||
}
|
||||
}
|
||||
|
||||
// S Y N T A X A N A L I S Y S
|
||||
|
||||
iWhat = SyntaxTable[iPrev][iCur];
|
||||
iPrev = iCur;
|
||||
switch (iWhat) {
|
||||
case 0: // syntax error
|
||||
EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
|
||||
case 1: // operand: number, variable, function
|
||||
EVAL_STATUS = operand(pointer, end, value, pointer, dictionary);
|
||||
if (EVAL_STATUS != EVAL::OK) { EVAL_EXIT( EVAL_STATUS, pointer ); }
|
||||
val.push(value);
|
||||
continue;
|
||||
case 2: // unary + or unary -
|
||||
val.push(0.0);
|
||||
if (iCur == PLUS) iCur = UNARY_PLUS;
|
||||
if (iCur == MINUS) iCur = UNARY_MINUS;
|
||||
// Note that for syntax purposes, ordinary + or - are fine.
|
||||
// Thus iPrev need not change when we encounter a unary minus or plus.
|
||||
case 3: default: // next operator
|
||||
break;
|
||||
}
|
||||
|
||||
// N E X T O P E R A T O R
|
||||
|
||||
for(;;) {
|
||||
if (op.size() == 0) { EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); }
|
||||
iTop = op.top();
|
||||
switch (ActionTable[iTop][iCur]) {
|
||||
case -1: // syntax error
|
||||
if (op.size() > 1) pointer = pos.top();
|
||||
EVAL_EXIT( EVAL::ERROR_UNPAIRED_PARENTHESIS, pointer );
|
||||
case 0: // last operation (assignment)
|
||||
if (val.size() == 1) {
|
||||
result = val.top();
|
||||
EVAL_EXIT( EVAL::OK, pointer );
|
||||
}else{
|
||||
EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer );
|
||||
}
|
||||
case 1: // push current operator in stack
|
||||
op.push(iCur); pos.push(pointer);
|
||||
break;
|
||||
case 2: // execute top operator
|
||||
EVAL_STATUS = maker(iTop, val); // put current operator in stack
|
||||
if (EVAL_STATUS != EVAL::OK) {
|
||||
EVAL_EXIT( EVAL_STATUS, pos.top() );
|
||||
}
|
||||
op.top() = iCur; pos.top() = pointer;
|
||||
break;
|
||||
case 3: // delete '(' from stack
|
||||
op.pop(); pos.pop();
|
||||
break;
|
||||
case 4: default: // execute top operator and
|
||||
EVAL_STATUS = maker(iTop, val); // delete it from stack
|
||||
if (EVAL_STATUS != EVAL::OK) { // repete with the same iCur
|
||||
EVAL_EXIT( EVAL_STATUS, pos.top() );
|
||||
}
|
||||
op.pop(); pos.pop();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static void setItem(const char * prefix, const char * name,
|
||||
const Item & item, Struct * s) {
|
||||
|
||||
if (name == 0 || *name == '\0') {
|
||||
s->theStatus = EVAL::ERROR_NOT_A_NAME;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
const char * pointer; int n; REMOVE_BLANKS;
|
||||
|
||||
// C H E C K N A M E
|
||||
|
||||
if (n == 0) {
|
||||
s->theStatus = EVAL::ERROR_NOT_A_NAME;
|
||||
return;
|
||||
}
|
||||
for(int i=0; i<n; i++) {
|
||||
char c = *(pointer+i);
|
||||
if (c != '_' && !isalnum(c)) {
|
||||
s->theStatus = EVAL::ERROR_NOT_A_NAME;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A D D I T E M T O T H E D I C T I O N A R Y
|
||||
|
||||
string item_name = prefix + string(pointer,n);
|
||||
dic_type::iterator iter = (s->theDictionary).find(item_name);
|
||||
if (iter != (s->theDictionary).end()) {
|
||||
iter->second = item;
|
||||
if (item_name == name) {
|
||||
s->theStatus = EVAL::WARNING_EXISTING_VARIABLE;
|
||||
}else{
|
||||
s->theStatus = EVAL::WARNING_EXISTING_FUNCTION;
|
||||
}
|
||||
}else{
|
||||
(s->theDictionary)[item_name] = item;
|
||||
s->theStatus = EVAL::OK;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
namespace HepTool {
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
Evaluator::Evaluator() {
|
||||
Struct * s = new Struct();
|
||||
p = (void *) s;
|
||||
s->theExpression = 0;
|
||||
s->thePosition = 0;
|
||||
s->theStatus = OK;
|
||||
s->theResult = 0.0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
Evaluator::~Evaluator() {
|
||||
delete (Struct *)(p);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
double Evaluator::evaluate(const char * expression) {
|
||||
Struct * s = (Struct *)(p);
|
||||
if (s->theExpression != 0) { delete[] s->theExpression; }
|
||||
s->theExpression = 0;
|
||||
s->thePosition = 0;
|
||||
s->theStatus = WARNING_BLANK_STRING;
|
||||
s->theResult = 0.0;
|
||||
if (expression != 0) {
|
||||
s->theExpression = new char[strlen(expression)+1];
|
||||
strcpy(s->theExpression, expression);
|
||||
s->theStatus = engine(s->theExpression,
|
||||
s->theExpression+strlen(expression)-1,
|
||||
s->theResult,
|
||||
s->thePosition,
|
||||
s->theDictionary);
|
||||
}
|
||||
return s->theResult;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int Evaluator::status() const {
|
||||
return ((Struct *)(p))->theStatus;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int Evaluator::error_position() const {
|
||||
return ((Struct *)(p))->thePosition - ((Struct *)(p))->theExpression;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Evaluator::print_error() const {
|
||||
Struct * s = (Struct *) p;
|
||||
if(s->theStatus != OK) {
|
||||
std::cerr << error_name() << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
std::string Evaluator::error_name() const
|
||||
{
|
||||
char prefix[] = "Evaluator : ";
|
||||
std::ostringstream errn;
|
||||
Struct * s = (Struct *) p;
|
||||
switch (s->theStatus) {
|
||||
case ERROR_NOT_A_NAME:
|
||||
errn << prefix << "invalid name";
|
||||
break;
|
||||
case ERROR_SYNTAX_ERROR:
|
||||
errn << prefix << "syntax error";
|
||||
break;
|
||||
case ERROR_UNPAIRED_PARENTHESIS:
|
||||
errn << prefix << "unpaired parenthesis";
|
||||
break;
|
||||
case ERROR_UNEXPECTED_SYMBOL:
|
||||
errn << prefix << "unexpected symbol";
|
||||
break;
|
||||
case ERROR_UNKNOWN_VARIABLE:
|
||||
errn << prefix << "unknown variable";
|
||||
break;
|
||||
case ERROR_UNKNOWN_FUNCTION:
|
||||
errn << prefix << "unknown function";
|
||||
break;
|
||||
case ERROR_EMPTY_PARAMETER:
|
||||
errn << prefix << "empty parameter in function call";
|
||||
break;
|
||||
case ERROR_CALCULATION_ERROR:
|
||||
errn << prefix << "calculation error";
|
||||
break;
|
||||
default:
|
||||
errn << " ";
|
||||
}
|
||||
return errn.str();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Evaluator::setVariable(const char * name, double value)
|
||||
{ setItem("", name, Item(value), (Struct *)p); }
|
||||
|
||||
void Evaluator::setVariable(const char * name, const char * expression)
|
||||
{ setItem("", name, Item(expression), (Struct *)p); }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Fix non ISO C++ compliant cast from pointer to function
|
||||
// to void*, which is a pointer to an object
|
||||
void Evaluator::setFunction(const char * name,
|
||||
double (*fun)())
|
||||
{ setItem("0", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
|
||||
|
||||
void Evaluator::setFunction(const char * name,
|
||||
double (*fun)(double))
|
||||
{ setItem("1", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
|
||||
|
||||
void Evaluator::setFunction(const char * name,
|
||||
double (*fun)(double,double))
|
||||
{ setItem("2", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
|
||||
|
||||
void Evaluator::setFunction(const char * name,
|
||||
double (*fun)(double,double,double))
|
||||
{ setItem("3", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
|
||||
|
||||
void Evaluator::setFunction(const char * name,
|
||||
double (*fun)(double,double,double,double))
|
||||
{ setItem("4", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
|
||||
|
||||
void Evaluator::setFunction(const char * name,
|
||||
double (*fun)(double,double,double,double,double))
|
||||
{ setItem("5", name, Item(reinterpret_cast<voidfuncptr>(fun)), (Struct *)p); }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Evaluator::findVariable(const char * name) const {
|
||||
if (name == 0 || *name == '\0') return false;
|
||||
const char * pointer; int n; REMOVE_BLANKS;
|
||||
if (n == 0) return false;
|
||||
Struct * s = (Struct *)(p);
|
||||
return
|
||||
((s->theDictionary).find(string(pointer,n)) == (s->theDictionary).end()) ?
|
||||
false : true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Evaluator::findFunction(const char * name, int npar) const {
|
||||
if (name == 0 || *name == '\0') return false;
|
||||
if (npar < 0 || npar > MAX_N_PAR) return false;
|
||||
const char * pointer; int n; REMOVE_BLANKS;
|
||||
if (n == 0) return false;
|
||||
Struct * s = (Struct *)(p);
|
||||
return ((s->theDictionary).find(sss[npar]+string(pointer,n)) ==
|
||||
(s->theDictionary).end()) ? false : true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Evaluator::removeVariable(const char * name) {
|
||||
if (name == 0 || *name == '\0') return;
|
||||
const char * pointer; int n; REMOVE_BLANKS;
|
||||
if (n == 0) return;
|
||||
Struct * s = (Struct *)(p);
|
||||
(s->theDictionary).erase(string(pointer,n));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Evaluator::removeFunction(const char * name, int npar) {
|
||||
if (name == 0 || *name == '\0') return;
|
||||
if (npar < 0 || npar > MAX_N_PAR) return;
|
||||
const char * pointer; int n; REMOVE_BLANKS;
|
||||
if (n == 0) return;
|
||||
Struct * s = (Struct *)(p);
|
||||
(s->theDictionary).erase(sss[npar]+string(pointer,n));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void Evaluator::clear() {
|
||||
Struct * s = (Struct *) p;
|
||||
s->theDictionary.clear();
|
||||
s->theExpression = 0;
|
||||
s->thePosition = 0;
|
||||
s->theStatus = OK;
|
||||
s->theResult = 0.0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
} // namespace HepTool
|
||||
Reference in New Issue
Block a user