Files correlati : omnia0.exe omnia.xml Ricompilazione Demo : [ ] Commento : Ultimissima verisione dell'acqua tutte le cose. git-svn-id: svn://10.65.10.50/trunk@11735 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1241 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1241 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <ctype.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#define __EXPR_CPP
 | 
						|
#include "expr.h"
 | 
						|
#include "date.h"
 | 
						|
 | 
						|
void TCodearray::clear()
 | 
						|
{
 | 
						|
  destroy();
 | 
						|
  TArray::add(new TCode(_endsym));
 | 
						|
}
 | 
						|
 | 
						|
void TCodearray::add(TCodesym sym, const TValue& val)
 | 
						|
{
 | 
						|
  TArray::insert(new TCode(sym, val), last());
 | 
						|
}
 | 
						|
 | 
						|
TObject * TCode::dup() const
 | 
						|
{
 | 
						|
  TCode * o = new TCode(*this);
 | 
						|
  return o;
 | 
						|
}    
 | 
						|
 | 
						|
TCode& TCode::operator =(const TCode& b)
 | 
						|
{
 | 
						|
  _sym = b._sym;
 | 
						|
  _val = b._val;
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
TObject * TVar::dup() const
 | 
						|
{
 | 
						|
  TVar * o = new TVar(*this);
 | 
						|
  return o;
 | 
						|
}    
 | 
						|
 | 
						|
void TVararray::add(const char* name, const TValue& val)
 | 
						|
{
 | 
						|
  TArray::add(new TVar(name, val));
 | 
						|
}
 | 
						|
 | 
						|
void TVararray::set(const char* name, const real& val)
 | 
						|
{
 | 
						|
  for (int i = last(); i >= 0; i--)
 | 
						|
  {
 | 
						|
    TVar* var = (TVar*)objptr(i);
 | 
						|
    if (var->getname() == name)
 | 
						|
    {     
 | 
						|
      *var = val;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }  
 | 
						|
  NFCHECK("Variabile non trovata: %s", name);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TVararray::set(const char* name, const char* val)
 | 
						|
{
 | 
						|
  for (int i = last(); i >= 0; i--)
 | 
						|
  {
 | 
						|
    TVar* var = (TVar*)objptr(i);
 | 
						|
    if (var->getname() == name)
 | 
						|
    {
 | 
						|
      *var = val;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }  
 | 
						|
  NFCHECK("Variabile non trovata: %s", name);
 | 
						|
}
 | 
						|
 | 
						|
const real& TVararray::getnum(const char* name)
 | 
						|
{
 | 
						|
  for (int i = items()-1; i >= 0; i--)
 | 
						|
  {
 | 
						|
    TVar* var = (TVar*)objptr(i);
 | 
						|
    if (var->getname() == name)
 | 
						|
      return var->number();
 | 
						|
  }
 | 
						|
  NFCHECK("Unknown variable: %s", name);
 | 
						|
  return ZERO;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
const real& TVararray::getnum(int varnum)
 | 
						|
{
 | 
						|
  if (varnum < 0 || varnum >= items())
 | 
						|
  {
 | 
						|
    NFCHECK("Invalid variable number : %d", varnum);
 | 
						|
    return ZERO;
 | 
						|
  }        
 | 
						|
  return ((TVar*)objptr(varnum))->number();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
const TString& TVararray::getstring(const char* name)
 | 
						|
{
 | 
						|
  for (int i = last(); i >= 0; i--)
 | 
						|
  {
 | 
						|
    TVar* var = (TVar*)objptr(i);
 | 
						|
    if (var->getname() == name)
 | 
						|
      return var->string();
 | 
						|
  }
 | 
						|
  NFCHECK("Unknown variable : %s", name);
 | 
						|
  return EMPTY_STRING;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
const TString& TVararray::getstring(int varnum)
 | 
						|
{
 | 
						|
  TVar* var = (TVar*)objptr(varnum);
 | 
						|
  if (var == NULL)
 | 
						|
  {
 | 
						|
    NFCHECK("Invalid variable number : %d", varnum);
 | 
						|
    return EMPTY_STRING;
 | 
						|
  }        
 | 
						|
  return var->string();
 | 
						|
}           
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TEval_stack
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
void TEval_stack::push(bool b)
 | 
						|
{
 | 
						|
  if (_sp < _data.items())
 | 
						|
  {
 | 
						|
    _sp++;
 | 
						|
    peek_real() = b ? 1.0 : 0.0;
 | 
						|
  }
 | 
						|
  else  
 | 
						|
    TStack::push(new TValue(b ? real(1.0) : ZERO));
 | 
						|
}
 | 
						|
 | 
						|
void TEval_stack::push(int n)
 | 
						|
{
 | 
						|
  if (_sp < _data.items())
 | 
						|
  {
 | 
						|
    _sp++;
 | 
						|
    peek_real() = n;
 | 
						|
  }
 | 
						|
  else  
 | 
						|
    TStack::push(new TValue(real(n)));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TEval_stack::push(const real& r)
 | 
						|
{
 | 
						|
  if (_sp < _data.items())
 | 
						|
  {
 | 
						|
    _sp++;
 | 
						|
    peek_real() = r;
 | 
						|
  }
 | 
						|
  else  
 | 
						|
    TStack::push(new TValue(r));
 | 
						|
}
 | 
						|
 | 
						|
void TEval_stack::push(const TString& s)
 | 
						|
{   
 | 
						|
  if (_sp < _data.items())
 | 
						|
  {
 | 
						|
    _sp++;
 | 
						|
    peek_string() = s;
 | 
						|
  }
 | 
						|
  else  
 | 
						|
    TStack::push(new TValue(s));
 | 
						|
}
 | 
						|
 | 
						|
void TEval_stack::push(const char* s)
 | 
						|
{
 | 
						|
  if (_sp < _data.items())
 | 
						|
  {
 | 
						|
    _sp++;
 | 
						|
    peek_string() = s;
 | 
						|
  }
 | 
						|
  else  
 | 
						|
    TStack::push(new TValue(s));
 | 
						|
}
 | 
						|
 | 
						|
real& TEval_stack::pop_real()
 | 
						|
{          
 | 
						|
  TValue& o = (TValue&)pop();
 | 
						|
  return o.number();
 | 
						|
}
 | 
						|
 | 
						|
real& TEval_stack::peek_real()
 | 
						|
{          
 | 
						|
  TValue& o = (TValue&)peek(0);
 | 
						|
  return o.number();
 | 
						|
}
 | 
						|
 | 
						|
TString& TEval_stack::pop_string()
 | 
						|
{          
 | 
						|
  TValue& o = (TValue&)pop();
 | 
						|
  return o.string();
 | 
						|
}
 | 
						|
 | 
						|
TString& TEval_stack::peek_string()
 | 
						|
{          
 | 
						|
  TValue& o = (TValue&)peek(0);
 | 
						|
  return o.string();
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TExpression
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
TExpression::TExpression(const char* expression, TTypeexp type, bool ignore_err)
 | 
						|
           : _original(expression)
 | 
						|
{
 | 
						|
  _ignore_error=ignore_err;
 | 
						|
  _error=0;
 | 
						|
  _dirty = TRUE;
 | 
						|
  _type = type;
 | 
						|
  compile(_original, type);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
TExpression::TExpression(TTypeexp type, bool ignore_err)
 | 
						|
{
 | 
						|
  _ignore_error=ignore_err;   
 | 
						|
  _error=0;
 | 
						|
  _dirty = FALSE;
 | 
						|
  _type = type;
 | 
						|
  _code.clear();
 | 
						|
}
 | 
						|
 | 
						|
TExpression::TExpression(const TExpression & expr)
 | 
						|
           : _code(expr._code), _var(expr._var), 
 | 
						|
             _val(expr._val), _dirty(expr._dirty), 
 | 
						|
             _type(expr._type), _original(expr._original),
 | 
						|
             _user_func_defined(expr._user_func_defined),
 | 
						|
             _ignore_error(expr._ignore_error),_error(expr._error)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
TObject* TExpression::dup() const
 | 
						|
{
 | 
						|
  TExpression* o = new TExpression(*this);
 | 
						|
  return o;
 | 
						|
}    
 | 
						|
 | 
						|
const real & TExpression::as_real()
 | 
						|
{            
 | 
						|
  if (user_func_dirty() || _dirty) 
 | 
						|
    eval();
 | 
						|
  _dirty = FALSE;
 | 
						|
  return _val.number();
 | 
						|
}
 | 
						|
 | 
						|
const TString & TExpression::as_string()
 | 
						|
{            
 | 
						|
  if (user_func_dirty() || _dirty) eval();
 | 
						|
  _dirty = FALSE;
 | 
						|
  return _val.string();
 | 
						|
}
 | 
						|
 | 
						|
bool TExpression::as_bool()
 | 
						|
{            
 | 
						|
  return !as_real().is_zero();
 | 
						|
}
 | 
						|
 | 
						|
void TExpression::print_on(ostream& out) const       
 | 
						|
{ out << _original; }
 | 
						|
 | 
						|
void TExpression::evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp  curtype) const
 | 
						|
{                
 | 
						|
  NFCHECK("Unknown function %d.", index);
 | 
						|
  for (int i = nparms; i > 0; i--)
 | 
						|
    stack.pop(); 
 | 
						|
  stack.push(ZERO);
 | 
						|
}    
 | 
						|
 | 
						|
void TExpression::setvar(const char* varname, const real& val)
 | 
						|
{
 | 
						|
  if (_var.getnum(varname) != val)
 | 
						|
  {
 | 
						|
    _var.set(varname, val);
 | 
						|
    _dirty = TRUE;
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
void TExpression::setvar(int varnum, const real& val)
 | 
						|
{
 | 
						|
  if (_var.getnum(varnum) != val)
 | 
						|
  {
 | 
						|
    _var.set(varnum, val);
 | 
						|
    _dirty = TRUE;
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
void TExpression::setvar(const char* varname, const char* val)
 | 
						|
{
 | 
						|
  if (_var.getstring(varname) != val)
 | 
						|
  {
 | 
						|
    _var.set(varname, val);
 | 
						|
    _dirty = TRUE;
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TExpression::setvar(int varnum, const char* val)
 | 
						|
{
 | 
						|
  if (strcmp(_var.getstring(varnum), val) != 0)
 | 
						|
  {
 | 
						|
    _var.set(varnum, val);
 | 
						|
    _dirty = TRUE;
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
bool TExpression::print_error(const char* msg) const
 | 
						|
{
 | 
						|
  return yesnofatal_box("%s", msg);
 | 
						|
}
 | 
						|
 | 
						|
void TExpression::eval()
 | 
						|
{                                   
 | 
						|
  TEval_stack evalstack;
 | 
						|
  TBit_array  types;
 | 
						|
  int         type_pointer = 0;
 | 
						|
  TCode       instr;
 | 
						|
    
 | 
						|
  types.set(type_pointer, (_type == _numexpr));
 | 
						|
  
 | 
						|
  TTypeexp type = _type;
 | 
						|
  
 | 
						|
  _code.begin();
 | 
						|
  while (!_code.end())
 | 
						|
  {
 | 
						|
    instr = _code.step();
 | 
						|
    switch (instr.getsym())
 | 
						|
    {
 | 
						|
    case _invalid:
 | 
						|
    case _endsym:
 | 
						|
      break;
 | 
						|
    case _variable:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString & s1 = _var.getstring(instr.string());
 | 
						|
        evalstack.push(s1);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        const real & r1 = _var.getnum(instr.string());
 | 
						|
        evalstack.push(r1);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _number:    
 | 
						|
      {
 | 
						|
        const real & r1 = instr.number();
 | 
						|
        evalstack.push(r1);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _string:
 | 
						|
      {
 | 
						|
        const TString & s1 = instr.string();
 | 
						|
        evalstack.push(s1);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _plus:                    
 | 
						|
      if (type == _strexpr)
 | 
						|
      {  
 | 
						|
        // Non unire le seguenti righe
 | 
						|
        const TString& s = evalstack.pop_string();
 | 
						|
        evalstack.peek_string() << s;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        // Non unire le seguenti righe
 | 
						|
        const real& r = evalstack.pop_real();
 | 
						|
        evalstack.peek_real() += r;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _minus:
 | 
						|
      {
 | 
						|
        const real& r = evalstack.pop_real();
 | 
						|
        evalstack.peek_real() -= r;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _multiply:
 | 
						|
      {
 | 
						|
        const real& r = evalstack.pop_real();
 | 
						|
        evalstack.peek_real() *= r;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _divide:
 | 
						|
      {
 | 
						|
        const real& r = evalstack.pop_real();
 | 
						|
        if (r.is_zero())
 | 
						|
        {
 | 
						|
          if (!evalstack.peek_real().is_zero())
 | 
						|
            if (_ignore_error)
 | 
						|
              _error=1;
 | 
						|
            else
 | 
						|
              print_error("Divisione per zero!");
 | 
						|
        } else
 | 
						|
          evalstack.peek_real() /= r;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _chgs:
 | 
						|
      {
 | 
						|
        real & r = evalstack.peek_real();
 | 
						|
        r = -r;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _and:
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();   
 | 
						|
        r1 = (!r1.is_zero() && !r2.is_zero()) ? UNO : ZERO;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _or:
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();   
 | 
						|
        r1 = (r1 != ZERO || r2 != ZERO) ? UNO : ZERO;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _not:
 | 
						|
      {
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = (r1 == ZERO) ? 1.0 : 0.0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _equal:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString & s2 = evalstack.pop_string();
 | 
						|
        const TString & s1 = evalstack.pop_string(); 
 | 
						|
        evalstack.push(s1 == s2);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = (r1 == r2) ? 1.0 : 0.0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _match:                                    
 | 
						|
     {
 | 
						|
        const TString & s2 = evalstack.pop_string();
 | 
						|
        const TString & s1 = evalstack.pop_string(); 
 | 
						|
        // evalstack.push(s1.match(s2));  // TBI
 | 
						|
        evalstack.push(ZERO);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _noteq:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString & s2 = evalstack.pop_string();
 | 
						|
        TString & s1 = evalstack.pop_string(); 
 | 
						|
        evalstack.push(s1 != s2);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = (r1 != r2) ? 1.0 : 0.0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _lt:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString & s2 = evalstack.pop_string();
 | 
						|
        const TString & s1 = evalstack.pop_string(); 
 | 
						|
        evalstack.push(s1 < s2);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = (r1 < r2) ? 1.0 : 0.0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _gt:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString & s2 = evalstack.pop_string();
 | 
						|
        const TString & s1 = evalstack.pop_string(); 
 | 
						|
        evalstack.push(s1 > s2);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = (r1 > r2) ? 1.0 : 0.0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _lteq:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString& s2 = evalstack.pop_string();
 | 
						|
        const TString& s1 = evalstack.pop_string(); 
 | 
						|
        evalstack.push(s1 <= s2);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        const real& r2 = evalstack.pop_real();
 | 
						|
        real& r1 = evalstack.peek_real();
 | 
						|
        r1 = (r1 <= r2) ? 1.0 : 0.0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _gteq:
 | 
						|
      if (type == _strexpr)
 | 
						|
      {
 | 
						|
        const TString& s2 = evalstack.pop_string();
 | 
						|
        const TString& s1 = evalstack.pop_string(); 
 | 
						|
        evalstack.push(s1 >= s2);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        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) evalstack.pop_real().integer();
 | 
						|
        const int index = atoi(instr.string());
 | 
						|
        
 | 
						|
        evaluate_user_func(index, nparms, evalstack, type);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _sqrt:
 | 
						|
      {
 | 
						|
        real& r = evalstack.peek_real();
 | 
						|
        if (r < ZERO)
 | 
						|
        {
 | 
						|
          if (_ignore_error)
 | 
						|
            _error=1;
 | 
						|
          else
 | 
						|
            print_error("Radice negativa!");
 | 
						|
          r = -r;
 | 
						|
        } 
 | 
						|
        r = sqrt(r);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _sqr:
 | 
						|
      evalstack.peek_real() = sqr(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _exp10:
 | 
						|
      evalstack.peek_real() = exp10(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _exp:
 | 
						|
      evalstack.peek_real() = exp(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _log10:
 | 
						|
      evalstack.peek_real() = log10(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _log:
 | 
						|
      evalstack.peek_real() = log(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _sin:
 | 
						|
      evalstack.peek_real() = sin(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _cos:
 | 
						|
      evalstack.peek_real() = cos(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _tan:
 | 
						|
      evalstack.peek_real() = tan(evalstack.peek_real());
 | 
						|
      break;
 | 
						|
    case _left:
 | 
						|
      {
 | 
						|
        const int len = (int)evalstack.pop_real().integer();
 | 
						|
        TString & s1 = evalstack.peek_string();
 | 
						|
        s1 = s1.left(len);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _right:
 | 
						|
      {
 | 
						|
        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 & 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 & s1 = evalstack.peek_string();
 | 
						|
        s1 = s1.sub(from, to);
 | 
						|
      }  
 | 
						|
      break;
 | 
						|
    case _len:
 | 
						|
      {
 | 
						|
        TString& s1 = evalstack.pop_string();
 | 
						|
        evalstack.push(s1.len());
 | 
						|
      }  
 | 
						|
      break;
 | 
						|
    case _pow:
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = pow(r1, r2);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _min:
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        if (r2 < r1)
 | 
						|
          r1 = r2;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _max:
 | 
						|
      {
 | 
						|
        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 _trim:
 | 
						|
      evalstack.peek_string().trim();
 | 
						|
      break;
 | 
						|
    case _round:
 | 
						|
      {
 | 
						|
        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();
 | 
						|
        real & r = evalstack.peek_real();
 | 
						|
        r.trunc(ndec);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _ceil:
 | 
						|
      {
 | 
						|
        const int ndec = (int)(evalstack.pop_real()).integer();
 | 
						|
        real & r = evalstack.peek_real();
 | 
						|
        r.ceil(ndec);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _perc:
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 = real(r1 * r2 / 100.0);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _scorp:
 | 
						|
      {
 | 
						|
        const real & r2 = evalstack.pop_real();
 | 
						|
        real & r1 = evalstack.peek_real();
 | 
						|
        r1 -= r1 * r2 / (r2 + 100.0);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _if:
 | 
						|
      {     
 | 
						|
        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;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _ansi:
 | 
						|
      {            
 | 
						|
        TString& s = evalstack.peek_string();
 | 
						|
        const TDate d(s);
 | 
						|
        s = d.string(ANSI);
 | 
						|
      }
 | 
						|
      break;     
 | 
						|
    case _num:      
 | 
						|
      type_pointer++;
 | 
						|
      types.set(type_pointer, FALSE);
 | 
						|
      type = _strexpr;
 | 
						|
      break;
 | 
						|
    case _endnum:
 | 
						|
      type_pointer--;
 | 
						|
      type = types[type_pointer] ? _numexpr : _strexpr;
 | 
						|
      if (type == _numexpr)
 | 
						|
        evalstack.peek_real();
 | 
						|
      break;
 | 
						|
    case _str:
 | 
						|
      type_pointer++;
 | 
						|
      types.set(type_pointer, TRUE);
 | 
						|
      type = _numexpr;
 | 
						|
      break;
 | 
						|
    case _endstr:
 | 
						|
      type_pointer--;
 | 
						|
      type = types[type_pointer] ? _numexpr : _strexpr;
 | 
						|
      if (type == _strexpr)
 | 
						|
        evalstack.peek_string();
 | 
						|
      break;
 | 
						|
    case _after:
 | 
						|
      {
 | 
						|
        const TString& s1 = evalstack.pop_string();
 | 
						|
        TString& s2 = evalstack.peek_string();
 | 
						|
        const int pos = s2.find(s1);
 | 
						|
        if (pos >= 0)
 | 
						|
          s2 = s2.mid(pos+s1.len());
 | 
						|
        else
 | 
						|
          s2.cut(0);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _before:
 | 
						|
      {
 | 
						|
        const TString& s1 = evalstack.pop_string();
 | 
						|
        TString& s2 = evalstack.peek_string();
 | 
						|
        const int pos = s2.find(s1);
 | 
						|
        if (pos >= 0)
 | 
						|
          s2.cut(pos);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _between:
 | 
						|
      {
 | 
						|
        const TString& end = evalstack.pop_string();
 | 
						|
        const TString& start = evalstack.pop_string();
 | 
						|
        TString& str = evalstack.peek_string();
 | 
						|
        int from = str.find(start);
 | 
						|
        if (from >= 0)
 | 
						|
        {
 | 
						|
          from += start.len();
 | 
						|
          const int to = str.find(end, from);
 | 
						|
          str = str.sub(from , to);
 | 
						|
        }
 | 
						|
        else
 | 
						|
          str.cut(0);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case _rfind:
 | 
						|
      {
 | 
						|
        const TString& s1 = evalstack.pop_string();
 | 
						|
        const TString& s2 = evalstack.pop_string();
 | 
						|
        const int pos = s2.rfind(s1[0]) + 1;
 | 
						|
        evalstack.push(pos);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      NFCHECK("operazione non valida %d", (int) instr.getsym());
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Lo stack non e' vuoto
 | 
						|
  if (_code.items() > 1)
 | 
						|
    _val = (const TValue&)evalstack.pop();
 | 
						|
  else
 | 
						|
    _val = ZERO;    
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
HIDDEN const char* _s;
 | 
						|
HIDDEN char  _tok[81];
 | 
						|
 | 
						|
TCodesym TExpression::tok2fun(const char* tok) const
 | 
						|
{                                                   
 | 
						|
  const int MAX_TOK = 32;
 | 
						|
  HIDDEN const char* fnstr[MAX_TOK] = { "AFTER",   "ANSI",  "BEFORE", "BETWEEN", "CEIL",   
 | 
						|
                                        "COS",     "EXP",   "EXP10",  "IF", 
 | 
						|
                                        "LEFT",  "LEN",    "LOG",     "LOG10",  
 | 
						|
                                        "MAX",     "MID",   "MIN",    "NUM",     "PERC", "POW",  
 | 
						|
                                        "RFIND",   "RIGHT", "ROUND",  "SCORP",   "SIN",  "SQR",        
 | 
						|
                                        "SQRT",    "STR",   "SUBSTR", "TAN",     "TRIM", 
 | 
						|
                                        "TRUNC",   "UPPER" };
 | 
						|
  
 | 
						|
  HIDDEN TCodesym fntok[MAX_TOK] =    { _after,   _ansi,  _before, _between, _ceil,  
 | 
						|
                                        _cos,     _exp,   _exp10,  _if,    
 | 
						|
                                        _left,  _len,    _log,     _log10, 
 | 
						|
                                        _max,     _mid,   _min,    _num,     _perc,  _pow,   
 | 
						|
                                        _rfind,   _right, _round,  _scorp,   _sin,   _sqr,   
 | 
						|
                                        _sqrt,    _str,   _substr, _tan,     _trim, 
 | 
						|
                                        _trunc,   _upper };
 | 
						|
                                  
 | 
						|
  int f = 0, l = MAX_TOK-1, i = MAX_TOK/2;
 | 
						|
  while (TRUE)
 | 
						|
  {
 | 
						|
//    i = (f+l)>>1;                  
 | 
						|
    i = f + (toupper(*tok) - *fnstr[f]) * (l - f + 1) / (*fnstr[l] - *fnstr[f] + 1);
 | 
						|
      
 | 
						|
    if (i < f || i > l)
 | 
						|
      return _invalid;
 | 
						|
      
 | 
						|
    const int cmp = stricmp(tok, fnstr[i]);
 | 
						|
 | 
						|
    if (cmp == 0) 
 | 
						|
      break;
 | 
						|
    if (cmp > 0) f = i+1;
 | 
						|
    else         l = i-1;
 | 
						|
    
 | 
						|
    if (f > l) 
 | 
						|
      return _invalid;
 | 
						|
  }      
 | 
						|
  CHECKD(i >= 0 && i < MAX_TOK, "Invalid function index ", i);
 | 
						|
  return fntok[i];
 | 
						|
}
 | 
						|
 | 
						|
                                  
 | 
						|
 | 
						|
TCodesym TExpression::__gettoken(bool /* reduct */)
 | 
						|
{
 | 
						|
  TCodesym sym = _invalid;
 | 
						|
  int i = 0;
 | 
						|
  
 | 
						|
  _tok[0] = '\0';
 | 
						|
  while (isspace(*_s)) _s++;
 | 
						|
  if (!*_s) return _endsym;
 | 
						|
 | 
						|
  bool square_bracket = FALSE;  
 | 
						|
  
 | 
						|
  if (isdigit(*_s) || (*_s == '.'))
 | 
						|
  {
 | 
						|
    sym = _number;
 | 
						|
    while (isalnum(*_s) || (*_s == '_') || (*_s == '.') ||
 | 
						|
           (*_s == ':')  || (*_s == '@')  || 
 | 
						|
           (sym == _variable && *_s == '[') || 
 | 
						|
           (sym == _number && *_s == '-' ) || 
 | 
						|
           (square_bracket && (*_s == ',' || *_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 == ']') || (*_s == ',')  */ 
 | 
						|
             ) 
 | 
						|
            sym = _variable;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
          if (sym == _variable && *_s == '[')
 | 
						|
            square_bracket = TRUE;
 | 
						|
        }
 | 
						|
        _tok[i++] = *(_s++);
 | 
						|
      } 
 | 
						|
    } 
 | 
						|
    _tok[i] = '\0';
 | 
						|
    return sym;
 | 
						|
  }
 | 
						|
  if (isalpha(*_s) || (*_s == '#') || (*_s == '_'))
 | 
						|
  {                               
 | 
						|
    if (*_s == '#')
 | 
						|
      sym = _variable;
 | 
						|
    
 | 
						|
    _tok[i++] = *(_s++); 
 | 
						|
    
 | 
						|
    while (isalnum(*_s) || (*_s == '-') || (*_s == '[') ||
 | 
						|
           (*_s == ':') || (*_s == '_') ||
 | 
						|
           (square_bracket && (*_s == ',' || *_s == ']'))
 | 
						|
          ) 
 | 
						|
    {
 | 
						|
      if (*_s == '-')
 | 
						|
      {
 | 
						|
        if (_s[1] != '>') 
 | 
						|
          break;                // Non e' una -> (freccia)
 | 
						|
        _tok[i++] = *(_s++);
 | 
						|
        sym = _variable;
 | 
						|
      }      
 | 
						|
      else
 | 
						|
      {
 | 
						|
        if (*_s == '[')
 | 
						|
        {
 | 
						|
          sym = _variable;
 | 
						|
          square_bracket = TRUE;
 | 
						|
        }  
 | 
						|
      }
 | 
						|
      _tok[i++] = *(_s++);
 | 
						|
    } 
 | 
						|
    _tok[i] = '\0';
 | 
						|
    
 | 
						|
    if (sym != _variable)     // So gia' tutto, inutile controllare oltre
 | 
						|
    {
 | 
						|
      sym = tok2fun(_tok);    
 | 
						|
      if (sym != _invalid)
 | 
						|
        return sym;
 | 
						|
  
 | 
						|
      for (const char * p = _s; isspace(*p); p++);
 | 
						|
      if (*p == '(')
 | 
						|
        return _userfunc; 
 | 
						|
    }
 | 
						|
    
 | 
						|
    return _variable;
 | 
						|
  }
 | 
						|
  switch (*_s)
 | 
						|
  {
 | 
						|
  case '"' :
 | 
						|
  case '\'' :
 | 
						|
    {
 | 
						|
      const char sep = *_s;
 | 
						|
      _s++;
 | 
						|
      while ((*_s) && (*_s != sep))
 | 
						|
        _tok[i++] = *(_s++);
 | 
						|
      _tok[i] = '\0';
 | 
						|
      if (*_s == sep) _s++;
 | 
						|
      return _string;
 | 
						|
    }
 | 
						|
  case ',' :
 | 
						|
    _tok[i++] = *(_s++);
 | 
						|
    _tok[i] = '\0';
 | 
						|
    return _comma;
 | 
						|
  case ';' :
 | 
						|
    _tok[i++] = *(_s++);
 | 
						|
    _tok[i] = '\0';
 | 
						|
    return _semicolon;
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
//HIDDEN int __parms_found = -1;
 | 
						|
 | 
						|
TCodesym TExpression::__factor(TCodesym startsym)
 | 
						|
{
 | 
						|
  TCodesym sym = _invalid;
 | 
						|
  int nparms_found = 0;
 | 
						|
  
 | 
						|
  switch (startsym)
 | 
						|
  {
 | 
						|
  case _lpar:
 | 
						|
    sym = __gettoken();
 | 
						|
    sym = __expression(sym);
 | 
						|
    if (sym == _rpar) sym = __gettoken(); 
 | 
						|
    else sym = _invalid;
 | 
						|
    break;
 | 
						|
  case _variable:
 | 
						|
    {     
 | 
						|
      int from = 1, to = 0;
 | 
						|
      char* quadra = strchr(_tok, '[');
 | 
						|
      if (quadra)
 | 
						|
      {
 | 
						|
        if (sscanf(quadra, "[%d,%d]", &from, &to) == 0)
 | 
						|
        {
 | 
						|
          sym = _invalid;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        *quadra = '\0';
 | 
						|
      }                        
 | 
						|
      _code.add(_variable, _tok);
 | 
						|
      if (quadra)
 | 
						|
      {
 | 
						|
        _code.add(_number, real(from));
 | 
						|
        _code.add(_number, real(to >= from ? to-from+1 : 0));
 | 
						|
        _code.add(_mid);
 | 
						|
      }  
 | 
						|
      for (int i = numvar()-1 ; i >= 0; i--)
 | 
						|
        if (strcmp(_tok, varname(i)) == 0) break;
 | 
						|
      if (i < 0) _var.add(_tok);
 | 
						|
      sym = __gettoken(TRUE);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case _number:
 | 
						|
  case _string:
 | 
						|
    _code.add(startsym, _tok);
 | 
						|
    sym = __gettoken(TRUE);
 | 
						|
    break;  
 | 
						|
  case _userfunc:
 | 
						|
    {       
 | 
						|
      TValue val (_tok);
 | 
						|
      int nparms_found = 0;
 | 
						|
      sym = __function(-1, true, nparms_found);
 | 
						|
      if (sym != _invalid)
 | 
						|
      {
 | 
						|
        const int index = parse_user_func((const char *) val.string(), nparms_found);
 | 
						|
 | 
						|
        if (index < 0) 
 | 
						|
        {
 | 
						|
          strcpy(_tok, (const char *) val.string());
 | 
						|
          sym = _invalid;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {                     
 | 
						|
          _code.add(_number, real(nparms_found));
 | 
						|
          val = real(index);
 | 
						|
          _code.add(startsym, val);
 | 
						|
          _user_func_defined = TRUE;                      
 | 
						|
        }  
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;  
 | 
						|
  case _sqrt:
 | 
						|
  case _sqr:
 | 
						|
  case _exp10:
 | 
						|
  case _exp:
 | 
						|
  case _log10:
 | 
						|
  case _log:
 | 
						|
  case _sin:
 | 
						|
  case _cos:
 | 
						|
  case _tan:
 | 
						|
  case _ansi:
 | 
						|
  case _upper:
 | 
						|
  case _trim:
 | 
						|
  case _len:
 | 
						|
    sym = __function(1, true, nparms_found);
 | 
						|
    _code.add(startsym);
 | 
						|
    break;
 | 
						|
  case _left:
 | 
						|
  case _right:
 | 
						|
  case _pow:
 | 
						|
  case _min:
 | 
						|
  case _max:
 | 
						|
  case _round: 
 | 
						|
  case _ceil:
 | 
						|
  case _trunc:
 | 
						|
  case _perc:
 | 
						|
  case _scorp:
 | 
						|
  case _after:
 | 
						|
  case _before:
 | 
						|
  case _rfind:
 | 
						|
    sym = __function(2, true, nparms_found);
 | 
						|
    _code.add(startsym);
 | 
						|
    break;
 | 
						|
  case _mid:
 | 
						|
  case _substr:
 | 
						|
  case _between:
 | 
						|
    sym = __function(3, true, nparms_found);
 | 
						|
    _code.add(startsym);
 | 
						|
    break;    
 | 
						|
  case _if:
 | 
						|
    sym = __function(3, true, nparms_found);
 | 
						|
    _code.add(startsym);
 | 
						|
    break;    
 | 
						|
  case _num:
 | 
						|
  case _str:
 | 
						|
    _code.add(startsym);
 | 
						|
    sym = __function(1, true, nparms_found);
 | 
						|
    _code.add(startsym == _num ? _endnum : _endstr);
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return sym;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
TCodesym TExpression::__term(TCodesym startsym)
 | 
						|
{
 | 
						|
  TCodesym sym = __factor(startsym);
 | 
						|
  while (sym == _multiply || sym == _divide)
 | 
						|
  {
 | 
						|
    const TCodesym savedsym = sym;
 | 
						|
    sym = __gettoken();
 | 
						|
    sym = __factor(sym);
 | 
						|
    _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);
 | 
						|
}
 | 
						|
 | 
						|
TCodesym TExpression::__function(int nparms, bool fixed_num, int& nparms_found)
 | 
						|
{
 | 
						|
  TCodesym sym = __gettoken(TRUE);
 | 
						|
  if (sym != _lpar)
 | 
						|
    return _invalid;
 | 
						|
  nparms_found = 0;        
 | 
						|
  sym = __gettoken(TRUE);
 | 
						|
  if (sym == _rpar)
 | 
						|
    return nparms <= 0 || !fixed_num ? __gettoken(TRUE) : _invalid;
 | 
						|
  nparms_found++;
 | 
						|
  sym = __expression(sym);
 | 
						|
  while (sym == _comma || sym == _semicolon)
 | 
						|
  {
 | 
						|
    sym = __gettoken(TRUE);
 | 
						|
    nparms_found++;
 | 
						|
    sym = __expression(sym);
 | 
						|
  }
 | 
						|
  if (sym == _rpar)
 | 
						|
    return nparms < 0 || nparms_found == nparms || (nparms_found < nparms && !fixed_num) ?
 | 
						|
           __gettoken(TRUE) :
 | 
						|
           _invalid;
 | 
						|
  return _invalid;
 | 
						|
}
 | 
						|
 | 
						|
bool TExpression::set(const char* expression, TTypeexp type) 
 | 
						|
{ 
 | 
						|
  _original = expression; 
 | 
						|
  _type = type; 
 | 
						|
  _dirty = TRUE; 
 | 
						|
  return compile(_original, type); 
 | 
						|
}
 | 
						|
 | 
						|
bool TExpression::compile(const TString& expression, TTypeexp type)
 | 
						|
{                      
 | 
						|
  _user_func_defined = FALSE;                      
 | 
						|
  _s = expression;
 | 
						|
  _type = type;  
 | 
						|
  _val = ZERO;
 | 
						|
  _code.clear();
 | 
						|
  if (expression.blank()) 
 | 
						|
    return TRUE;
 | 
						|
 
 | 
						|
  TCodesym currsym = __gettoken();                      
 | 
						|
  bool ok = currsym != _invalid;
 | 
						|
  if (ok) 
 | 
						|
    ok = __expression(currsym) == _endsym;
 | 
						|
  if (!ok)
 | 
						|
  {
 | 
						|
    _error = 2;
 | 
						|
    if (!_ignore_error)
 | 
						|
    {
 | 
						|
      TString msg; 
 | 
						|
      msg << "Espressione errata : " << _original;
 | 
						|
      print_error(msg);
 | 
						|
    }
 | 
						|
  }  
 | 
						|
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
const char* TExpression::last_token() const
 | 
						|
{
 | 
						|
  return _tok;
 | 
						|
}
 |