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:
guy 1996-08-23 12:58:19 +00:00
parent a4b9a8e833
commit 60fa7010c1
4 changed files with 176 additions and 51 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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];
}

View File

@ -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