Пример #1
0
int AlgebraicParser::atof_map(const string &str, double *val) {
  *val=atof(str.c_str());
  if (*val==0 && str!="0") {
    if(str.length()==0)
      return -1; // empty string
    if(str[str.length()-1]==')') { // function
      int i;
      for (i=0; i<(int)str.length(); i++) {
        if (str[i]=='(') break;
      }
      if (i==(int)str.length()) return -1;
      string func=SUBSTR(str, 0, i);
      if (zerofunctions.find(func)!=zerofunctions.end()) {
        if (i!=(int)str.length()-2) return -1;
        *val=zerofunctions[func]();
      }
      else if (functions.find(func)!=functions.end()) {
        double val2;
        if (operator()(SUBSTR(str, i+1, (int)str.length()-(i+1)-1), &val2)<1) return -1;
        *val=functions[func](val2);
      }
      else if (bifunctions.find(func)!=bifunctions.end()) {
        int j;
        int br=0;
        for (j=i+1; j<(int)str.length(); j++) {
          if (str[j]=='(')
            br++;
          else if (str[j]==')') {
            if (br==0)
              return -1;
            br--;
          }
          else if (str[j]==',' && br==0) break;
        }
        if (j>=(int)str.length()-2 || j==i+1) return -1;
        double val2, val3;
        if (operator()(SUBSTR(str, i+1, j-(i+1)), &val2)<1) return -1;
        if (operator()(SUBSTR(str, j+1, (int)str.length()-(j+1)-1), &val3)<1) return -1;
        *val=bifunctions[func](val2, val3);
      }
      else if (trifunctions.find(func)!=trifunctions.end()) {
        int j, j1=-2;
        int br=0;
        for (j=i+1; j<(int)str.length(); j++) {
          if (str[j]=='(')
            br++;
          else if (str[j]==')') {
            if (br==0)
              return -1;
            br--;
          }
          else if (str[j]==',' && br==0) {
            if (j1<0)
              j1=j;
            else
              break;
          }
        }
        if (j>=(int)str.length()-2 || j1==i+1 || j-j1<2) return -1;
        double val1,val2, val3;
        if (operator()(SUBSTR(str, i+1, j1-(i+1)), &val1)<1) return -1;
        if (operator()(SUBSTR(str, j1+1, j-(j1+1)), &val2)<1) return -1;
        if (operator()(SUBSTR(str, j+1, (int)str.length()-(j+1)-1), &val3)<1) return -1;
        *val=trifunctions[func](val1,val2, val3);
      }
      else
        return -1;
    }
    else { // constant
      if (constants.find(str)==constants.end()) return -1;
      *val=constants[str];
    }
  }
  return 1;
}
Пример #2
0
/*!
  \param Func
*/
xbShort xbExpn::ProcessFunction( char * Func )
{
/* 1 - pop function from stack
   2 - verify function name and get no of parms needed 
   3 - verify no of parms >= remainder of stack
   4 - pop parms off stack
   5 - execute function
   6 - push result back on stack
*/


  char   *buf = 0;
  xbExpNode *p1, *p2, *p3, *WorkNode, *FuncNode;
  xbShort  ParmsNeeded,len;
  char   ptype = 0;  /* process type s=string, l=logical, d=double */
  xbDouble DoubResult = 0;
  xbLong   IntResult = 0;
  FuncNode = (xbExpNode *) Pop();

  ParmsNeeded = GetFuncInfo( Func, 1 );

  if( ParmsNeeded == -1 ) {
    return XB_INVALID_FUNCTION;
  }
  else {
    ParmsNeeded = 0;
    if( FuncNode->Sibling1 ) ParmsNeeded++;
    if( FuncNode->Sibling2 ) ParmsNeeded++;
    if( FuncNode->Sibling3 ) ParmsNeeded++;
  }

  if( ParmsNeeded > GetStackDepth())
    return XB_INSUFFICIENT_PARMS;

  p1 = p2 = p3 = NULL;
  if( ParmsNeeded > 2 ) p3 = (xbExpNode *) Pop(); 
  if( ParmsNeeded > 1 ) p2 = (xbExpNode *) Pop(); 
  if( ParmsNeeded > 0 ) p1 = (xbExpNode *) Pop(); 
  memset( WorkBuf, 0x00, WorkBufMaxLen+1);

  if( strncmp( Func, "ABS", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = ABS( GetDoub( p1 ));
  }
  else if( strncmp( Func, "ASC", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = ASC( p1->StringResult );
  }
  else if( strncmp( Func, "AT", 2 ) == 0 ) {  
    ptype = 'd';
    DoubResult = AT( p1->StringResult, p2->StringResult );
  }
  else if( strncmp( Func, "CDOW", 4 ) == 0 ) {  
    ptype = 's';
    buf = CDOW( p1->StringResult );
  }
  else if( strncmp( Func, "CHR", 3 ) == 0 ) {  
    ptype = 's';
    buf = CHR( GetInt( p1 ));
  }
  else if( strncmp( Func, "CMONTH", 6 ) == 0 ) {  
    ptype = 's';
    buf = CMONTH( p1->StringResult );
  }
  else if( strncmp( Func, "CTOD", 4 ) == 0 ) {  
    ptype = 's';
    buf = CTOD( p1->StringResult );
  }
  else if( strncmp( Func, "DATE", 4 ) == 0 ) {  
    ptype = 's';
    buf = DATE();
  }
  else if( strncmp( Func, "DAY", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = DAY( p1->StringResult );
  }
  else if( strncmp( Func, "DESCEND", 7 ) == 0 && p1->ExpressionType == 'C' ) {  
    ptype = 's';
    buf = DESCEND( p1->StringResult.c_str() );
  }
  else if( strncmp( Func, "DESCEND", 7 ) == 0 && p1->ExpressionType == 'N' ) {  
    ptype = 'd';
    DoubResult = DESCEND( GetDoub( p1 ));
  }
  else if( strncmp( Func, "DESCEND", 7 ) == 0 && p1->ExpressionType == 'D' ) {  
    xbDate d( p1->StringResult );
    ptype = 'd';
    DoubResult = DESCEND( d );
  }
  else if( strncmp( Func, "DOW", 3 ) == 0 ) {
    ptype = 'd';
    DoubResult = DOW( p1->StringResult );
  }
  else if( strncmp( Func, "DTOC", 4 ) == 0 ) {  
    ptype = 's';
    buf = DTOC( p1->StringResult );
  }
  else if( strncmp( Func, "DTOS", 4 ) == 0 ) {  
    ptype = 's';
    buf = DTOS( p1->StringResult );
  }
  else if( strncmp( Func, "EXP", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = EXP( GetDoub( p1 ));
  }
  else if( strncmp( Func, "IIF", 3 ) == 0 ){
    ptype = 's';
    buf = IIF( p1->IntResult, p2->StringResult, p3->StringResult );
  }
  else if( strncmp( Func, "INT", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = INT( GetDoub( p1 ));
  }
  else if( strncmp( Func, "ISALPHA", 7 ) == 0 ) {  
    ptype = 'l';
    IntResult = ISALPHA( p1->StringResult );
  }
  else if( strncmp( Func, "ISLOWER", 7 ) == 0 ) {  
    ptype = 'l';
    IntResult = ISLOWER( p1->StringResult );
  }
  else if( strncmp( Func, "ISUPPER", 7 ) == 0 ) {  
    ptype = 'l';
    IntResult = ISUPPER( p1->StringResult );
  }
  else if( strncmp( Func, "LEN", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = LEN( p1->StringResult );
  }
  else if( strncmp( Func, "LEFT", 4 ) == 0 ) {  
    ptype = 's';
    buf = LEFT( p1->StringResult, INT( p2->DoubResult ));
  }
  else if( strncmp( Func, "LTRIM", 5 ) == 0 ) {  
    ptype = 's';
    buf = LTRIM( p1->StringResult );
  }  
  else if( strncmp( Func, "LOG", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = LOG( GetDoub( p1 ));
  }  
  else if( strncmp( Func, "LOWER", 5 ) == 0 ) {  
    ptype = 's';
    buf = LOWER( p1->StringResult );
  }  
  else if( strncmp( Func, "MAX", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = MAX( GetDoub( p1 ), GetDoub( p2 ));
  }  
  else if( strncmp( Func, "MIN", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = MIN( GetDoub( p1 ), GetDoub( p2 ));
  }  
  else if( strncmp( Func, "MONTH", 5 ) == 0 ) {  
    ptype = 'd';
    DoubResult = MONTH( p1->StringResult );
  } 

  else if( strncmp( Func, "RECNO", 5 ) == 0 )
  {
    ptype = 'd';
    DoubResult = RECNO( FuncNode->dbf );
  }

  else if( strncmp( Func, "REPLICATE", 9 ) == 0 ) {
    ptype = 's';
    buf = REPLICATE( p1->StringResult, GetInt( p2 ));
  }
  else if( strncmp( Func, "RIGHT", 5 ) == 0 ) {
    ptype = 's';
    buf = RIGHT( p1->StringResult, GetInt( p2 ));
  }
  else if( strncmp( Func, "RTRIM", 5 ) == 0 ) {  
    ptype = 's';
    buf = RTRIM( p1->StringResult );
  }  
  else if( strncmp( Func, "SPACE", 5 ) == 0 ) {  
    ptype = 's';
    buf = SPACE( INT( GetDoub( p1 )));
  }
  else if( strncmp( Func, "SQRT", 4 ) == 0 ) {  
    ptype = 'd';
    DoubResult = SQRT( GetDoub( p1 ));
  }
  else if( strncmp( Func, "STRZERO", 7 ) == 0 && ParmsNeeded == 1 ) {
    ptype = 's';
    buf = STRZERO( p1->StringResult );
  }   
  else if( strncmp( Func, "STRZERO", 7 ) == 0 && ParmsNeeded == 2 ) {
    ptype = 's';
    buf = STRZERO( p1->StringResult, GetInt( p2 ));
  }   
  else if( strncmp( Func, "STRZERO", 7 ) == 0 && ParmsNeeded == 3 ) {
    ptype = 's';
    buf = STRZERO( p1->StringResult, GetInt( p2 ), GetInt( p3 ));
  }   

  else if( strncmp( Func, "STR", 3 ) == 0 && p3 ) {
    ptype = 's';
    if(p1->ExpressionType == 'N')
      buf = STR( p1->DoubResult, GetInt( p2 ), GetInt( p3 ));
    else
      buf = STR( p1->StringResult, GetInt( p2 ), GetInt( p3 ));
  }   

  else if( strncmp( Func, "STR", 3 ) == 0 && p2 ) {
    ptype = 's';
    buf = STR( p1->StringResult, GetInt( p2 ));
  }

  else if( strncmp( Func, "STR", 3 ) == 0 && p1 ) {
    ptype = 's';
    buf = STR( p1->StringResult );
  }
   
  else if( strncmp( Func, "SUBSTR", 6 ) == 0 ) {
    ptype = 's';
    buf = SUBSTR( p1->StringResult, GetInt( p2 ), GetInt( p3 )); 
  }
  else if( strncmp( Func, "TRIM", 4 ) == 0 ) {  
    ptype = 's';
    buf = TRIM( p1->StringResult );
  }  
  else if( strncmp( Func, "UPPER", 5 ) == 0 ) {  
    ptype = 's';
    buf = UPPER( p1->StringResult );
  }  
  else if( strncmp( Func, "VAL", 3 ) == 0 ) {  
    ptype = 'd';
    DoubResult = VAL( p1->StringResult );
  }  
  else if( strncmp( Func, "YEAR", 4 ) == 0 ) {  
    ptype = 'd';
    DoubResult = YEAR( p1->StringResult );
  }  
  if( p1 && !p1->InTree ) delete p1;
  if( p2 && !p2->InTree ) delete p2;
  if( p3 && !p3->InTree ) delete p3;
  if( !FuncNode->InTree ) delete FuncNode;
  if( buf ){
    len = strlen( buf );
    WorkNode = new xbExpNode;
    if( !WorkNode )
      return XB_NO_MEMORY;
    WorkNode->ResultLen = len + 1;
    
  } else {    
    len = 0;
    WorkNode = new xbExpNode;
    if( !WorkNode )
      return XB_NO_MEMORY;
    WorkNode->ResultLen = 0;
  }

  switch( ptype ){
   case 's':                               /* string or char result */
    WorkNode->DataLen = len;
    WorkNode->ExpressionType = 'C';
    WorkNode->Type = 's';
    WorkNode->StringResult = buf;
    break;
   case 'd':                               /* numeric result */
    WorkNode->DataLen = 0;
    WorkNode->ExpressionType = 'N';
    WorkNode->Type = 'd';
    WorkNode->DoubResult = DoubResult;
    break;
   case 'l':                               /* logical result */
    WorkNode->DataLen = 0;
    WorkNode->ExpressionType = 'L';
    WorkNode->Type = 'l';
    WorkNode->IntResult = IntResult;
    break;
   default:
    std::cout << "\nInternal error. " << ptype;
    break;
  }
  Push(WorkNode);
  return XB_NO_ERROR;
}
Пример #3
0
int AlgebraicParser::operator()(const string &str, double *val){

 // coding of arythmetical operations
  const int extOP_PLUS=1;
  const int extOP_MINUS=-1;
  const int extOP_MUL=2;
  const int extOP_DIV=-2;

  /* вначале разбиваем строку на подстроки, связанные + и -, 
  поскольку эти операции обладают меньшим приоритетом.
  потом разбиваем подстроки, связанные * и /.
  Данная функция разбивает строку на две подстроки.
  Дальнейшее разбитие осуществляется с помощью рекурсивного вызова этой же функции.
  */

  if (str.length()==0)
    return -2;

  int direct=0; // 1 - правое слагаемое есть число, 0 - правое слагаемое есть выражение

  //ищем с конца первый символ + или - вне скобок ()
  int op=extOP_MINUS; // кодирует арифметическое действие (возможные значения перечислены в разделе define)
  int c1=find_symbol(str,'-');
  int c2=find_symbol(str,'+');
  if (c1<-1 || c2<-1) return -2; // скобки в строке расставлены некорректно

  if(c1<0 && c2<0){ // none of +/- found
    //ищем с конца первый символ * или / вне скобок ()
    op=extOP_MUL;
    c1=find_symbol(str,'*');
    c2=find_symbol(str,'/');
    if (c1<-1 || c2<-1) return -2; // скобки в строке расставлены некорректно
    direct=1; // предполагаем, что правое слагаемое есть число
  }

  if(c2>c1){ // первой с конца встречается операция, противоположная изначально заданной (+ или / )
    op=-op;
    c1=c2;
  }
  double val1=0, val2=0; // в эти переменные будут записаны значения для первого и второго слагаемого

  if (c1<0 && c2<0) { // ни одного символа + - * / в строке не встречено
    if(str[0]=='(' && str[str.length()-1]==')') { // строка есть выражение в скобках (...)
      string token1=SUBSTR(str, 1, (int)str.length()-2); // смотрим, что внутри скобок
      return operator()(token1, val); // считаем это и возвращаем
    }
    // строка есть просто число. в этом случае val1 будет единицей, val2 будет этим числом,
    // а действие будет умножением (в результате мы получим 1*val2=val2)
    val1=1;
  }
  else {
    string token1=SUBSTR(str, 0, c1);
    trim(token1);
    if(token1.length()==0){ // длина подстроки перед символом равна нулю
      if(op==extOP_MINUS)val1=0.; // унарный минус (например, -5)
      else return -1; // ошибка
    }
    else{
      if(operator()(token1,&val1)<0) // считаем val1
        return -1;
    }
  }

//  string token2=str.substr(c1+1, str.length()-(c1+1));
  string token2=my_substr(str, c1+1, (int)str.length()-(c1+1));
  if (token2.length()==0)
    return -1; // ошибка
  trim(token2);
  if(token2[0]=='(' && token2[token2.length()-1]==')'){ // правое слагаемое есть выражение в скобках, а не число
    direct=0;
  }
  if(direct){ // правое выражение есть непосредственно число
    if(atof_map(token2, &val2)<1)return -1;
  }
  else{
    if(operator()(token2,&val2)<0)
      return -1;
  }
  // мы посчитали два слагаемых val1 и val2 и производим арифметическую операцию  
  switch(op){
    case extOP_PLUS:
      *val=val1+val2;
    break;
    case extOP_MINUS:
      *val=val1-val2;
    break;
    case extOP_DIV:
      *val=val1/val2;
    break;
    case extOP_MUL:
      *val=val1*val2;
    break;
  }
  return 1;
}