529 lines
18 KiB
C++
Executable File

#pragma once
#ifndef __EXPR_H
#define __EXPR_H
#ifndef __REAL_H
#include <real.h>
#endif
#ifndef __STACK_H
#include <stack.h>
#endif
#ifndef __STRINGS_H
#include <strings.h>
#endif
// @doc INTERNAL
// @enum TCodesym | Lista di simboli/istruzioni possibili
enum TCodesym {
_invalid, // @emem Simbolo non riconosciuto
_endsym, // @emem Segnaposto per simbolo finale
_comma, // @emem Simbolo virgola ","
_semicolon, // @emem Simbolo punto e virgola ";"
_lpar, // @emem Simbolo aperta parentesi "("
_rpar, // @emem Simbolo chiusa parentesi ")"
_variable, // @emem Nome di una variabile
_number, // @emem Numero
_string, // @emem Stringa
_plus, // @emem Simbolo piu' "+"
_minus, // @emem Simbolo meno "-"
_multiply, // @emem Simbolo per "*"
_divide, // @emem Simbolo diviso "/"
_chgs, // @emem MENO unario
_and, // @emem AND logico
_or, // @emem OR logico
_not, // @emem NOT logico
_equal, // @emem Simbolo uguale "="
_match, // @emem Confronto tra stringhe con wildcards
_noteq, // @emem Simbolo diverso "!="
_lt, // @emem Simbolo minore "<lt>"
_gt, // @emem Simbolo maggiore "<gt>"
_lteq, // @emem Simbolo minore o uguale "<lt>="
_gteq, // @emem Simbolo maggiore o uguale "<gt>="
_userfunc, // @emem Funzione utente non definita chiamera' la .... in esecuzione
_sqrt, // @emem Radice quadrata
_sqr, // @emem Elevamento al quadrato
_exp10, // @emem Funzione 10 a potenza
_exp, // @emem Funzione e (nepero) elevato a
_log10, // @emem Logaritmo in base 10
_log, // @emem Logaritmo naturale
_sin, // @emem Funzione seno
_cos, // @emem Funzione coseno
_tan, // @emem Funzione tangente
_left, // @emem Primi caratteri di una stringa
_right, // @emem Ultimi caratteri di una stringa
_pow, // @emem Elevamento a potenza
_min, // @emem Minimo tra piu' elementi
_max, // @emem Massimo tra piu' elementi
_mid, // @emem Media degli elementi
_upper, // @emem Trasformazione in maiuscolo
_round, // @emem Arrotondamento
_ansi, // @emem Data in ansi
_if, // @emem Se(expr, val TRUE, val FALSE)
_num, // @emem Converte una stringa in numero
_endnum, // @emem Termine della funzione num
_str, // @emem Converte un numero in stringa
_endstr, // @emem Termine della funzione str
_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
_len, // @emem Lunghezza di una stringa
_trim, // @emem Elimina spazi iniziali e finali di una stringa
_between, // @emem controlla se il primo argomento e' compreso tra gli altri due
_cfcheck, // @emem controlla il codice fiscale (+stato)
_picheck, // @emem controlla la partita IVA (+stato)
_year, // @emem estrae l'anno da una data
_zerofill, // @emem riepie di zeri l'inizio di una stringa
_scon2perc, // @emem converte una espressione in percentuale di sconto
_bool, // @emem converte una espressione in booleano (0 o 1)
};
// @doc INTERNAL
// @enum TTypeexp | Tipi di espressioni definiti
enum TTypeexp {
_numexpr, // @emem Espressione numerica
_strexpr, // @emem Espressione in lettere
_mixexpr } ;
// @doc INTERNAL
// @class TValue | Classe per la definizione dei valori che possono essere assunti
// dai termini di una espressione o il valore dell'espressione stessa
//
// @base public | TObject
class TValue : public TObject
// @author:(INTERNAL) Alex
{
// @access:(INTERNAL) Private Member
// @cmember:(INTERNAL) Valore real
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; _t = val._t; return *this; }
// @cmember Assegnamento di una stringa
TValue& operator =(const TString& s) { set(s); return *this; }
// @cmember Assegnamento di un numero
TValue& operator =(const real& r) { set(r); return *this; }
// @cmember Ritorna il valore numerico
real& number();
// @cmember Ritorna il valore come stringa
TString& string();
void set(const real& val) { _r = val; _t = _numexpr; }
void set(const char* val) { _s = val; _t = _strexpr; }
// @cmember Setta il valore passato come stringa
TTypeexp type() const { return _t; }
// @cmember Costruttore. Inizializza TValue a 0,0 e ""
TValue() { }
// @cmember Costruttore. Inizializza TValue con un reale
TValue(const real& val) { set(val); }
// @cmember Costruttore. Inizializza TValue con una stringa
TValue(const char* val) { set(val); }
// @cmember Costruttore. Inizializza TValue con una stringa
TValue(const TString& val){ set(val); }
// @cmember Costruttore. Inizializza TValue con un altro TValue
TValue(const TValue& val) { _s = val._s; _r = val._r; _t = val._t; }
// @cmember Distruttore
virtual ~TValue() {}
};
#ifdef __EXPR_CPP
#define extern
#endif
extern TValue nulltvalue;
#undef extern
// @doc INTERNAL
// @class TCode | Classe per la ridefinizione di una espressione in
// notazione polacca inversa (RPN)
//
// @base public | TObject
class TCode : public TObject
// @author:(INTERNAL) Alex
// @access:(INTERNAL) Private Member
{
// @cmember:(INTERNAL) Simbolo-istruzione-codice
TCodesym _sym;
// @cmember:(INTERNAL) Valore
TValue _val;
// @access Public Member
public:
// @cmember Duplica il codice
virtual TObject* dup() const;
// @cmember Assegnamento tra oggetti TCode
TCode& operator =(const TCode& b);
// @cmember Inizializza simbolo e valore
void set(TCodesym sym, const TValue& val = nulltvalue)
{ _sym = sym; _val = val; }
// @cmember Ritorna il simbolo
TCodesym getsym() const
{ return _sym;}
// @cmember Ritorna il valore come <c real>
real& number()
{ return _val.number(); }
// @cmember Ritorna il valore come stringa
TString& string()
{ return _val.string(); }
// @cmember Costruttore, inizializza simbolo con "invalid", valore a nullvalue
TCode()
{set(_invalid);}
// @cmember Costruttore
TCode(TCodesym sym, const TValue& val = nulltvalue)
// @cmember Costruttore, inizializza simbolo con <p sym> e valore con <p val>
{ set(sym, val);}
// @cmember Costruttore
TCode(const TCode & c)
// @cmember Costruttore, inizializza simbolo con <p c>
{ set(c._sym, c._val);}
// @cmember Distruttore
virtual ~TCode()
{}
};
// @doc INTERNAL
// @class TCodearray | Classe per la definizione di un array di istruzioni da valutare
// passo per passo in una espressione
//
// @base public | TArray
class TCodearray : public TArray
// @author:(INTERNAL) Alex
// @access:(INTERNAL) Private Member
{
// @cmember:(INTERNAL) Puntatore all'istruzione corrente (Istruction pointer)
int _ip;
// @access Public Member
public:
// @cmember Cancella contenuto array
void clear();
// @cmember Aggiunge un'istruzione all'array
void add(TCodesym sym, const TValue& val = nulltvalue);
// @cmember Posiziona all'inizio il puntatore all'istruzione corrente
void begin()
{ _ip = 0;}
// @cmember Incrementa l'istruction pointer
TCode& step()
{ return *((TCode *) objptr(end() ? _ip : _ip++));}
// @cmember Ritorna TRUE se l'istruction pointer ha raggiunto il simbolo di fine codice
bool end() const
{ return ((TCode *) objptr(_ip))->getsym() == _endsym;}
// @cmember Sposta indietro l'istruction pointer di <p step> passi (si ferma
// quando trova l'inizio del puntatore)
void backtrace(int step = 1)
{ if (_ip > step) _ip -= step; else begin(); }
// @cmember Costruttore. Crea un array di 50 elementi
TCodearray(int size = 64) : TArray(size), _ip(0)
{}
// @cmember Distruttore
virtual ~TCodearray()
{}
};
// @doc INTERNAL
// @class TVar | Classe per la definizione delle variabile delle espressioni
//
// @base public | TObject
class TVar : public TSortable
// @author:(INTERNAL) Alex
// @access:(INTERNAL) Private Member
{
// @cmember:(INTERNAL) Nome della variabile
TString _name;
// @cmember:(INTERNAL) Valore assegnato alla variabile
TValue _val;
// @access Public Member
public:
// @cmember Duplica la variabile
virtual TObject* dup() const;
virtual int compare(const TSortable& s) const;
// @cmember Assegnamento di una stringa all'oggetto Tval
const char* operator =(const char* val)
{ _val.set(val); return val;}
// @cmember Assegnamento di un numero all'oggetto TVal
const real& operator =(const real& val)
{ _val.set(val); return val;}
// @cmember Assegnamento di un oggetto <c TValue>
TVar& operator =(const TValue& val)
{ _val = val; return *this;}
// @cmember Assegnamento tra oggetti TVal
TVar& operator =(const TVar& var)
{ _name = var._name ; _val = var._val; return *this;}
// @cmember Setta l'oggetto TVal con il nome e il valore passati
void set(const char* name, const TValue& val = nulltvalue)
{ _name = name ; _val = val;}
// @cmember Setta a <p name> il nome della variabile
void setname(const char* name)
{ _name = name;}
// @cmember Ritorna il nome della variabile
const TString& getname() const
{ return _name;}
// @cmember Ritorna il valore assegnato alla variabile (un <c TValue>)
operator TValue&()
{ return _val;}
// @cmember Ritorna il valore real della variabile
real& number()
{ return _val.number(); }
// @cmember Ritorna il valore stringa della variabile
TString& string()
{ return _val.string();}
// @cmember Costruttore (assegna "" al campo <p _name> ed il valore nulltvalue al campo <p val>)
TVar()
{ _name = ""; _val = nulltvalue;}
// @cmember Costruttore (assegna nome e valore passato)
TVar(const char* name, const TValue& val = nulltvalue)
{ _name = name; _val = val;}
// @cmember Costruttore (assegna l'oggetto TVal passato)
TVar(const TVar & v)
{ _name = v._name; _val = v._val;}
// @cmember Distruttore
virtual ~TVar()
{}
};
// @doc INTERNAL
// @class TVararray | Classe per la definizione di un array di variabili da
// valutare nell'esspressione
//
class TVararray
// @author:(INTERNAL) Alex
// @access:(INTERNAL) Private Member
{
TArray _vars;
protected:
TVar* find(const char* name) const;
TVar* find(const int varnum) const;
// @access Public Member
public:
// @cmember Cancella il contenuto dell'array
void clear() { _vars.destroy(); }
// @cmember Aggiunge un oggetto TVar
void add(const TVar& var);
// @cmember Aggiunge un nome di variabile e il suo valore
void add(const char* name, const TValue& val = nulltvalue);
// @cmember Ritorna il nome della variabile di posto varnum
const char* varname(int varnum) const
{ return find(varnum)->getname(); }
bool exist(const char* name) const
{ return find(name) != NULL; }
// @cmember Setta l'oggetto TVararray con il nome e il valore della variabile
void set(const char* varname, const real& val);
// @cmember Setta l'oggetto TVararray con il nome e il valore della variabile
// (passato come stringa)
void set(const char* varname, const char* val);
// @cmember Setta l'elemnto dell varaibile <p varnum>-esima al valore passato
void set(int varnum, const real& val)
{ *find(varnum) = val;}
// @cmember Setta l'elemento dell variabile <p varnum>-esima al valore passato
// come stringa
void set(int varnum, const char* val)
{ *find(varnum) = val;}
// @cmember Ritorna il valore della variabile con nome <p varname>
const real& getnum(const char* varname);
// @cmember Ritorna il valore della variabile di posto <p varnum>-esimo
const real& getnum(int varnum) { return find(varnum)->number(); }
// @cmember Ritorna il nome della variabile con nome <p varname>
const TString& getstring(const char* varname);
// @cmember Ritorna il nome della variabile di posto <p varnum>-esimo
const TString& getstring(int varnum) { return find(varnum)->string(); }
// @cmember Ritorna il numero di variabili utilizzate
int numvar() const { return _vars.items();}
// @cmember Costruttore
TVararray(int size = 16) : _vars(size) {}
// @cmember Distruttore
virtual ~TVararray() {}
};
class TEval_stack : public TStack
{
public:
real& pop_real();
real& peek_real();
TString& pop_string();
TString& peek_string();
void push(bool b);
void push(int n);
void push(const real& r);
void push(const TString& s);
void push(const char* s);
TTypeexp top1_type() const;
TTypeexp top2_type() const;
};
// @doc EXTERNAL
// @class TExpression | Classe per la interpretazione e valutazione di espressioni
// numeriche e di stringhe
//
// @base public | TObject
class TExpression : public TObject
// @author:(INTERNAL) Alex
// @access:(INTERNAL) Private Member
{
// @access Protected Member
protected:
// @cmember:(INTERNAL) Array di codice
TCodearray _code;
// @cmember:(INTERNAL) Array di variabili
TVararray _var;
// @cmember:(INTERNAL) Valore dell'espressione
TValue _val;
// @cmember:(INTERNAL) Indica se segnalare o no errori di valutazione
bool _ignore_error;
// @cmember:(INTERNAL) Diverso da 0 se la valutazione dell'espressione ha dato errori (ZERO DIV)
int _error;
// @cmember:(INTERNAL) TRUE se l'espressione e' stata modificata
bool _dirty;
// @cmember:(INTERNAL) TRUE se l'espressione ha almeno una funzione utente
bool _user_func_defined;
// @cmember:(INTERNAL) Tipo dell'espressione
TTypeexp _type;
// @cmember:(INTERNAL) Stringa originale
TString _original;
// @access Protected Member
protected:
// @cmember funzione utente da ricalcolare
virtual bool user_func_dirty() const { return _user_func_defined; }
// @cmember stampa un messaggio d'errore
virtual bool print_error(const char* msg) const;
// @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();
// @cmember Esegue la compilazione di un fattore
TCodesym __factor(TCodesym startsym);
// @cmember Esegue la compilazione di un termine
TCodesym __term(TCodesym startsym);
// @cmember Esegue la compilazione di un'espressione
TCodesym __expression(TCodesym startsym);
// @cmember Esegue la compilazione di un una funzione
TCodesym __function(int nparms = -1, int* actual_params = NULL);
// @cmember Compila l'espressione
bool compile(const TString& expression, TTypeexp type);
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(int index, int nparms, TEval_stack& stack, TTypeexp type) const;
virtual int parse_user_func(const char* name, int nparms) const { return -1; }
// @access Public Member
public:
// @cmember Duplica l'espressione
virtual TObject* dup() const;
// @cmember operator const | real& | | Ritorna il valore real dell'espressione
operator const real&() {return as_real();}
// @cmember operator const | char* | | Ritorna il valore dell'espressione come stringa
operator const TString &() {return as_string();}
// @cmember Ritorna il valore dell'espressione come booleano
operator bool() {return as_bool();}
// @cmember operator const | real& | | Ritorna il valore real dell'espressione
const real & as_real();
// @cmember operator const | char* | | Ritorna il valore dell'espressione come stringa
const TString & as_string();
// @cmember Ritorna il valore dell'espressione come booleano
bool as_bool();
// @cmember Ritorna il nome della variabile di posto <p varnum>
const char* varname(int varnum) const
{ return _var.varname(varnum); }
// @cmember Ritorna il numero di variabili nell'espressione
int numvar() const
{ return _var.numvar(); }
// @cmember Ritorna il tipo dell'espressione
const TTypeexp type() const
{ return _type; }
// @cmember Ritorna l'array del codice
TCodearray& code() const
{ return (TCodearray&)_code; }
// @cmember Ritorna l'array di variabili
const TVararray& vars() const
{ return _var; }
// @cmember controlla l'esistenza di una variabile
bool exist(const char* name) const
{ return _var.exist(name); }
// @cmember Setta la variabile con nome e numero
void setvar(const char* varname, const real& val);
// @cmember Setta la variabile con posizione e numero
void setvar(int varnum, const real& val);
// @cmember Setta la variabile con nome e valore passato come stringa
void setvar(const char* varname, const char* val);
// @cmember Setta la variabile passato con posizione e numero passato come stringa
void setvar(int varnum, const char* val);
// @cmember Setta il tipo dell'espressione
void set_type(const TTypeexp type)
{ _type = type; }
// @cmember Setta l'espressione e la compila (ritorna il risultato della compilazione)
bool set(const char* expression, TTypeexp type = _numexpr);
const char* last_token() const;
// @cmember Ritorna l'espressione originale
const char * string() const { return _original; }
// @cmember Ritorna eventuali errori
int error() const { return _error; }
// @cmember Costruttore (assegna l'estressione e il suo tipo)
TExpression(const char* expression, TTypeexp type = _numexpr, bool ignore_err=FALSE);
// @cmember Costruttore (assegna il tipo dell'istruzione)
TExpression(TTypeexp type = _numexpr, bool ignore_err=FALSE);
// @cmember Costruttore di copia
TExpression(const TExpression & expr);
// @cmember Distruttore
virtual ~TExpression() {}
};
bool is_real_discount(const TString& exp);
bool scontoexpr2perc(const TString& exp, bool signal, TString& goodexp, real& val_perc);
real prezzo_scontato(const real& prezzo, const TString& sconto);
#endif // __EXPR_H