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; }
/*! \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; }
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; }