Finite correzzioni su expr

git-svn-id: svn://10.65.10.50/trunk@3675 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
alex 1996-09-26 15:30:49 +00:00
parent c7d7a67725
commit ec4bf8d8e8
2 changed files with 239 additions and 330 deletions

View File

@ -194,10 +194,7 @@ TExpression::TExpression(const char* expression, TTypeexp type)
_dirty = TRUE;
_type = type;
if (!compile(_original, type))
{
error_box("Wrong expression : %s", expression);
_code.clear();
}
print_error(format("Wrong expression : %s", expression));
}
@ -213,7 +210,8 @@ TExpression::TExpression(TTypeexp type)
TExpression::TExpression(const TExpression & expr)
: _code(expr._code), _var(expr._var),
_val(expr._val), _dirty(expr._dirty),
_type(expr._type), _original(expr._original)
_type(expr._type), _original(expr._original),
_user_func_defined(expr._user_func_defined)
{
}
@ -311,8 +309,6 @@ void TExpression::eval()
TBit_array types;
int type_pointer = 0;
TCode instr;
real o1, o2;
TString s1, s2;
types.set(type_pointer, (_type == _numexpr));
@ -330,341 +326,335 @@ void TExpression::eval()
case _variable:
if (type == _strexpr)
{
s1 = _var.getstring(instr.string());
const TString & s1 = _var.getstring(instr.string());
evalstack.push(s1);
}
else
{
o1 = _var.getnum(instr.string());
evalstack.push(o1);
const real & r1 = _var.getnum(instr.string());
evalstack.push(r1);
}
break;
case _number:
o1 = instr.number();
evalstack.push(o1);
case _number:
{
const real & r1 = instr.number();
evalstack.push(r1);
}
break;
case _string:
s1 = instr.string();
evalstack.push(s1);
{
const TString & s1 = instr.string();
evalstack.push(s1);
}
break;
case _plus:
if (type == _strexpr)
{
/*
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
s1 << s2;
evalstack.push(s1);
*/
// Non unire le seguenti righe
const TString& s = evalstack.pop_string();
evalstack.peek_string() << s;
}
else
{
/*
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real(o1 + o2));
*/
// Non unire le seguenti righe
const real& r = evalstack.pop_real();
evalstack.peek_real() += r;
}
break;
case _minus:
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real(o1 - o2));
{
const real& r = evalstack.pop_real();
evalstack.peek_real() -= r;
}
break;
case _multiply:
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real(o1 * o2));
{
const real& r = evalstack.pop_real();
evalstack.peek_real() *= r;
}
break;
case _divide:
o2 = evalstack.pop_real();
if (o2.is_zero())
{
print_error("Divisione per zero!");
o2 = 1.0;
real& r = evalstack.pop_real();
if (r.is_zero())
{
print_error("Divisione per zero!");
r = 1.0;
}
evalstack.peek_real() /= r;
}
o1 = evalstack.pop_real();
evalstack.push(real(o1 / o2));
break;
case _chgs:
o1 = evalstack.pop_real();
evalstack.push(-o1);
{
real & r = evalstack.peek_real();
r = -r;
}
break;
case _and:
if (type == _strexpr)
{
o2 = real((const char*)evalstack.pop_string());
o1 = real((const char*)evalstack.pop_string());
evalstack.push(TString((o1 != ZERO && o2 != ZERO) ? "1" : "0"));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 != ZERO && o2 != ZERO) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (!r1.is_zero() && !r2.is_zero()) ? 1.0 : 0.0;
}
break;
case _or:
if (type == _strexpr)
{
o2 = real((const char*) evalstack.pop_string());
o1 = real((const char*) evalstack.pop_string());
evalstack.push(TString((o1 != ZERO || o2 != ZERO) ? "1" : "0"));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 != ZERO || o2 != ZERO) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 != ZERO || r2 != ZERO) ? 1.0 : 0.0;
}
break;
case _not:
o1 = evalstack.pop_real();
evalstack.push(real((o1 == ZERO) ? 1.0 : 0.0));
{
real & r1 = evalstack.peek_real();
r1 = (r1 == ZERO) ? 1.0 : 0.0;
}
break;
case _equal:
if (type == _strexpr)
{
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString((s1 == s2) ? "1" : "0"));
const TString & s2 = evalstack.pop_string();
const TString & s1 = evalstack.pop_string();
evalstack.push(real(s1 == s2 ? 1.0 : 0.0));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 == o2) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 == r2) ? 1.0 : 0.0;
}
break;
case _match:
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString((s1.match(s2)) ? "1" : "0"));
case _match:
{
const TString & s2 = evalstack.pop_string();
const TString & s1 = evalstack.pop_string();
evalstack.push(real((s1.match(s2)) ? 1.0 : 0.0));
}
break;
case _noteq:
if (type == _strexpr)
{
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString(s1 != s2 ? "1" : "0"));
const TString & s2 = evalstack.pop_string();
TString & s1 = evalstack.pop_string();
evalstack.push(real(s1 != s2 ? 1.0 : 0.0));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 != o2) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 != r2) ? 1.0 : 0.0;
}
break;
case _lt:
if (type == _strexpr)
{
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString((s1 < (const char*)s2) ? "1" : "0"));
const TString & s2 = evalstack.pop_string();
const TString & s1 = evalstack.peek_string();
evalstack.push(real(s1 < s2 ? 1.0 : 0.0));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 < o2) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 < r2) ? 1.0 : 0.0;
}
break;
case _gt:
if (type == _strexpr)
{
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString((s1 > (const char*)s2) ? "1" : "0"));
const TString & s2 = evalstack.pop_string();
const TString & s1 = evalstack.peek_string();
evalstack.push(real(s1 > s2 ? 1.0 : 0.0));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 > o2) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 > r2) ? 1.0 : 0.0;
}
break;
case _lteq:
if (type == _strexpr)
{
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString((s1 <= (const char*)s2) ? "1" : "0"));
const TString & s2 = evalstack.pop_string();
const TString & s1 = evalstack.peek_string();
evalstack.push(real(s1 <= s2 ? 1.0 : 0.0));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 <= o2) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 <= r2) ? 1.0 : 0.0;
}
break;
case _gteq:
if (type == _strexpr)
{
s2 = evalstack.pop_string();
s1 = evalstack.pop_string();
evalstack.push(TString((s1 >= (const char*)s2) ? "1" : "0"));
const TString & s2 = evalstack.pop_string();
TString & s1 = evalstack.peek_string();
evalstack.push(real(s1 >= s2 ? 1.0 : 0.0));
}
else
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real((o1 >= o2) ? 1.0 : 0.0));
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = (r1 >= r2) ? 1.0 : 0.0;
}
break;
case _userfunc:
{
const int nparms = (int) ((real &) evalstack.pop()).integer();
const int nparms = (int) evalstack.pop_real().integer();
const int index = atoi(instr.string());
evaluate_user_func(index, nparms, evalstack, type);
}
break;
case _sqrt:
evalstack.push(real(sqrt(evalstack.pop_real())));
case _sqrt:
evalstack.peek_real() = sqrt(evalstack.peek_real());
break;
case _sqr:
evalstack.push(real(sqr(evalstack.pop_real())));
evalstack.peek_real() = sqr(evalstack.peek_real());
break;
case _exp10:
evalstack.push(real(exp10(evalstack.pop_real())));
evalstack.peek_real() = exp10(evalstack.peek_real());
break;
case _exp:
evalstack.push(real(exp(evalstack.pop_real())));
evalstack.peek_real() = exp(evalstack.peek_real());
break;
case _log10:
evalstack.push(real(log10(evalstack.pop_real())));
evalstack.peek_real() = log10(evalstack.peek_real());
break;
case _log:
evalstack.push(real(log(evalstack.pop_real())));
evalstack.peek_real() = log(evalstack.peek_real());
break;
case _sin:
evalstack.push(real(sin(evalstack.pop_real())));
evalstack.peek_real() = sin(evalstack.peek_real());
break;
case _cos:
evalstack.push(real(cos(evalstack.pop_real())));
evalstack.peek_real() = cos(evalstack.peek_real());
break;
case _tan:
evalstack.push(real(tan(evalstack.pop_real())));
evalstack.peek_real() = tan(evalstack.peek_real());
break;
case _left:
o2 = evalstack.pop_real();
s2 = evalstack.pop_string();
s1 = s2.left((int)o2.integer());
evalstack.push(s1);
{
const int len = (int)evalstack.pop_real().integer();
TString & s1 = evalstack.peek_string();
s1 = s1.left(len);
}
break;
case _right:
o2 = evalstack.pop_real();
s2 = evalstack.pop_string();
s1 = s2.right((int)o2.integer());
evalstack.push(s1);
{
const int len = (int)evalstack.pop_real().integer();
TString & s1 = evalstack.peek_string();
s1 = s1.right(len);
}
break;
case _mid:
{
int count = (int)evalstack.pop_real().integer();
if (count == 0) count--;
int from = (int)evalstack.pop_real().integer() - 1;
if (from < 0) from = 0;
TString& s = evalstack.peek_string();
s = s.mid(from, count);
}
{
int count = (int)evalstack.pop_real().integer();
if (count == 0) count--;
int from = (int)evalstack.pop_real().integer() - 1;
if (from < 0) from = 0;
TString & s1 = evalstack.peek_string();
s1 = s1.mid(from, count);
}
break;
case _substr:
{
const int to = (int)evalstack.pop_real().integer();
int from = (int)evalstack.pop_real().integer() - 1;
if (from < 0) from = 0;
TString& s = evalstack.peek_string();
s = s.sub(from, to);
}
{
const int to = (int)evalstack.pop_real().integer();
int from = (int)evalstack.pop_real().integer() - 1;
if (from < 0) from = 0;
TString & s1 = evalstack.peek_string();
s1 = s1.sub(from, to);
}
break;
case _pow:
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(real(pow(o1, o2)));
{
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = pow(r1, r2);
}
break;
case _min:
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(o1 < o2 ? o1 : o2);
{
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
if (r2 < r1)
r1 = r2;
}
break;
case _max:
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
evalstack.push(o1 > o2 ? o1 : o2);
{
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
if (r2 > r1)
r1 = r2;
}
break;
case _upper:
evalstack.peek_string().upper();
break;
case _round:
{
const int ndec = (int)evalstack.pop_real().integer();
o1 = evalstack.pop_real();
o1.round(ndec);
evalstack.push(o1);
}
{
const int ndec = (int)(evalstack.pop_real()).integer();
real & r = evalstack.peek_real();
r.round(ndec);
}
break;
case _trunc:
{
const int ndec = (int)evalstack.pop_real().integer();
o1 = evalstack.pop_real();
o1.trunc(ndec);
evalstack.push(o1);
}
{
const int ndec = (int)(evalstack.pop_real()).integer();
real & r = evalstack.peek_real();
r.trunc(ndec);
}
break;
case _ceil:
{
const int ndec = (int)evalstack.pop_real().integer();
o1 = evalstack.pop_real();
o1.ceil(ndec);
evalstack.push(o1);
}
{
const int ndec = (int)(evalstack.pop_real()).integer();
real & r = evalstack.peek_real();
r.ceil(ndec);
}
break;
case _perc:
{
o2 = evalstack.pop_real();
o1 = evalstack.pop_real();
const real val = real(o1 * o2 / 100.0);
evalstack.push(val);
}
{
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 = real(r1 * r2 / 100.0);
}
break;
case _scorp:
{
const real percent = evalstack.pop_real();
real val = evalstack.pop_real();
val -= val * percent / (percent + 100.0);
evalstack.push(val);
}
{
const real & r2 = evalstack.pop_real();
real & r1 = evalstack.peek_real();
r1 -= r1 * r2 / (r2 + 100.0);
}
break;
case _if:
{
if (type == _strexpr)
{
s1 = evalstack.pop_string();
s2 = evalstack.pop_string();
const real cond(evalstack.pop_string());
evalstack.push(cond.is_zero() ? s1 : s2);
{
if (type == _strexpr)
{
const TString & s1 = evalstack.pop_string();
const TString & s2 = evalstack.pop_string();
const real & cond = evalstack.pop_real();
evalstack.push(cond.is_zero() ? s1 : s2);
}
else
{
const real & r1 = evalstack.pop_real();
const real & r2 = evalstack.pop_real();
real & cond = evalstack.peek_real();
cond = cond.is_zero() ? r1 : r2;
}
}
else
{
o1 = evalstack.pop_real();
o2 = evalstack.pop_real();
const real cond = evalstack.pop_real();
evalstack.push(cond.is_zero() ? o1 : o2);
}
}
break;
case _ansi:
{
const TDate d(evalstack.pop_string());
const TString16 s(d.string(ANSI));
evalstack.push(s);
}
{
TString & s = evalstack.peek_string();
const TDate d(s);
s = d.string(ANSI);
}
break;
case _num:
type_pointer++;
types.set(type_pointer, FALSE);
@ -674,7 +664,7 @@ void TExpression::eval()
type_pointer--;
type = types[type_pointer] ? _numexpr : _strexpr;
if (type == _numexpr)
evalstack.push(real(evalstack.pop_string()));
evalstack.peek_real();
break;
case _str:
type_pointer++;
@ -685,7 +675,7 @@ void TExpression::eval()
type_pointer--;
type = types[type_pointer] ? _numexpr : _strexpr;
if (type == _strexpr)
evalstack.push(TString(evalstack.pop_real().string()));
evalstack.peek_string();
break;
default:
NFCHECK("operazione non valida %d", (int) instr.getsym());
@ -765,7 +755,8 @@ TCodesym TExpression::__gettoken(bool /* reduct */)
if (isdigit(*_s) || (*_s == '.'))
{
sym = _number;
while (isalnum(*_s) || (*_s == '_') || (*_s == '.') || (*_s == ':') ||
while (isalnum(*_s) || (*_s == '_') || (*_s == '.') ||
(*_s == ':') || (*_s == '@') ||
(sym == _number && (*_s == '-' || *_s == '[')) ||
(square_bracket && (*_s == ',' || *_s == ']'))
)
@ -781,7 +772,7 @@ TCodesym TExpression::__gettoken(bool /* reduct */)
{
if (sym == _number)
{
if (isalpha(*_s) || (*_s == '_') || (*_s == ':')
if (isalpha(*_s) || (*_s == '_') || (*_s == ':')
/* || (*_s == '[') || (*_s == ']') || (*_s == ',') */
)
sym = _variable;
@ -801,8 +792,8 @@ TCodesym TExpression::__gettoken(bool /* reduct */)
{
if (*_s == '#')
sym = _variable;
_tok[i++] = *(_s++);
_tok[i++] = *(_s++);
while (isalnum(*_s) || (*_s == '-') || (*_s == '[') ||
(*_s == ':') || (*_s == '_') ||
@ -940,6 +931,7 @@ TCodesym TExpression::__gettoken(bool /* reduct */)
return _invalid;
}
HIDDEN int __parms_found = -1;
TCodesym TExpression::__factor(TCodesym startsym)
{
@ -987,38 +979,23 @@ TCodesym TExpression::__factor(TCodesym startsym)
case _userfunc:
{
TValue val (_tok);
sym = __gettoken();
if (sym == _lpar)
{
sym = __gettoken();
int nparms = sym == _rpar ? 0 : 1;
if (sym != _rpar)
sym = __function();
if (sym != _invalid)
{
const int index = parse_user_func((const char *) val.string(), __parms_found);
if (index < 0)
{
while ((sym = __expression(sym)) == _comma)
{
sym = __gettoken(TRUE);
nparms++;
}
}
if (sym == _rpar)
{
_code.add(_number, real(nparms));
const int index = parse_user_func((const char *) val.string(), nparms);
if (index < 0)
{
strcpy(_tok, (const char *) val.string());
sym = _invalid;
}
else
{
val.set(format("%d", index));
_code.add(startsym, val);
_user_func_defined = TRUE;
sym = __gettoken(TRUE);
}
strcpy(_tok, (const char *) val.string());
sym = _invalid;
}
else
sym = _invalid;
{
_code.add(_number, real(__parms_found));
val.set(format("%d", index));
_code.add(startsym, val);
_user_func_defined = TRUE;
}
}
}
break;
@ -1032,21 +1009,8 @@ TCodesym TExpression::__factor(TCodesym startsym)
case _cos:
case _tan:
case _ansi:
sym = __gettoken();
if (sym == _lpar) sym = __gettoken();
else break;
sym = __expression(sym);
if (sym == _rpar) sym = __gettoken();
else break;
_code.add(startsym);
break;
case _upper:
sym = __gettoken();
if (sym == _lpar) sym = __gettoken();
else break;
sym = __expression(sym);
if (sym == _rpar) sym = __gettoken();
else break;
sym = __function(1);
_code.add(startsym);
break;
case _left:
@ -1059,57 +1023,22 @@ TCodesym TExpression::__factor(TCodesym startsym)
case _trunc:
case _perc:
case _scorp:
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 == _rpar) sym = __gettoken(TRUE);
else break;
sym = __function(2);
_code.add(startsym);
break;
case _mid:
case _substr:
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(TRUE);
else break;
sym = __function(3);
_code.add(startsym);
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(TRUE);
else break;
sym = __function(3);
_code.add(startsym);
break;
case _num:
case _str:
_code.add(startsym);
sym = __gettoken();
if (sym == _lpar) sym = __gettoken();
else break;
sym = __expression(sym);
if (sym == _rpar) sym = __gettoken();
else break;
sym = __function(1);
_code.add(startsym == _num ? _endnum : _endstr);
break;
default:
@ -1157,6 +1086,28 @@ TCodesym TExpression::__expression(TCodesym startsym)
return(sym);
}
TCodesym TExpression::__function(int nparms, bool fixed_num)
{
TCodesym sym = __gettoken(TRUE);
if (sym != _lpar)
return _invalid;
__parms_found = 0;
sym = __gettoken(TRUE);
if (sym == _rpar)
return nparms <= 0 || !fixed_num ? __gettoken(TRUE) : _invalid;
__parms_found++;
while ((sym = __expression(sym)) == _comma)
{
sym = __gettoken(TRUE);
__parms_found++;
}
if (sym == _rpar)
return nparms < 0 || __parms_found == nparms || (__parms_found < nparms && !fixed_num) ?
__gettoken(TRUE) :
_invalid;
return _invalid;
}
bool TExpression::set(const char* expression, TTypeexp type)
{
_original = expression;
@ -1173,50 +1124,6 @@ bool TExpression::compile(const char* expression, TTypeexp type)
_user_func_defined = FALSE;
_s = expression;
_type = type;
/*
TString sc(256);
while (((currsym = __gettoken()) != _endsym) && (currsym != _invalid))
{
if (currsym == _variable)
{
char *s1 = _tok;
while ((*s1) && (*s1 != '[')) s1++;
if (!*s1) sc << " " << _tok;
else
{
*s1 = '\0';
s1++;
char *s2 = s1;
while ((*s1) && (*s1 != ',')) s1++;
if (!*s1) sc << " " << _tok;
else
{
*s1 = '\0';
s1++;
int n1 = atoi(s2);
s2 = s1;
while ((*s1) && (*s1 != ']')) s1++;
if (!*s1) sc << " " << _tok;
else
{
const int n2 = atoi(s2);
sc << format(" mid(%s,%d,%d)", _tok, n1, (n2 < n1) ? 0 : n2 - n1 + 1);
}
}
}
}
else
if (currsym == _string)
{
const char sep (strchr(_tok, '\"') != NULL ? '\'' : '\"');
sc << sep << _tok << sep;
}
else sc << " " << _tok;
}
_s = sc;
*/
_val = real(0.0);
_code.clear();
if (*_s == '\0')

View File

@ -416,12 +416,14 @@ protected:
// @cmember Ritorna il prossimo token dell'espressione (se <p reduct> e' TRUE interpreta
// la virgola come un token)
TCodesym __gettoken(bool reduct = FALSE);
// @cmember Ritorna il prossimo fattore
// @cmember Esegue la compilazione di un fattore
TCodesym __factor(TCodesym startsym);
// @cmember Ritorna il prossimo termine
// @cmember Esegue la compilazione di un termine
TCodesym __term(TCodesym startsym);
// @cmember Ritorna la prossima espressione
// @cmember Esegue la compilazione di un'espressione
TCodesym __expression(TCodesym startsym);
// @cmember Esegue la compilazione di un una funzione
TCodesym __function(int nparms = -1, bool fixed_num = TRUE);
// @cmember Compila l'espressione
bool compile(const char* expression, TTypeexp type);