expr.cpp Aggiunte nuove funzioni.
stack.cpp Aggiunto metodo peek. CV: ---------------------------------------------------------------------- git-svn-id: svn://10.65.10.50/trunk@3429 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
a4b9a8e833
commit
60fa7010c1
163
include/expr.cpp
163
include/expr.cpp
@ -11,7 +11,8 @@
|
||||
TValue::TValue(const real& val)
|
||||
{
|
||||
_r = val;
|
||||
_s = val.string( );
|
||||
_s = val.string();
|
||||
_t = _numexpr;
|
||||
}
|
||||
|
||||
TCodearray::TCodearray(int size) : _rpn(size)
|
||||
@ -45,14 +46,12 @@ TCode& TCode::operator =(const TCode& b)
|
||||
}
|
||||
|
||||
TVararray::TVararray(int size) : _array(size)
|
||||
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void TVararray::add(const char* name, const TValue& val)
|
||||
|
||||
{
|
||||
TVar* v = new TVar(name, val);
|
||||
_array.add(v, _last++);
|
||||
@ -190,7 +189,7 @@ TExpression::operator const char*()
|
||||
void TExpression::print_on(ostream& out) const
|
||||
{ out << _original; }
|
||||
|
||||
void TExpression::evaluate_user_func(const char * name, int nparms, TStack & stack)
|
||||
void TExpression::evaluate_user_func(const char * name, int nparms, TStack & stack) const
|
||||
|
||||
{
|
||||
NFCHECK("Unknown function : %s ", name);
|
||||
@ -246,7 +245,7 @@ void TExpression::eval()
|
||||
{
|
||||
TStack evalstack(50);
|
||||
TCode instr;
|
||||
real o1, o2, zero(0.00);
|
||||
real o1, o2;
|
||||
TString s1, s2;
|
||||
|
||||
_code.begin();
|
||||
@ -315,15 +314,15 @@ void TExpression::eval()
|
||||
case _and:
|
||||
if (_type == _strexpr)
|
||||
{
|
||||
o2 = real((const char*) (TString&)evalstack.pop());
|
||||
o1 = real((const char*) (TString&)evalstack.pop());
|
||||
evalstack.push(TString((o1 != zero && o2 != zero) ? "1" : "0"));
|
||||
o2 = real((const char*)(TString&)evalstack.pop());
|
||||
o1 = real((const char*)(TString&)evalstack.pop());
|
||||
evalstack.push(TString((o1 != ZERO && o2 != ZERO) ? "1" : "0"));
|
||||
}
|
||||
else
|
||||
{
|
||||
o2 = (real&) evalstack.pop();
|
||||
o1 = (real&) evalstack.pop();
|
||||
evalstack.push(real((o1 != zero && o2 != zero) ? 1.0 : 0.0));
|
||||
evalstack.push(real((o1 != ZERO && o2 != ZERO) ? 1.0 : 0.0));
|
||||
}
|
||||
break;
|
||||
case _or:
|
||||
@ -331,18 +330,18 @@ void TExpression::eval()
|
||||
{
|
||||
o2 = real((const char*) (TString&)evalstack.pop());
|
||||
o1 = real((const char*) (TString&)evalstack.pop());
|
||||
evalstack.push(TString((o1 != zero || o2 != zero) ? "1" : "0"));
|
||||
evalstack.push(TString((o1 != ZERO || o2 != ZERO) ? "1" : "0"));
|
||||
}
|
||||
else
|
||||
{
|
||||
o2 = (real&) evalstack.pop();
|
||||
o1 = (real&) evalstack.pop();
|
||||
evalstack.push(real((o1 != zero || o2 != zero) ? 1.0 : 0.0));
|
||||
evalstack.push(real((o1 != ZERO || o2 != ZERO) ? 1.0 : 0.0));
|
||||
}
|
||||
break;
|
||||
case _not:
|
||||
o1 = (real&) evalstack.pop();
|
||||
evalstack.push(real((o1 == zero) ? 1.0 : 0.0));
|
||||
evalstack.push(real((o1 == ZERO) ? 1.0 : 0.0));
|
||||
break;
|
||||
case _equal:
|
||||
if (_type == _strexpr)
|
||||
@ -488,6 +487,14 @@ void TExpression::eval()
|
||||
evalstack.push(s);
|
||||
}
|
||||
break;
|
||||
case _substr:
|
||||
{
|
||||
const int to = (int)((const real&)evalstack.pop()).integer();
|
||||
const int from = (int)((const real&)evalstack.pop()).integer() - 1;
|
||||
const TString& s = ((const TString&)evalstack.pop()).sub(from, to);
|
||||
evalstack.push(s);
|
||||
}
|
||||
break;
|
||||
case _pow:
|
||||
o2 = (real&) evalstack.pop();
|
||||
o1 = (real&) evalstack.pop();
|
||||
@ -516,6 +523,46 @@ void TExpression::eval()
|
||||
evalstack.push(o1);
|
||||
}
|
||||
break;
|
||||
case _trunc:
|
||||
{
|
||||
const int ndec = (int)((real&) evalstack.pop()).integer();
|
||||
o1 = (real&) evalstack.pop();
|
||||
o1.trunc(ndec);
|
||||
evalstack.push(o1);
|
||||
}
|
||||
break;
|
||||
case _ceil:
|
||||
{
|
||||
const int ndec = (int)((real&) evalstack.pop()).integer();
|
||||
o1 = (real&) evalstack.pop();
|
||||
o1.ceil(ndec);
|
||||
evalstack.push(o1);
|
||||
}
|
||||
break;
|
||||
case _perc:
|
||||
{
|
||||
o1 = (real&) evalstack.pop();
|
||||
o2 = (real&) evalstack.pop();
|
||||
evalstack.push(real(o1 * o2 / 100.0));
|
||||
}
|
||||
break;
|
||||
case _scorp:
|
||||
{
|
||||
const real percent = (real&)evalstack.pop();
|
||||
real imponibile = (real&)evalstack.pop();
|
||||
const real imposta = imponibile * percent / (percent + 100.0);
|
||||
imponibile -= imposta;
|
||||
evalstack.push(imponibile);
|
||||
}
|
||||
break;
|
||||
case _if:
|
||||
{
|
||||
s1 = (TString&)evalstack.pop();
|
||||
s2 = (TString&)evalstack.pop();
|
||||
const real cond = (real&) evalstack.pop();;
|
||||
evalstack.push(cond.is_zero() ? s1 : s2);
|
||||
}
|
||||
break;
|
||||
case _ansi:
|
||||
{
|
||||
const TDate d((const TString&)evalstack.pop());
|
||||
@ -526,29 +573,55 @@ void TExpression::eval()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_type == _strexpr)
|
||||
_val = (const char*) (TString&) evalstack.pop();
|
||||
else
|
||||
_val = (real&) evalstack.pop();
|
||||
|
||||
if (_type == _strexpr)
|
||||
_val = (TString&)evalstack.pop();
|
||||
else
|
||||
_val = (real&)evalstack.pop();
|
||||
}
|
||||
|
||||
|
||||
HIDDEN const char* _s;
|
||||
HIDDEN char _tok[81];
|
||||
HIDDEN const char* _fntable[] = { "sqrt", "sqr", "exp10", "exp", "log10",
|
||||
"log", "sin", "cos", "tan", "left",
|
||||
"right", "pow", "min", "max", "mid", "upper",
|
||||
"round", "ansi", NULL };
|
||||
|
||||
HIDDEN TCodesym _fntok[] = { _sqrt, _sqr, _exp10, _exp, _log10, _log,
|
||||
_sin, _cos, _tan, _left, _right, _pow,
|
||||
_min, _max, _mid, _upper, _round, _ansi};
|
||||
TCodesym TExpression::tok2fun(const char* tok) const
|
||||
{
|
||||
const int MAX_TOK = 24;
|
||||
HIDDEN const char* fnstr[MAX_TOK] = { "ANSI", "CEIL", "COS", "EXP", "EXP10",
|
||||
"IF", "LEFT", "LOG", "LOG10", "MAX",
|
||||
"MID", "MIN", "PERC", "POW", "RIGHT",
|
||||
"ROUND", "SCORP", "SIN", "SQR", "SQRT",
|
||||
"SUBSTR", "TAN", "TRUNC", "UPPER" };
|
||||
|
||||
HIDDEN TCodesym fntok[MAX_TOK] = { _ansi, _ceil, _cos, _exp, _exp10,
|
||||
_if, _left, _log, _log10, _max,
|
||||
_mid, _min, _perc, _pow, _right,
|
||||
_round, _scorp, _sin, _sqr, _sqrt,
|
||||
_substr, _tan, _trunc, _upper };
|
||||
|
||||
int f = 0, l = MAX_TOK-1, i;
|
||||
while (TRUE)
|
||||
{
|
||||
i = (f+l)>>1;
|
||||
const int cmp = stricmp(tok, fnstr[i]);
|
||||
if (cmp == 0)
|
||||
break;
|
||||
if (cmp > 0) f = i+1;
|
||||
else l = i-1;
|
||||
if (f > l)
|
||||
{
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i >= 0 ? fntok[i] : _invalid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TCodesym TExpression::__gettoken(bool reduct)
|
||||
|
||||
{
|
||||
TCodesym sym = _invalid;
|
||||
TCodesym sym = _invalid;
|
||||
int i = 0;
|
||||
|
||||
_tok[0] = '\0';
|
||||
@ -598,13 +671,14 @@ TCodesym TExpression::__gettoken(bool reduct)
|
||||
_tok[i++] = *(_s++);
|
||||
}
|
||||
_tok[i] = '\0';
|
||||
TString s(_tok);
|
||||
s.lower();
|
||||
for ( int j = 0; _fntable[j] != NULL; j++)
|
||||
if (s == _fntable[j]) return _fntok[j];
|
||||
for (const char * p = _s; *p && *p == ' '; p++);
|
||||
|
||||
sym = tok2fun(_tok); // Guy was here!
|
||||
if (sym != _invalid)
|
||||
return sym;
|
||||
|
||||
for (const char * p = _s; isspace(*p); p++);
|
||||
if (*p == '(')
|
||||
return _userfunc;
|
||||
return _userfunc;
|
||||
return _variable;
|
||||
}
|
||||
switch (*_s)
|
||||
@ -703,9 +777,8 @@ TCodesym TExpression::__gettoken(bool reduct)
|
||||
|
||||
|
||||
TCodesym TExpression::__factor(TCodesym startsym)
|
||||
|
||||
{
|
||||
TCodesym sym = _invalid;
|
||||
TCodesym sym = _invalid;
|
||||
|
||||
switch (startsym)
|
||||
{
|
||||
@ -729,7 +802,6 @@ TCodesym TExpression::__factor(TCodesym startsym)
|
||||
case _userfunc:
|
||||
{
|
||||
TValue val (_tok);
|
||||
|
||||
sym = __gettoken();
|
||||
if (sym == _lpar)
|
||||
{
|
||||
@ -779,6 +851,10 @@ TCodesym TExpression::__factor(TCodesym startsym)
|
||||
case _min:
|
||||
case _max:
|
||||
case _round:
|
||||
case _ceil:
|
||||
case _trunc:
|
||||
case _perc:
|
||||
case _scorp:
|
||||
sym = __gettoken();
|
||||
if (sym == _lpar) sym = __gettoken(TRUE);
|
||||
else break;
|
||||
@ -791,6 +867,7 @@ TCodesym TExpression::__factor(TCodesym startsym)
|
||||
_code.add(startsym);
|
||||
break;
|
||||
case _mid:
|
||||
case _substr:
|
||||
sym = __gettoken();
|
||||
if (sym == _lpar) sym = __gettoken(TRUE);
|
||||
else break;
|
||||
@ -805,7 +882,22 @@ TCodesym TExpression::__factor(TCodesym startsym)
|
||||
if (sym == _rpar) sym = __gettoken();
|
||||
else break;
|
||||
_code.add(startsym);
|
||||
break;
|
||||
break;
|
||||
case _if:
|
||||
sym = __gettoken();
|
||||
if (sym == _lpar) sym = __gettoken(TRUE);
|
||||
else break;
|
||||
sym = __expression(sym);
|
||||
if (sym == _comma) sym = __gettoken(TRUE);
|
||||
else break;
|
||||
sym = __expression(sym);
|
||||
if (sym == _comma) sym = __gettoken(TRUE);
|
||||
else break;
|
||||
sym = __expression(sym);
|
||||
if (sym == _rpar) sym = __gettoken();
|
||||
else break;
|
||||
_code.add(startsym);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -814,7 +906,6 @@ TCodesym TExpression::__factor(TCodesym startsym)
|
||||
|
||||
|
||||
TCodesym TExpression::__term(TCodesym startsym)
|
||||
|
||||
{
|
||||
TCodesym sym;
|
||||
|
||||
|
@ -54,8 +54,16 @@ enum TCodesym {
|
||||
_mid, // @emem Media degli elementi
|
||||
_upper, // @emem Trasformazione in maiuscolo
|
||||
_round, // @emem Arrotondamento
|
||||
_ansi } ; // @emem Data in ansi
|
||||
|
||||
_ansi, // @emem Data in ansi
|
||||
_if, // @emem Se(expr, val TRUE, val FALSE)
|
||||
_num, // @emem Converte una stringa in numero
|
||||
_str, // @emem Converte un numero in stringa
|
||||
_ceil, // @emem Arrotonda un numero all'intero successivo
|
||||
_trunc, // @emem Tronca i decimali
|
||||
_perc, // @emem Calcola la percentuale
|
||||
_scorp, // @emem Scorpora una percentuale
|
||||
_substr, // @emem Estrae una sottostringa
|
||||
} ;
|
||||
// @doc INTERNAL
|
||||
|
||||
// @enum TTypeexp | Tipi di espressioni definiti
|
||||
@ -79,30 +87,39 @@ enum TCodesym {
|
||||
real _r;
|
||||
// @cmember:(INTERNAL) Valore in formato stringa
|
||||
TString _s;
|
||||
|
||||
// @cmember:(INTERNAL) Tipo preferito
|
||||
TTypeexp _t;
|
||||
|
||||
// @access Public Member
|
||||
public:
|
||||
// @cmember Assegnamento tra oggetti TValue
|
||||
TValue& operator =(const TValue& val)
|
||||
{ _s = val._s; _r = val._r; return *this;}
|
||||
{ _s = val._s; _r = val._r; _t = val._t; return *this; }
|
||||
// @cmember Assegnamento di una stringa
|
||||
TValue& operator =(const TString& s)
|
||||
{ _s = s; _r = real(s); _t = _strexpr; return *this; }
|
||||
// @cmember Assegnamento di un numero
|
||||
TValue& operator =(const real& r)
|
||||
{ _s = r.string(); _r = r; _t = _numexpr; return *this; }
|
||||
// @cmember Ritorna il valore numerico
|
||||
const real& number() const
|
||||
{ return _r;}
|
||||
{ return _r; }
|
||||
// @cmember Ritorna il valore come stringa
|
||||
const char* string() const
|
||||
{ return (const char*) _s;}
|
||||
// @cmember Setta il valore passato come real
|
||||
void set(const real& val)
|
||||
{ _r = val; _s = val.string();}
|
||||
{ _r = val; _s = val.string(); _t = _numexpr; }
|
||||
// @cmember Setta il valore passato come stringa
|
||||
void set(const char* val)
|
||||
{ _s = val; _r = real(val);}
|
||||
|
||||
{ _s = val; _r = real(val); _t = _strexpr; }
|
||||
// @cmember Setta il valore passato come stringa
|
||||
TTypeexp type() const { return _t; }
|
||||
// @cmember Costruttore. Inizializza TValue con un reale
|
||||
TValue(const real& val);
|
||||
// @cmember Costruttore. Inizializza TValue con una stringa
|
||||
TValue(const char* val)
|
||||
{ _s = val; _r = real(val);}
|
||||
{ _s = val; _r = real(val); _t = _strexpr; }
|
||||
// @cmember Costruttore. Inizializza TValue con un altro TValue
|
||||
TValue(const TValue& val)
|
||||
{ *this = val; }
|
||||
@ -377,6 +394,8 @@ class TExpression : public TObject
|
||||
protected:
|
||||
// @cmember Valuta (calcola) l'espressione
|
||||
void eval();
|
||||
// @cmember Converte una stringa in un nome di funzione o _invalid se non esiste
|
||||
TCodesym tok2fun(const char* tok) const;
|
||||
// @cmember Ritorna il prossimo token dell'espressione (se <p reduct> e' TRUE interpreta
|
||||
// la virgola come un token)
|
||||
TCodesym __gettoken(bool reduct = FALSE);
|
||||
@ -392,7 +411,7 @@ protected:
|
||||
protected: // TObject
|
||||
// @cmember Stampa l'espressione su <p out> (serve per implementare l'insertore)
|
||||
virtual void print_on(ostream& out) const ;
|
||||
virtual void evaluate_user_func(const char * name, int nparms, TStack & stack);
|
||||
virtual void evaluate_user_func(const char* name, int nparms, TStack& stack) const;
|
||||
|
||||
// @access Public Member
|
||||
public:
|
||||
|
@ -8,9 +8,19 @@ void TStack::push(const TObject& o)
|
||||
add(o, _sp++);
|
||||
}
|
||||
|
||||
void TStack::push(TObject* o)
|
||||
{
|
||||
add(o, _sp++);
|
||||
}
|
||||
|
||||
TObject& TStack::pop()
|
||||
{
|
||||
CHECK(count() > 0, "Stack underflow!");
|
||||
return (*this)[--_sp];
|
||||
}
|
||||
|
||||
TObject& TStack::peek(int depth) const
|
||||
{
|
||||
CHECK(depth > _sp, "Stack underflow!");
|
||||
return (*this)[_sp-depth-1];
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// @base public | TArray
|
||||
class TStack : private TArray
|
||||
|
||||
// @author:(INTERNAL) Sandro
|
||||
// @author:(INTERNAL) Alex
|
||||
|
||||
// @access:(INTERNAL) Private Member
|
||||
{
|
||||
@ -21,16 +21,21 @@ class TStack : private TArray
|
||||
|
||||
// @access Public Member
|
||||
public:
|
||||
// @cmember Costruttore. Chaima il costruttore di <c TArray>
|
||||
TStack(int size);
|
||||
|
||||
// @cmember Ritorna il puntatore allo stack
|
||||
int count() const
|
||||
{ return _sp; }
|
||||
// @cmember Aggiunge un oggetto sullo stack
|
||||
void push(const TObject&);
|
||||
void push(const TObject& o);
|
||||
// @cmember Aggiunge un oggetto sullo stack
|
||||
void push(TObject* o);
|
||||
// @cmember Ritorna il primo oggetto sulla cima dello stack
|
||||
TObject& pop();
|
||||
// @cmember Ritorna l'oggetto ad una data profondita' nello stack
|
||||
TObject& peek(int depth = 0) const;
|
||||
// @cmember Costruttore. Chiama il costruttore di <c TArray>
|
||||
TStack(int size = 16);
|
||||
// @cmember Distruttore. Chiama il distruttore di <c TArray>
|
||||
virtual ~TStack() { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user