857 lines
18 KiB
C++
Executable File
857 lines
18 KiB
C++
Executable File
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
#define __EXPR_CPP
|
|
#include <expr.h>
|
|
#include <stack.h>
|
|
#include <utility.h>
|
|
|
|
TCodearray::TCodearray(int size) : _rpn(size)
|
|
{
|
|
clear();
|
|
}
|
|
|
|
|
|
void TCodearray::clear()
|
|
{
|
|
_rpn.destroy();
|
|
_last = 0;
|
|
TCode *c = new TCode(_endsym);
|
|
_rpn.add(c, _last);
|
|
}
|
|
|
|
|
|
void TCodearray::add(TCodesym sym, const TValue& val)
|
|
{
|
|
TCode *c = new TCode(sym, val);
|
|
_rpn.add(c, _last++);
|
|
TCode *c1 = new TCode(_endsym);
|
|
_rpn.add(c1, _last);
|
|
}
|
|
|
|
TCode& TCode::operator =(const TCode& b)
|
|
{
|
|
_sym = b._sym;
|
|
_val = b._val;
|
|
return *this;
|
|
}
|
|
|
|
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++);
|
|
}
|
|
|
|
void TVararray::set(const char* name, const real& val)
|
|
|
|
{
|
|
for (int i = 0; i < _array.items(); i++)
|
|
if (strcmp(((TVar&) _array[i]).getname(), name) == 0)
|
|
{
|
|
((TVar&) _array[i]) = (TValue&) val;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void TVararray::set(const char* name, const char* val)
|
|
|
|
{
|
|
for (int i = 0; i < _array.items(); i++)
|
|
if (strcmp(((TVar&) _array[i]).getname(), name) == 0)
|
|
{
|
|
((TVar&) _array[i]) = (TValue&) val;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
real __r;
|
|
|
|
const real& TVararray::getnum(const char* name)
|
|
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < _array.items(); i++)
|
|
{
|
|
if (strcmp(((TVar*) _array.objptr(i))->getname(), name) == 0)
|
|
{
|
|
__r = ((TVar*) _array.objptr(i))->number();
|
|
return __r;
|
|
}
|
|
}
|
|
fatal_box("Unknown variable : %s", name);
|
|
return __r;
|
|
}
|
|
|
|
|
|
const real& TVararray::getnum(int varnum)
|
|
|
|
{
|
|
if (varnum >= _array.items())
|
|
fatal_box("invalid variable number : %d", varnum);
|
|
__r = ((TVar*) _array.objptr(varnum))->number();
|
|
return __r;
|
|
}
|
|
|
|
|
|
const char* TVararray::getstring(const char* name)
|
|
|
|
{
|
|
const char* s = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < _array.items(); i++)
|
|
{
|
|
if (strcmp(((TVar*) _array.objptr(i))->getname(), name) == 0)
|
|
return ((TVar*) _array.objptr(i))->string();
|
|
}
|
|
fatal_box("Unknown variable : %s", name);
|
|
return s;
|
|
}
|
|
|
|
|
|
const char* TVararray::getstring(int varnum)
|
|
|
|
{
|
|
if (varnum >= _array.items())
|
|
fatal_box("invalid variable number : %d", varnum);
|
|
return ((TVar*) _array.objptr(varnum))->string();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TExpression
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TExpression::TExpression(const char* expression, TTypeexp type)
|
|
: _original(expression)
|
|
|
|
{
|
|
_val = real(0.0);
|
|
_dirty = TRUE;
|
|
_type = type;
|
|
if (!compile(expression, type))
|
|
{
|
|
error_box("Wrong expression : %s", expression);
|
|
_code.clear();
|
|
}
|
|
}
|
|
|
|
|
|
TExpression::TExpression(TTypeexp type)
|
|
: _original("")
|
|
|
|
{
|
|
_val = real(0.0);
|
|
_dirty = FALSE;
|
|
_type = type;
|
|
_code.clear();
|
|
}
|
|
|
|
|
|
TExpression::operator const real&()
|
|
|
|
{
|
|
if (_dirty) eval();
|
|
_dirty = FALSE;
|
|
return _val.number();
|
|
}
|
|
|
|
|
|
TExpression::operator const char*()
|
|
|
|
{
|
|
if (_dirty) eval();
|
|
_dirty = FALSE;
|
|
return _val.string();
|
|
}
|
|
|
|
|
|
void TExpression::print_on(ostream& out) const
|
|
{ out << _original; }
|
|
|
|
|
|
TExpression::operator bool()
|
|
|
|
{
|
|
if (_dirty) eval();
|
|
_dirty = FALSE;
|
|
const real& r = _val.number();
|
|
return !r.is_zero();
|
|
}
|
|
|
|
|
|
void TExpression::setvar(const char* varname, const real& val)
|
|
|
|
{
|
|
_dirty = TRUE;
|
|
_var.set(varname, val);
|
|
}
|
|
|
|
|
|
void TExpression::setvar(int varnum, const real& val)
|
|
|
|
{
|
|
_dirty = TRUE;
|
|
_var.set(varnum, val);
|
|
}
|
|
|
|
|
|
void TExpression::setvar(const char* varname, const char* val)
|
|
|
|
{
|
|
_dirty = TRUE;
|
|
_var.set(varname, val);
|
|
}
|
|
|
|
|
|
void TExpression::setvar(int varnum, const char* val)
|
|
|
|
{
|
|
_dirty = TRUE;
|
|
_var.set(varnum, val);
|
|
}
|
|
|
|
|
|
void TExpression::eval()
|
|
|
|
{
|
|
TStack evalstack(50);
|
|
TCode instr;
|
|
real o1, o2, zero(0.00);
|
|
TString s1, s2;
|
|
|
|
_code.begin();
|
|
while (!_code.end())
|
|
{
|
|
instr = _code.step();
|
|
switch (instr.getsym())
|
|
{
|
|
case _invalid:
|
|
case _endsym:
|
|
break;
|
|
case _variable:
|
|
if (_type == _strexpr)
|
|
{
|
|
s1 = _var.getstring(instr.string());
|
|
evalstack.push(s1);
|
|
}
|
|
else
|
|
{
|
|
o1 = _var.getnum(instr.string());
|
|
evalstack.push(o1);
|
|
}
|
|
break;
|
|
case _number:
|
|
o1 = instr.number();
|
|
evalstack.push(o1);
|
|
break;
|
|
case _string:
|
|
s1 = instr.string();
|
|
evalstack.push(s1);
|
|
break;
|
|
case _plus:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
s1 << s2;
|
|
evalstack.push(s1);
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(o1 + o2);
|
|
}
|
|
break;
|
|
case _minus:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(o1 - o2);
|
|
break;
|
|
case _multiply:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(o1 * o2);
|
|
break;
|
|
case _divide:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(o1 / o2);
|
|
break;
|
|
case _chgs:
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(-o1);
|
|
break;
|
|
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"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 != zero && o2 != zero) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _or:
|
|
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"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
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));
|
|
break;
|
|
case _equal:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
evalstack.push(TString((s1 == s2) ? "1" : "0"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 == o2) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _noteq:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
evalstack.push(TString(s1 != s2 ? "1" : "0"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 != o2) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _lt:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
evalstack.push(TString((s1 < (const char*)s2) ? "1" : "0"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 < o2) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _gt:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
evalstack.push(TString((s1 > (const char*)s2) ? "1" : "0"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 > o2) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _lteq:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
evalstack.push(TString((s1 <= (const char*)s2) ? "1" : "0"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 <= o2) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _gteq:
|
|
if (_type == _strexpr)
|
|
{
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = (TString&) evalstack.pop();
|
|
evalstack.push(TString((s1 >= (const char*)s2) ? "1" : "0"));
|
|
}
|
|
else
|
|
{
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(real((o1 >= o2) ? 1.0 : 0.0));
|
|
}
|
|
break;
|
|
case _sqrt:
|
|
evalstack.push(sqrt((real&) evalstack.pop()));
|
|
break;
|
|
case _sqr:
|
|
evalstack.push(sqr((real&) evalstack.pop()));
|
|
break;
|
|
case _exp10:
|
|
evalstack.push(exp10((real&) evalstack.pop()));
|
|
break;
|
|
case _exp:
|
|
evalstack.push(exp((real&) evalstack.pop()));
|
|
break;
|
|
case _log10:
|
|
evalstack.push(log10((real&) evalstack.pop()));
|
|
break;
|
|
case _log:
|
|
evalstack.push(log((real&) evalstack.pop()));
|
|
break;
|
|
case _sin:
|
|
evalstack.push(sin((real&) evalstack.pop()));
|
|
break;
|
|
case _cos:
|
|
evalstack.push(cos((real&) evalstack.pop()));
|
|
break;
|
|
case _tan:
|
|
evalstack.push(tan((real&) evalstack.pop()));
|
|
break;
|
|
case _left:
|
|
o2 = (real&) evalstack.pop();
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = s2.left(o2.integer());
|
|
evalstack.push(s1);
|
|
break;
|
|
case _right:
|
|
o2 = (real&) evalstack.pop();
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = s2.right(o2.integer());
|
|
evalstack.push(s1);
|
|
break;
|
|
case _mid:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
o1 -= 1.00;
|
|
s2 = (TString&) evalstack.pop();
|
|
s1 = s2.mid(o1.integer(), o2.integer());
|
|
evalstack.push(s1);
|
|
break;
|
|
case _pow:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(pow(o1, o2));
|
|
break;
|
|
case _min:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(fnc_min(o1, o2));
|
|
break;
|
|
case _max:
|
|
o2 = (real&) evalstack.pop();
|
|
o1 = (real&) evalstack.pop();
|
|
evalstack.push(fnc_min(o1, o2));
|
|
break;
|
|
case _upper:
|
|
s1 = (TString&) evalstack.pop();
|
|
s1.upper();
|
|
evalstack.push(s1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (_type == _strexpr)
|
|
_val = (const char*) (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", NULL };
|
|
|
|
HIDDEN TCodesym _fntok[] = { _sqrt, _sqr, _exp10, _exp, _log10, _log,
|
|
_sin, _cos, _tan, _left, _right, _pow,
|
|
_min, _max, _mid, _upper};
|
|
|
|
TCodesym TExpression::__gettoken(bool reduct)
|
|
|
|
{
|
|
TCodesym sym = _invalid;
|
|
int i = 0;
|
|
|
|
_tok[0] = '\0';
|
|
while (isspace(*_s)) _s++;
|
|
if (!*_s) return _endsym;
|
|
if ((reduct) && (*_s == ','))
|
|
{
|
|
_s++;
|
|
return _comma;
|
|
}
|
|
if (isdigit(*_s) || (*_s == '.') || (*_s == ','))
|
|
{
|
|
sym = _number;
|
|
while (isalpha(*_s) || isdigit(*_s) || (*_s == '-') || (*_s == '[') ||
|
|
(*_s == ']') || (*_s == '.') || (*_s == ':') ||
|
|
(!reduct && (*_s == ',')))
|
|
{
|
|
if (*_s == '-')
|
|
{
|
|
if (_s[1] != '>') break;
|
|
_tok[i++] = *(_s++);
|
|
_tok[i++] = *(_s++);
|
|
sym = _variable;
|
|
}
|
|
else
|
|
{
|
|
if (sym == _number)
|
|
if ((isalpha(*_s)) ||(*_s == '[') || (*_s == ']') ||
|
|
(*_s == ',') || (*_s == ':')) sym = _variable;
|
|
_tok[i++] = *(_s++);
|
|
}
|
|
}
|
|
_tok[i] = '\0';
|
|
return sym;
|
|
}
|
|
if (isalpha(*_s) || (*_s == '#'))
|
|
{
|
|
_tok[i++] = *(_s++);
|
|
while (isalpha(*_s) || isdigit(*_s) || (*_s == '-') || (*_s == '[') ||
|
|
(*_s == ']') || (*_s == ':') || (!reduct && (*_s == ',')))
|
|
{
|
|
if (*_s == '-')
|
|
{
|
|
if (_s[1] != '>') break;
|
|
_tok[i++] = *(_s++);
|
|
}
|
|
_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];
|
|
return _variable;
|
|
}
|
|
switch (*_s)
|
|
{
|
|
case '"' :
|
|
_s++;
|
|
while ((*_s) && (*_s != '"'))
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
if (*_s == '"') _s++;
|
|
return _string;
|
|
case ',' :
|
|
_s++;
|
|
return _comma;
|
|
case '(' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _lpar;
|
|
case ')' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _rpar;
|
|
case '+' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _plus;
|
|
case '-' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _minus;
|
|
case '*' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _multiply;
|
|
case '/' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _divide;
|
|
case '&' :
|
|
_tok[i++] = *(_s++);
|
|
if (*_s != '&') break;
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _and;
|
|
case '|' :
|
|
_tok[i++] = *(_s++);
|
|
if (*_s != '|') break;
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _or;
|
|
case '!' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
if (*_s == '=')
|
|
{
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _noteq;
|
|
}
|
|
return _not;
|
|
case '=' :
|
|
_tok[i++] = *(_s++);
|
|
if (*_s == '=') _tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _equal;
|
|
case '?' :
|
|
_tok[i++] = *(_s++);
|
|
if (*_s == '=') _tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _match;
|
|
case '>' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
if (*_s == '=')
|
|
{
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _gteq;
|
|
}
|
|
return _gt;
|
|
case '<' :
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
if (*_s == '=')
|
|
{
|
|
_tok[i++] = *(_s++);
|
|
_tok[i] = '\0';
|
|
return _lteq;
|
|
}
|
|
return _lt;
|
|
default:
|
|
break;
|
|
}
|
|
return _invalid;
|
|
}
|
|
|
|
|
|
TCodesym TExpression::__factor(TCodesym startsym)
|
|
|
|
{
|
|
TCodesym sym = _invalid;
|
|
|
|
switch (startsym)
|
|
{
|
|
case _lpar:
|
|
sym = __gettoken();
|
|
sym = __expression(sym);
|
|
if (sym == _rpar) sym = __gettoken();
|
|
break;
|
|
case _variable:
|
|
case _number:
|
|
case _string:
|
|
_code.add(startsym, _tok);
|
|
if (startsym == _variable)
|
|
{
|
|
for (int i = 0 ; i < numvar(); i++)
|
|
if (strcmp(_tok, varname(i)) == 0) break;
|
|
if (i == numvar()) _var.add(_tok);
|
|
}
|
|
sym = __gettoken(TRUE);
|
|
break;
|
|
case _sqrt:
|
|
case _sqr:
|
|
case _exp10:
|
|
case _exp:
|
|
case _log10:
|
|
case _log:
|
|
case _sin:
|
|
case _cos:
|
|
case _tan:
|
|
sym = __gettoken();
|
|
if (sym == _lpar) sym = __gettoken();
|
|
else break;
|
|
if ((sym == _number) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _rpar) sym = __gettoken();
|
|
else break;
|
|
_code.add(startsym);
|
|
break;
|
|
case _upper:
|
|
sym = __gettoken();
|
|
if (sym == _lpar) sym = __gettoken();
|
|
else break;
|
|
if ((sym == _string) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _rpar) sym = __gettoken();
|
|
else break;
|
|
_code.add(startsym);
|
|
break;
|
|
case _left:
|
|
case _right:
|
|
case _pow:
|
|
case _min:
|
|
case _max:
|
|
sym = __gettoken();
|
|
if (sym == _lpar) sym = __gettoken(TRUE);
|
|
else break;
|
|
if ((sym == _number) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _comma) sym = __gettoken(TRUE);
|
|
else break;
|
|
if ((sym == _number) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _rpar) sym = __gettoken();
|
|
else break;
|
|
_code.add(startsym);
|
|
break;
|
|
case _mid:
|
|
sym = __gettoken();
|
|
if (sym == _lpar) sym = __gettoken(TRUE);
|
|
else break;
|
|
if ((sym == _number) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _comma) sym = __gettoken(TRUE);
|
|
else break;
|
|
if ((sym == _number) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _comma) sym = __gettoken(TRUE);
|
|
else break;
|
|
if ((sym == _number) || (sym == _variable)) sym = __factor(sym);
|
|
else break;
|
|
if (sym == _rpar) sym = __gettoken();
|
|
else break;
|
|
_code.add(startsym);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return sym;
|
|
}
|
|
|
|
|
|
TCodesym TExpression::__term(TCodesym startsym)
|
|
|
|
{
|
|
TCodesym sym;
|
|
|
|
sym = __factor(startsym);
|
|
while ((sym != _endsym) && ((sym == _multiply) || (sym == _divide)))
|
|
{
|
|
TCodesym savedsym = sym;
|
|
sym = __gettoken();
|
|
sym = __factor(startsym);
|
|
_code.add(savedsym);
|
|
}
|
|
|
|
return sym;
|
|
}
|
|
|
|
|
|
TCodesym TExpression::__expression(TCodesym startsym)
|
|
|
|
{
|
|
TCodesym sym;
|
|
|
|
if ((startsym == _minus) || (startsym == _not) || (startsym == _plus))
|
|
sym =__gettoken();
|
|
else sym = startsym;
|
|
sym = __term(sym);
|
|
if ((startsym == _minus) || (startsym == _not))
|
|
_code.add(startsym == _not ? startsym : _chgs);
|
|
while ((sym != _endsym) &&
|
|
((sym == _minus) || (sym == _plus) || (sym == _equal) ||
|
|
(sym == _noteq) || (sym == _gt) || (sym == _lt) ||
|
|
(sym == _gteq) || (sym == _lteq) || (sym == _and) ||
|
|
(sym == _or)))
|
|
{
|
|
TCodesym savedsym = sym;
|
|
sym = __gettoken();
|
|
sym = __term(sym);
|
|
_code.add(savedsym);
|
|
}
|
|
return(sym);
|
|
}
|
|
|
|
bool TExpression::set(const char* expression, TTypeexp type)
|
|
{
|
|
_original = expression;
|
|
_type = type;
|
|
_dirty = TRUE;
|
|
return compile(expression, type);
|
|
}
|
|
|
|
bool TExpression::compile(const char* expression, TTypeexp type)
|
|
|
|
{
|
|
TString sc(256);
|
|
TCodesym currsym;
|
|
|
|
_s = expression;
|
|
_type = type;
|
|
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);
|
|
// if (n1 == 0) sc << format(" right(%s,%d)", _tok, n2);
|
|
// else
|
|
// if (n2 == 0) sc << format(" left(%s,%d)", _tok, n1);
|
|
// else
|
|
if (n2 == 0) sc << format(" mid(%s,%d,0)", _tok, n1);
|
|
else
|
|
sc << format(" mid(%s,%d,%d)", _tok, n1, n2 - n1 + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (currsym == _string) sc << " \"" << _tok << "\"";
|
|
else sc << " " << _tok;
|
|
}
|
|
_s = sc;
|
|
_val = real(0.0);
|
|
_code.clear();
|
|
if (!*_s) return TRUE;
|
|
if ((currsym = __gettoken()) == _invalid) return FALSE;
|
|
return __expression(currsym) == _endsym;
|
|
}
|