(PG su e giu' a velocita' variabile) con maschere contenenti spreadsheet nelle pagine successive alla prima. git-svn-id: svn://10.65.10.50/trunk@696 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			861 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			861 lines
		
	
	
		
			19 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 _match:
 | 
						|
      s2 = (TString&) evalstack.pop();
 | 
						|
      s1 = (TString&) evalstack.pop(); 
 | 
						|
      evalstack.push(TString((s1.match(s2)) ? "1" : "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((int)o2.integer());
 | 
						|
      evalstack.push(s1);
 | 
						|
      break;
 | 
						|
    case _right:
 | 
						|
      o2 = (real&) evalstack.pop();
 | 
						|
      s2 = (TString&) evalstack.pop();
 | 
						|
      s1 = s2.right((int)o2.integer());
 | 
						|
      evalstack.push(s1);
 | 
						|
      break;
 | 
						|
    case _mid:
 | 
						|
    {
 | 
						|
      int count = (int)((const real&)evalstack.pop()).integer();   
 | 
						|
      if (count == 0) count--;
 | 
						|
      const int from = (int)((const real&)evalstack.pop()).integer() - 1; 
 | 
						|
      const TString& s = ((const TString&)evalstack.pop()).mid(from, count);
 | 
						|
      evalstack.push(s);
 | 
						|
    }  
 | 
						|
      break;
 | 
						|
    case _pow:
 | 
						|
      o2 = (real&) evalstack.pop();
 | 
						|
      o1 = (real&) evalstack.pop();
 | 
						|
      evalstack.push(pow(o1, o2));
 | 
						|
      break;
 | 
						|
      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;
 | 
						|
    case _round:
 | 
						|
    {
 | 
						|
      const int ndec = (int)((real&) evalstack.pop()).integer();
 | 
						|
      o1 = (real&) evalstack.pop();
 | 
						|
      o1.round(ndec);
 | 
						|
      evalstack.push(o1);
 | 
						|
    }
 | 
						|
      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", 
 | 
						|
                                  "round", NULL };
 | 
						|
 | 
						|
HIDDEN TCodesym  _fntok[] = { _sqrt, _sqr, _exp10, _exp, _log10, _log,
 | 
						|
                              _sin, _cos, _tan, _left, _right, _pow,
 | 
						|
                              _min, _max, _mid, _upper, _round};
 | 
						|
 | 
						|
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;
 | 
						|
    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;
 | 
						|
    if ((sym == _string) || (sym == _variable)) sym = __expression(sym);
 | 
						|
    else break;
 | 
						|
    if (sym == _rpar) sym = __gettoken();
 | 
						|
    else break;
 | 
						|
    _code.add(startsym);
 | 
						|
    break;
 | 
						|
  case _left:
 | 
						|
  case _right:
 | 
						|
  case _pow:
 | 
						|
  case _min:
 | 
						|
  case _max:
 | 
						|
  case _round:
 | 
						|
    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();
 | 
						|
    else break;
 | 
						|
    _code.add(startsym);
 | 
						|
    break;
 | 
						|
  case _mid:
 | 
						|
    sym = __gettoken();
 | 
						|
    if (sym == _lpar) sym = __gettoken(TRUE);
 | 
						|
    else break;
 | 
						|
    if ((sym == _string) || (sym == _variable)) sym = __expression(sym);
 | 
						|
    else break;
 | 
						|
    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;
 | 
						|
  }
 | 
						|
  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) || (sym == _match)))
 | 
						|
  {
 | 
						|
    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);
 | 
						|
            sc << format(" mid(%s,%d,%d)", _tok, n1, (n2 < n1) ? 0 : 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;
 | 
						|
}
 |