# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

eval_num_expr.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NeL Network Services.
00010  * NEVRAX NeL Network Services is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NeL Network Services is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NeL Network Services; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdmisc.h"
00027 
00028 #include "nel/misc/eval_num_expr.h"
00029 
00030 namespace NLMISC
00031 {
00032 
00033 using namespace std;
00034 
00035 // ***************************************************************************
00036 
00037 CEvalNumExpr::TReturnState CEvalNumExpr::readDecimal (double &value)
00038 {
00039         // Read first integer value
00040         readIntegerNumberDecimal (value);
00041 
00042         // Dot ?
00043         char currentChar = *_ExprPtr;
00044         if (currentChar == '.')
00045         {
00046                 // Next char
00047                 _ExprPtr++;
00048                 currentChar = *_ExprPtr;
00049                 if (currentChar < '0' || currentChar > '9')
00050                         return NumberSyntaxError;
00051 
00052                 // Read the decimal part
00053                 const char *start = _ExprPtr;
00054                 double fract;
00055                 readIntegerNumberDecimal (fract);
00056                 fract /= (double)pow (10 ,(_ExprPtr-start));
00057                 value += fract;
00058         }
00059 
00060         return NoError;
00061 }
00062 
00063 // ***************************************************************************
00064 
00065 void CEvalNumExpr::readIntegerNumberDecimal (double &value)
00066 {
00067         // Registered values
00068         register double regValue = 0;
00069 
00070         // Read the first value
00071         char currentChar = *_ExprPtr;
00072         if ((currentChar >= '0') && (currentChar <= '9'))
00073         {
00074                 regValue += (currentChar - '0');
00075                 _ExprPtr++;
00076                 currentChar = *_ExprPtr;
00077 
00078                 // For each values
00079                 while ((currentChar >= '0') && (currentChar <= '9'))
00080                 {
00081                         regValue *= 10;
00082                         regValue += (currentChar - '0');
00083 
00084                         // Next char
00085                         _ExprPtr++;
00086                         currentChar = *_ExprPtr;
00087                 }
00088         }
00089         
00090         // Store value
00091         value = regValue;
00092 }
00093 
00094 // ***************************************************************************
00095 
00096 CEvalNumExpr::TReturnState CEvalNumExpr::getNextToken (TToken &token)
00097 {
00098         // Get the current char
00099         uint8 currentChar = *_ExprPtr;
00100 
00101         // Skip space
00102         while ((currentChar!=0) && (currentChar<=0x20))
00103         {
00104                 _ExprPtr++;
00105                 currentChar = *_ExprPtr;
00106         }
00107 
00108         // Can be an operator ?
00109         if (currentChar <= 128)
00110         {
00111                 // Get the operator
00112                 _Op = _OperatorArray[currentChar];
00113 
00114                 // Is an operator ?
00115                 if (_Op != NotOperator)
00116                 {
00117                         // It is an operator
00118                         token = Operator;
00119 
00120                         // Is a 2 characters operator ?
00121                         if (_Op != ExtOperator)
00122                         {
00123                                 // Return next character
00124                                 _ExprPtr++;
00125                                 return NoError;
00126                         }
00127                         else
00128                         {
00129                                 // Have a second character ?
00130                                 char secondChar = *(_ExprPtr+1);
00131 
00132                                 // What kind of 1st character
00133                                 switch (currentChar)
00134                                 {
00135                                 case '!':
00136                                         if (secondChar == '=')
00137                                         {
00138                                                 _Op = NotEqual;
00139                                                 _ExprPtr+=2;
00140                                                 return NoError;
00141                                         }
00142                                         else
00143                                         {
00144                                                 _Op = Not;
00145                                                 _ExprPtr++;
00146                                                 return NoError;
00147                                         }
00148                                 case '&':
00149                                         if (secondChar == '&')
00150                                         {
00151                                                 _Op = LogicalAnd;
00152                                                 _ExprPtr+=2;
00153                                                 return NoError;
00154                                         }
00155                                         else
00156                                         {
00157                                                 _Op = And;
00158                                                 _ExprPtr+=1;
00159                                                 return NoError;
00160                                         }
00161                                 case '-':
00162                                         if (secondChar == '>')
00163                                         {
00164                                                 _Op = SRightShift;
00165                                                 _ExprPtr+=2;
00166                                                 return NoError;
00167                                         }
00168                                         else
00169                                         {
00170                                                 _Op = Minus;
00171                                                 _ExprPtr++;
00172                                                 return NoError;
00173                                         }
00174                                 case '<':
00175                                         if (secondChar == '<')
00176                                         {
00177                                                 _Op = ULeftShift;
00178                                                 _ExprPtr+=2;
00179                                                 return NoError;
00180                                         }
00181                                         else if (secondChar == '=')
00182                                         {
00183                                                 _Op = InferiorEqual;
00184                                                 _ExprPtr+=2;
00185                                                 return NoError;
00186                                         }
00187                                         else if (secondChar == '-')
00188                                         {
00189                                                 _Op = SLeftShift;
00190                                                 _ExprPtr+=2;
00191                                                 return NoError;
00192                                         }
00193                                         else
00194                                         {
00195                                                 _Op = Inferior;
00196                                                 _ExprPtr+=1;
00197                                                 return NoError;
00198                                         }
00199                                 case '=':
00200                                         if (secondChar == '=')
00201                                         {
00202                                                 _Op = Equal;
00203                                                 _ExprPtr+=2;
00204                                                 return NoError;
00205                                         }
00206                                 case '>':
00207                                         if (secondChar == '>')
00208                                         {
00209                                                 _Op = URightShift;
00210                                                 _ExprPtr+=2;
00211                                                 return NoError;
00212                                         }
00213                                         else if (secondChar == '=')
00214                                         {
00215                                                 _Op = SuperiorEqual;
00216                                                 _ExprPtr+=2;
00217                                                 return NoError;
00218                                         }
00219                                         else
00220                                         {
00221                                                 _Op = Superior;
00222                                                 _ExprPtr+=1;
00223                                                 return NoError;
00224                                         }
00225                                 case '^':
00226                                         if (secondChar == '^')
00227                                         {
00228                                                 _Op = LogicalXor;
00229                                                 _ExprPtr+=2;
00230                                                 return NoError;
00231                                         }
00232                                         else
00233                                         {
00234                                                 _Op = Xor;
00235                                                 _ExprPtr+=1;
00236                                                 return NoError;
00237                                         }
00238                                 case '|':
00239                                         if (secondChar == '|')
00240                                         {
00241                                                 _Op = LogicalOr;
00242                                                 _ExprPtr+=2;
00243                                                 return NoError;
00244                                         }
00245                                         else
00246                                         {
00247                                                 _Op = Or;
00248                                                 _ExprPtr+=1;
00249                                                 return NoError;
00250                                         }
00251                                 }
00252 
00253                                 // Can't found the operator
00254                                 return UnkownOperator;
00255                         }
00256                 }
00257                 // Is End, '(', ')', '.' ?
00258                 else if (currentChar == 0)
00259                 {
00260                         token = End;
00261                         return NoError;
00262                 }
00263                 else if (currentChar == '(')
00264                 {
00265                         _ExprPtr++;
00266                         token = Open;
00267                         return NoError;
00268                 }
00269                 else if (currentChar == ')')
00270                 {
00271                         _ExprPtr++;
00272                         token = Close;
00273                         return NoError;
00274                 }
00275                 else if (currentChar == ',')
00276                 {
00277                         _ExprPtr++;
00278                         token = Coma;
00279                         return NoError;
00280                 }
00281                 // Is a number ?
00282                 else if ((currentChar >= '0') && (currentChar <= '9') || (currentChar == '.'))
00283                 {
00284                         // This is a number
00285                         token = Number;
00286 
00287                         // Have a second character ?
00288                         char secondChar = *(_ExprPtr+1);
00289 
00290                         // Is an hexadecimal value ?
00291                         if ((currentChar == '0') && (secondChar == 'x'))
00292                         {
00293                                 // Go to the number
00294                                 _ExprPtr +=2;
00295                                 currentChar = *_ExprPtr;
00296 
00297                                 // Registered values
00298                                 register double regValue = 0;
00299                                 if ((currentChar >= '0') && (currentChar <= '9'))
00300                                 {
00301                                         regValue += (currentChar - '0');
00302                                 }
00303                                 else if ((currentChar >= 'a') && (currentChar <= 'f'))
00304                                 {
00305                                         regValue += (currentChar - 'a' + 10);
00306                                 }
00307                                 else if ((currentChar >= 'A') && (currentChar <= 'F'))
00308                                 {
00309                                         regValue += (currentChar - 'A' + 10);
00310                                 }
00311                                 else
00312                                 {
00313                                         // Number syntax error
00314                                         return NumberSyntaxError;
00315                                 }
00316                                 _ExprPtr++;
00317                                 currentChar = *_ExprPtr;
00318 
00319                                 // For each values
00320                                 while (1)
00321                                 {
00322                                         if ((currentChar >= '0') && (currentChar <= '9'))
00323                                         {
00324                                                 regValue *= 16;
00325                                                 regValue += (currentChar - '0');
00326                                         }
00327                                         else if ((currentChar >= 'a') && (currentChar <= 'f'))
00328                                         {
00329                                                 regValue *= 16;
00330                                                 regValue += (currentChar - 'a' + 10);
00331                                         }
00332                                         else if ((currentChar >= 'A') && (currentChar <= 'F'))
00333                                         {
00334                                                 regValue *= 16;
00335                                                 regValue += (currentChar - 'A' + 10);
00336                                         }
00337                                         else
00338                                         {
00339                                                 // Stop
00340                                                 break;
00341                                         }
00342 
00343                                         // Next char
00344                                         _ExprPtr++;
00345                                         currentChar = *_ExprPtr;
00346                                 }
00347                                 
00348                                 // Store value
00349                                 _Value = regValue;
00350 
00351                                 // Number ok
00352                                 return NoError;
00353                         }
00354                         // Is an octal value ?
00355                         else if ((currentChar == '0') && (secondChar >= '0') && (secondChar <= '9'))
00356                         {
00357                                 // Go to the number
00358                                 _ExprPtr ++;
00359                                 currentChar = *_ExprPtr;
00360 
00361                                 // Registered values
00362                                 register double regValue = 0;
00363 
00364                                 // Check octal number
00365                                 if (currentChar > '7')
00366                                         return NumberSyntaxError;
00367 
00368                                 // Read the first value
00369                                 regValue += (currentChar - '0');
00370                                 _ExprPtr++;
00371                                 currentChar = *_ExprPtr;
00372 
00373                                 // For each values
00374                                 while ((currentChar >= '0') && (currentChar <= '9'))
00375                                 {
00376                                         // Check octal number
00377                                         if (currentChar > '7')
00378                                                 return NumberSyntaxError;
00379 
00380                                         regValue *= 8;
00381                                         regValue += (currentChar - '0');
00382 
00383                                         // Next char
00384                                         _ExprPtr++;
00385                                         currentChar = *_ExprPtr;
00386                                 }
00387                                 
00388                                 // Store value
00389                                 _Value = regValue;
00390 
00391                                 // Number ok
00392                                 return NoError;
00393                         }
00394                         // It is a decimal value
00395                         else
00396                         {
00397                                 // Read value
00398                                 TReturnState state = readDecimal (_Value);
00399                                 if (state == NoError)
00400                                 {
00401                                         // Exponent ?
00402                                         currentChar = *_ExprPtr;
00403                                         if ( (currentChar == 'e') || (currentChar == 'E') )
00404                                         {
00405                                                 // Next char
00406                                                 _ExprPtr++;
00407 
00408                                                 // Minus ?
00409                                                 bool negative = false;
00410                                                 if (*_ExprPtr == '-')
00411                                                 {
00412                                                         negative = true;
00413                                                         _ExprPtr++;
00414                                                 }
00415 
00416                                                 // Read value
00417                                                 double exponent;
00418                                                 state = readDecimal (exponent);
00419                                                 if (state == NoError)
00420                                                 {
00421                                                         // Negative value ?
00422                                                         if (negative)
00423                                                                 exponent = -exponent;
00424 
00425                                                         // Raise 10 at the power of
00426                                                         _Value *= pow (10.0, exponent);
00427                                                 }
00428                                                 else
00429                                                 {
00430                                                         return state;
00431                                                 }
00432                                         }
00433 
00434                                         // Number ok
00435                                         return NoError;
00436                                 }
00437                                 else
00438                                 {
00439                                         return state;
00440                                 }
00441                         }
00442                 }
00443                 // Is a string ?
00444                 else if (currentChar == '"')
00445                 {
00446                         // Look for the end of the string
00447                         _ExprPtr++;
00448                         currentChar = *_ExprPtr;
00449                         const char *start = _ExprPtr;
00450                         while ( (currentChar != 0) && (currentChar != '"') )
00451                         {
00452                                 _ExprPtr++;
00453                                 currentChar = *_ExprPtr;
00454                         }
00455                         
00456                         // End reached ?
00457                         if (currentChar == 0)
00458                                 return MustBeDoubleQuote;
00459 
00460                         // This is a user string, copy the string
00461                         uint size = _ExprPtr - start;
00462                         if (size >= (InternalStringLen-1))
00463                         {
00464                                 _InternalStlString.resize (size);
00465                                 uint i;
00466                                 for (i=0; i<size; i++)
00467                                         _InternalStlString[i] = start[i];
00468                                 _InternalStringPtr = _InternalStlString.c_str ();
00469                         }
00470                         else
00471                         {
00472                                 memcpy (_InternalString, start, size);
00473                                 _InternalString[size] = 0;
00474                                 _InternalStringPtr = _InternalString;
00475                         }
00476 
00477                         // Token
00478                         _ExprPtr++;
00479                         token = String;
00480                         return NoError;
00481                 }
00482         }
00483 
00484         // Read a string
00485         const char *start = _ExprPtr;
00486         while ( (currentChar >= 128) || _StringChar[currentChar] )
00487         {
00488                 _ExprPtr++;
00489                 currentChar = *_ExprPtr;
00490         }
00491 
00492         // Is pi ?
00493         if (((_ExprPtr - start) == 2) && (start[0] == 'p') && (start[1] == 'i'))
00494         {
00495                 token = Number;
00496                 _Value = 3.1415926535897932384626433832795;
00497                 return NoError;
00498         }
00499         // Is e ?
00500         else if (((_ExprPtr - start) == 1) && (start[0] == 'e'))
00501         {
00502                 token = Number;
00503                 _Value = 2.7182818284590452353602874713527;
00504                 return NoError;
00505         }
00506 
00507         // This is a user string, copy the string
00508         uint size = _ExprPtr - start;
00509         if (size >= (InternalStringLen-1))
00510         {
00511                 _InternalStlString.resize (size);
00512                 uint i;
00513                 for (i=0; i<size; i++)
00514                         _InternalStlString[i] = start[i];
00515                 _InternalStringPtr = _InternalStlString.c_str ();
00516         }
00517         else
00518         {
00519                 memcpy (_InternalString, start, size);
00520                 _InternalString[size] = 0;
00521                 _InternalStringPtr = _InternalString;
00522         }
00523 
00524         // Search for a reserved word ?
00525         uint begin = 0;
00526         uint end = ReservedWordCount-1;
00527         sint result = strcmp (_InternalStringPtr, _ReservedWord[begin]);
00528         if ( result >= 0 )
00529         {
00530                 // The first is the good ?
00531                 if ( result == 0 )
00532                 {
00533                         end = begin;
00534                 }
00535 
00536                 result = strcmp (_InternalStringPtr, _ReservedWord[end]);
00537                 if (result <= 0)
00538                 {
00539                         // The last is the good ?
00540                         if ( result == 0 )
00541                         {
00542                                 begin = end;
00543                         }
00544 
00545                         // While there is a middle..
00546                         while ((end - begin) > 1)
00547                         {
00548                                 uint middle = begin + (end - begin) / 2;
00549                                 result = strcmp (_InternalStringPtr, _ReservedWord[middle]);
00550                                 if (result == 0)
00551                                 {
00552                                         begin = middle;
00553                                         end = middle;
00554                                         break;
00555                                 }
00556                                 else if (result < 0)
00557                                 {
00558                                         end = middle;
00559                                 }
00560                                 else
00561                                 {
00562                                         begin = middle;
00563                                 }
00564                         }
00565                 }
00566 
00567                 // Found ?
00568                 if (end == begin)
00569                 {
00570                         // Return the token
00571                         _ReservedWordFound = (TReservedWord)begin;
00572                         token = _ReservedWordToken[begin];
00573 
00574                         // Ok
00575                         return NoError;
00576                 }
00577         }
00578 
00579         // Token
00580         token = String;
00581         return NoError;
00582 }
00583 
00584 // ***************************************************************************
00585 
00586 CEvalNumExpr::TReturnState CEvalNumExpr::evalExpression (const char *expression, double &result, 
00587                                                                                                                  int *errorIndex, uint32 userData)
00588 {
00589         // Init the ptr
00590         _ExprPtr = expression;
00591 
00592         TToken nextToken;
00593         TReturnState error = evalExpression (result, nextToken, userData);
00594         if (error == NoError)
00595         {
00596                 // The end ?
00597                 if (nextToken == End)
00598                         return NoError;
00599                 else
00600                 {
00601                         if (errorIndex)
00602                                 *errorIndex = _ExprPtr - expression;
00603                         return MustBeEnd;
00604                 }
00605         }
00606         else
00607         {
00608                 if (errorIndex)
00609                         *errorIndex = _ExprPtr - expression;
00610                 return error;
00611         }
00612 }
00613 
00614 // ***************************************************************************
00615 
00616 CEvalNumExpr::TReturnState CEvalNumExpr::evalExpression (double &finalResult, TToken &nextToken, uint32 userData)
00617 {
00618         // Array of result
00619 
00620         uint exprCount = 0;
00621         double result[InternalOperator];
00622         vector<double> resultSup;
00623 
00624         uint opCount = 0;
00625         TOperator resultOp[InternalOperator];
00626         vector<TOperator> resultOpSup;
00627 
00628         // Read a token
00629         TReturnState error = getNextToken (nextToken);
00630         if (error != NoError)
00631                 return error;
00632         while (1)
00633         {
00634                 // Unary opertor
00635                 uint unaryOpCount = 0;
00636                 TOperator resultUnaryOp[InternalOperator];
00637                 vector<TOperator> resultUnaryOpSup;
00638                 
00639                 // Current value
00640                 double value;
00641 
00642                 // Unary operator ?
00643                 if ( (nextToken == Operator) && ( (_Op == Minus) || (_Op == Not) || (_Op == Tilde) ) )
00644                 {
00645                         // Push the unary operator
00646                         if (unaryOpCount<InternalOperator)
00647                                 resultUnaryOp[unaryOpCount] = _Op;
00648                         else
00649                                 resultUnaryOpSup.push_back (_Op);
00650                         unaryOpCount++;
00651 
00652                         // Read next token
00653                         error = getNextToken (nextToken);
00654                         if (error != NoError)
00655                                 return error;
00656                 }
00657 
00658                 // Parenthesis ?
00659                 if (nextToken == Open)
00660                 {
00661                         // Eval sub expression
00662                         error = evalExpression (value, nextToken, userData);
00663                         if (error == NoError)
00664                         {
00665                                 if (nextToken != Close)
00666                                         return MustBeClose;
00667                         }       
00668                         else
00669                                 return error;
00670 
00671                         // Get next token
00672                         error = getNextToken (nextToken);
00673                         if (error != NoError)
00674                                 return error;
00675                 }
00676                 // This is a function ?
00677                 else if ( (nextToken == Function1) || (nextToken == Function2) )
00678                 {
00679                         TToken backupedToken = nextToken;
00680 
00681                         // Get the function
00682                         TReservedWord reservedWord = _ReservedWordFound;
00683 
00684                         // Read a token
00685                         error = getNextToken (nextToken);
00686                         if (error == NoError)
00687                         {
00688                                 // Open ?
00689                                 if (nextToken != Open)
00690                                 {
00691                                         return MustBeOpen;
00692                                 }
00693 
00694                                 // Eval an expression
00695                                 double arg0;
00696                                 error = evalExpression (arg0, nextToken, userData);
00697                                 if (error == NoError)
00698                                 {
00699                                         // 2 arg ?
00700                                         if (backupedToken == Function2)
00701                                         {
00702                                                 if (nextToken == Coma)
00703                                                 {
00704                                                         // Second argument
00705                                                         double arg1;
00706                                                         error = evalExpression (arg1, nextToken, userData);
00707                                                         if (error == NoError)
00708                                                         {
00709                                                                 // Final with close ?
00710                                                                 if (nextToken == Close)
00711                                                                 {
00712                                                                         switch (reservedWord)
00713                                                                         {
00714                                                                         case Atan2:
00715                                                                                 value = atan2 (arg0, arg1);
00716                                                                                 break;
00717                                                                         case Max:
00718                                                                                 value = (arg0>arg1) ? arg0 : arg1;
00719                                                                                 break;
00720                                                                         case Min:
00721                                                                                 value = (arg0<arg1) ? arg0 : arg1;
00722                                                                                 break;
00723                                                                         case Pow:
00724                                                                                 value = pow (arg0, arg1);
00725                                                                                 break;
00726                                                                         case Rand:
00727                                                                                 value = arg0 + (arg1-arg0) * (double)rand () / (double)(RAND_MAX+1);
00728                                                                                 break;
00729                                                                         default:
00730                                                                                 // Can't be hear after getToken
00731                                                                                 nlstop;
00732                                                                         }                                                                               
00733                                                                 }
00734                                                                 else
00735                                                                         return MustBeClose;
00736                                                         }
00737                                                         else
00738                                                                 return error;
00739                                                 }
00740                                                 else
00741                                                         return MustBeComa;
00742                                         }
00743                                         else
00744                                         {
00745                                                 if (nextToken == Close)
00746                                                 {
00747                                                         // Eval the function
00748                                                         switch (reservedWord)
00749                                                         {
00750                                                         case Abs:
00751                                                                 value = fabs (arg0);
00752                                                                 break;
00753                                                         case Acos:
00754                                                                 value = acos (arg0);
00755                                                                 break;
00756                                                         case Asin:
00757                                                                 value = asin (arg0);
00758                                                                 break;
00759                                                         case Atan:
00760                                                                 value = atan (arg0);
00761                                                                 break;
00762                                                         case Ceil:
00763                                                                 value = ceil (arg0);
00764                                                                 break;
00765                                                         case Cosh:
00766                                                                 value = cosh (arg0);
00767                                                                 break;
00768                                                         case Cos:
00769                                                                 value = cos (arg0);
00770                                                                 break;
00771                                                         case Exponent:
00772                                                                 {
00773                                                                         int exponent;
00774                                                                         frexp( arg0, &exponent);
00775                                                                         value = (double)exponent;
00776                                                                 }
00777                                                                 break;
00778                                                         case Exp:
00779                                                                 value = exp (arg0);
00780                                                                 break;
00781                                                         case Floor:
00782                                                                 value = floor (arg0);
00783                                                                 break;
00784                                                         case Int:
00785                                                                 value = (double)(int)(arg0);
00786                                                                 break;
00787                                                         case Log10:
00788                                                                 value = log10 (arg0);
00789                                                                 break;
00790                                                         case Log:
00791                                                                 value = log (arg0);
00792                                                                 break;
00793                                                         case Mantissa:
00794                                                                 {
00795                                                                         int exponent;
00796                                                                         value = frexp( arg0, &exponent);
00797                                                                 }
00798                                                                 break;
00799                                                         case Round:
00800                                                                 value = floor (arg0 + 0.5);
00801                                                                 break;
00802                                                         case Sinh:
00803                                                                 value = sinh (arg0);
00804                                                                 break;
00805                                                         case Sin:
00806                                                                 value = sin (arg0);
00807                                                                 break;
00808                                                         case Sqrt:
00809                                                                 value = sqrt (arg0);
00810                                                                 break;
00811                                                         case Sq:
00812                                                                 value = arg0 * arg0;
00813                                                                 break;
00814                                                         case Tanh:
00815                                                                 value = tanh (arg0);
00816                                                                 break;
00817                                                         case Tan:
00818                                                                 value = tan (arg0);
00819                                                                 break;
00820                                                         default:
00821                                                                 // Can't be hear after getToken
00822                                                                 nlstop
00823                                                         }
00824                                                 }
00825                                                 else
00826                                                         return MustBeClose;
00827                                         }
00828                                 }
00829                                 else
00830                                         return error;
00831                         }
00832                         else
00833                                 return error;
00834 
00835                         // Get next token
00836                         error = getNextToken (nextToken);
00837                         if (error != NoError)
00838                                 return error;
00839                 }
00840                 else if (nextToken == Number)
00841                 {
00842                         // Save the internal value
00843                         value = _Value;
00844 
00845                         // Get next token
00846                         error = getNextToken (nextToken);
00847                         if (error != NoError)
00848                                 return error;
00849                 }
00850                 else if (nextToken == String)
00851                 {
00852                         // Copy the string
00853                         char                    internalString[InternalStringLen];
00854                         std::string             internalStlString;
00855                         const char              *internalStringPtr;
00856                         if (strlen (_InternalStringPtr) >= InternalStringLen-1)
00857                         {
00858                                 internalStlString = _InternalStringPtr;
00859                                 internalStringPtr = internalStlString.c_str ();
00860                         }
00861                         else
00862                         {
00863                                 strcpy (internalString ,_InternalStringPtr);
00864                                 internalStringPtr = internalString;
00865                         }
00866 
00867                         // Read a token
00868                         error = getNextToken (nextToken);
00869                         if (error == NoError)
00870                         {
00871                                 // Open ?
00872                                 if (nextToken == Open)
00873                                 {
00874                                         // Eval an expression
00875                                         double arg0;
00876                                         error = evalExpression (arg0, nextToken, userData);
00877                                         if (error == NoError)
00878                                         {
00879                                                 if (nextToken == Coma)
00880                                                 {
00881                                                         // Second argument
00882                                                         double arg1;
00883                                                         error = evalExpression (arg1, nextToken, userData);
00884                                                         if (error == NoError)
00885                                                         {
00886                                                                 // Final with close ?
00887                                                                 if (nextToken == Close)
00888                                                                 {
00889                                                                         // Eval the function
00890                                                                         error = evalFunction (internalStringPtr, arg0, arg1, value);
00891                                                                         if (error != NoError)
00892                                                                                 return error;
00893 
00894                                                                         // Get next token
00895                                                                         error = getNextToken (nextToken);
00896                                                                         if (error != NoError)
00897                                                                                 return error;
00898                                                                 }
00899                                                                 else
00900                                                                         return MustBeClose;
00901                                                         }
00902                                                         else
00903                                                                 return error;
00904                                                 }
00905                                                 else
00906                                                 {
00907                                                         if (nextToken == Close)
00908                                                         {
00909                                                                 // Eval the function
00910                                                                 error = evalFunction (internalStringPtr, arg0, value);
00911                                                                 if (error != NoError)
00912                                                                         return error;
00913 
00914                                                                 // Get next token
00915                                                                 error = getNextToken (nextToken);
00916                                                                 if (error != NoError)
00917                                                                         return error;
00918                                                         }
00919                                                         else
00920                                                                 return MustBeClose;
00921                                                 }
00922                                         }
00923                                         else
00924                                                 return error;
00925                                 }
00926                                 else
00927                                 {
00928                                         // This is a user value
00929                                         error = evalValue (internalStringPtr, value, userData);
00930                                         if (error != NoError)
00931                                                 return error;
00932                                 }
00933                         }
00934                         else
00935                                 return error;
00936                 }
00937                 else
00938                 {
00939                         return MustBeExpression;
00940                 }
00941 
00942                 // Eval unary operator
00943                 sint i;
00944                 for (i=unaryOpCount-1; i>=0; i--)
00945                 {
00946                         switch ((i<InternalOperator)?resultUnaryOp[i]:resultUnaryOpSup[i-InternalOperator])
00947                         {
00948                         case Not:
00949                                 value = (double)(uint)((floor (value+0.5)==0.0));
00950                                 break;
00951                         case Tilde:
00952                                 value = (double)~((uint)floor (value+0.5));
00953                                 break;
00954                         case Minus:
00955                                 value = -value;
00956                                 break;
00957                         default:
00958                                 // Can't be hear after getToken
00959                                 nlstop
00960                         }
00961                 }
00962 
00963                 // Push the value
00964                 if (exprCount < InternalOperator)
00965                         result[exprCount] = value;
00966                 else
00967                         resultSup.push_back (value);
00968                 exprCount++;
00969 
00970                 // Look for an operator
00971                 // Operator ?
00972                 if (nextToken == Operator)
00973                 {
00974                         // Yes, push it
00975                         if (opCount < InternalOperator)
00976                                 resultOp[opCount] = _Op;
00977                         else
00978                                 resultOpSup.push_back (_Op);
00979                         opCount++;
00980                 }
00981                 else 
00982                 {
00983                         // Exit the evaluate loop
00984                         break;
00985                 }
00986 
00987                 // Next token
00988                 error = getNextToken (nextToken);
00989         }
00990 
00991         // Reduce the expression
00992         uint index = 1;
00993         while (exprCount != 1)
00994         {
00995                 // Reduct ?
00996                 TOperator before = (((index-1)<InternalOperator)?resultOp[index-1]:resultOpSup[index-1-InternalOperator]);
00997                 TOperator after = (index < opCount)?(((index)<InternalOperator)?resultOp[index]:resultOpSup[index-InternalOperator]):NotOperator;
00998                 if ((index == opCount) || (_OperatorPrecedence[before] <= _OperatorPrecedence[after]))
00999                 {
01000                         // Eval the value
01001                         double &v0 = ((index-1)<InternalOperator)?result[index-1]:resultSup[index-1-InternalOperator];
01002                         double &v1 = ((index)<InternalOperator)?result[index]:resultSup[index-InternalOperator];
01003 
01004                         // Choose the operator
01005                         switch (before)
01006                         {
01007                         case Not:
01008                         case Tilde:
01009                                 return NotUnaryOperator;
01010                         case Mul:
01011                                 v0 *= v1;
01012                                 break;
01013                         case Div:
01014                                 v0 /= v1;
01015                                 break;
01016                         case Remainder:
01017                                 v0 = fmod (v0, v1);
01018                                 break;
01019                         case Plus:
01020                                 v0 += v1;
01021                                 break;
01022                         case Minus:
01023                                 v0 -= v1;
01024                                 break;
01025                         case ULeftShift:
01026                                 v0 = (double)(((uint)floor (v0 + 0.5))<<((uint)floor (v1 + 0.5)));
01027                                 break;
01028                         case URightShift:
01029                                 v0 = (double)(((uint)floor (v0 + 0.5))>>((uint)floor (v1 + 0.5)));
01030                                 break;
01031                         case SLeftShift:
01032                                 v0 = (double)(((sint)floor (v0 + 0.5))<<((sint)floor (v1 + 0.5)));
01033                                 break;
01034                         case SRightShift:
01035                                 v0 = (double)(((sint)floor (v0 + 0.5))>>((sint)floor (v1 + 0.5)));
01036                                 break;
01037                         case Inferior:
01038                                 v0 = (v0<v1)?1.0:0.0;
01039                                 break;
01040                         case InferiorEqual:
01041                                 v0 = (v0<=v1)?1.0:0.0;
01042                                 break;
01043                         case Superior:
01044                                 v0 = (v0>v1)?1.0:0.0;
01045                                 break;
01046                         case SuperiorEqual:
01047                                 v0 = (v0>=v1)?1.0:0.0;
01048                                 break;
01049                         case Equal:
01050                                 v0 = (v0==v1)?1.0:0.0;
01051                                 break;
01052                         case NotEqual:
01053                                 v0 = (v0!=v1)?1.0:0.0;
01054                                 break;
01055                         case And:
01056                                 v0 = (double)(((uint)floor (v0 + 0.5)) & ((uint)floor (v1 + 0.5)));
01057                                 break;
01058                         case Or:
01059                                 v0 = (double)(((uint)floor (v0 + 0.5)) | ((uint)floor (v1 + 0.5)));
01060                                 break;
01061                         case Xor:
01062                                 v0 = (double)(((uint)floor (v0 + 0.5)) ^ ((uint)floor (v1 + 0.5)));
01063                                 break;
01064                         case LogicalAnd:
01065                                 v0 = (double)(uint)((floor (v0 + 0.5) != 0.0) && (floor (v1 + 0.5) != 0.0));
01066                                 break;
01067                         case LogicalOr:
01068                                 v0 = (double)(uint)((floor (v0 + 0.5) != 0.0) || (floor (v1 + 0.5) != 0.0));
01069                                 break;
01070                         case LogicalXor:
01071                                 {
01072                                         bool b0 = floor (v0 + 0.5) != 0.0;
01073                                         bool b1 = floor (v1 + 0.5) != 0.0;
01074                                         v0 = (double)(uint)((b0&&!b1) || ((!b0)&&b1));
01075                                 }
01076                                 break;
01077                         default:
01078                                 nlassert (0);
01079                         }
01080 
01081                         // Decal others values
01082                         uint i = index;
01083                         for (; i<exprCount-1; i++)
01084                         {
01085                                 // Copy
01086                                 if (i<InternalOperator)
01087                                         result[i] = (i+1<InternalOperator)?result[i+1]:resultSup[i+1-InternalOperator];
01088                                 else 
01089                                         resultSup[i-InternalOperator] = (i+1<InternalOperator)?result[i+1]:resultSup[i+1-InternalOperator];
01090                         }
01091                         exprCount--;
01092 
01093                         // Decal operators
01094                         i = index-1;
01095                         for (; i<opCount-1; i++)
01096                         {
01097                                 // Copy
01098                                 if (i<InternalOperator)
01099                                         resultOp[i] = (i+1<InternalOperator)?resultOp[i+1]:resultOpSup[i+1-InternalOperator];
01100                                 else 
01101                                         resultOpSup[i-InternalOperator] = (i+1<InternalOperator)?resultOp[i+1]:resultOpSup[i+1-InternalOperator];
01102                                         
01103                         }
01104                         opCount--;
01105 
01106                         // Last one ?
01107                         if (index > 1)
01108                                 index--;
01109                 }
01110                 else
01111                         index++;
01112         }
01113 
01114         finalResult = result[0];
01115         return NoError;
01116 }
01117 
01118 // ***************************************************************************
01119 
01120 bool CEvalNumExpr::internalCheck ()
01121 {
01122         for (uint i=0; i<ReservedWordCount-1; i++)
01123                 if (strcmp (_ReservedWord[i], _ReservedWord[i+1]) >= 0)
01124                 {
01125                         nlassert (0);
01126                         return false;
01127                 }
01128         return true;
01129 }
01130 
01131 // ***************************************************************************
01132 
01133 // ASCII TABLE
01134 
01135 /*
01136 0 NUL   SOH             STX             ETX             EOT             ENQ             ACK             BEL             BS              TAB             LF              VT              FF              CR              SO              SI 
01137 1 DLE   DC1             DC2             DC3             DC4             NAK             SYN             ETB             CAN             EM              SUB             ESC             FS              GS              RS              US 
01138 2               !               "               #               $               %               &               '               (               )               *               +               ,               -               .               / 
01139 3 0             1               2               3               4               5               6               7               8               9               :               ;               <               =               >               ? 
01140 4 @             A               B               C               D               E               F               G               H               I               J               K               L               M               N               O 
01141 5 P             Q               R               S               T               U               V               W               X               Y               Z               [               \               ]               ^               _ 
01142 6 `             a               b               c               d               e               f               g               h               i               j               k               l               m               n               o 
01143 7 p             q               r               s               t               u               v               w               x               y               z               {               |               }               ~
01144 */
01145 
01146 // ***************************************************************************
01147 
01148 const CEvalNumExpr::TOperator   CEvalNumExpr::_OperatorArray[128] = 
01149 {
01150         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator,
01151         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator,
01152         NotOperator, ExtOperator, NotOperator, NotOperator, NotOperator, Remainder,   ExtOperator, NotOperator, NotOperator, NotOperator, Mul,             Plus,                NotOperator, ExtOperator, NotOperator, Div,
01153         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, ExtOperator, ExtOperator, ExtOperator, NotOperator,
01154         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator,
01155         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, ExtOperator, NotOperator,
01156         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator,
01157         NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, NotOperator, ExtOperator, NotOperator, Tilde,       NotOperator,
01158 };
01159 
01160 // ***************************************************************************
01161 
01162 const bool CEvalNumExpr::_StringChar[128] = 
01163 {
01164         false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
01165         false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
01166         false, false, true,  true,  true,  false, false, true,  false, false, false, false, false, false, false, false,
01167         true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  false, false, false, true,
01168         true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
01169         true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  false,  true,
01170         true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
01171         true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  false, true,  false, true,
01172 };
01173 
01174 // ***************************************************************************
01175 
01176 CEvalNumExpr::TReturnState CEvalNumExpr::evalValue (const char *value, double &result, uint32 userData)
01177 {
01178         return UnkownValue;
01179 }
01180 
01181 // ***************************************************************************
01182 
01183 CEvalNumExpr::TReturnState CEvalNumExpr::evalFunction (const char *funcName, double arg0, double &result)
01184 {
01185         return UnkownFunction;
01186 }
01187 
01188 // ***************************************************************************
01189 
01190 CEvalNumExpr::TReturnState CEvalNumExpr::evalFunction (const char *funcName, double arg0, double arg1, double &result)
01191 {
01192         return UnkownFunction;
01193 }
01194 
01195 // ***************************************************************************
01196 
01197 const char *CEvalNumExpr::_ReservedWord[ReservedWordCount] =
01198 {
01199         "abs", // Abs
01200         "acos", // Acos
01201         "asin", // Asin
01202         "atan", // Atan
01203         "atan2", // Atan2
01204         "ceil", // Ceil
01205         "cos",  // Cos
01206         "cosh", // Cosh
01207         "exp", // Exp
01208         "exponent", // Exponent
01209         "floor", // Floor
01210         "int", // Int
01211         "log", // Log
01212         "log10", // Log10
01213         "mantissa", // Mantissa
01214         "max", // Max
01215         "min", // Min
01216         "pow", // Pow
01217         "rand", // Rand
01218         "round", // Round
01219         "sin", // Sin
01220         "sinh", // Sinh
01221         "sq", // Sq
01222         "sqrt", // Sqrt
01223         "tan", // Tan
01224         "tanh", // Tanh
01225 };
01226 
01227 // ***************************************************************************
01228 
01229 const CEvalNumExpr::TToken CEvalNumExpr::_ReservedWordToken[ReservedWordCount] =
01230 {
01231         Function1, // Abs
01232         Function1, // Acos
01233         Function1, // Asin
01234         Function1, // Atan
01235         Function2, // Atan2
01236         Function1, // Ceil
01237         Function1, // Cos
01238         Function1, // Cosh
01239         Function1, // Exp
01240         Function1, // Exponent
01241         Function1, // Floor
01242         Function1, // Int
01243         Function1, // Log
01244         Function1, // Log10
01245         Function1, // Mantissa
01246         Function2, // Max
01247         Function2, // Min
01248         Function2, // Pow
01249         Function2, // Rand
01250         Function1, // Round
01251         Function1, // Sin
01252         Function1, // Sinh
01253         Function1, // Sq
01254         Function1, // Sqrt
01255         Function1, // Tan
01256         Function1, // Tanh
01257 };
01258 
01259 // ***************************************************************************
01260 
01261 const char *CEvalNumExpr::_ErrorString[ReturnValueCount]=
01262 {
01263         "No error",
01264         "Unkown value",
01265         "Error during user defined value evaluation",
01266         "Unkown function",
01267         "Error during user defined function evaluation",
01268         "Syntax error in a number expression",
01269         "Unkown operator",
01270         "Should be a open parentesis",
01271         "Should be a close parentesis",
01272         "Should be a coma character",
01273         "Should be an expression",
01274         "Should not be an unary operator",
01275         "Should be the end of the expression",
01276         "Should be a double quote",
01277 };
01278 
01279 // ***************************************************************************
01280 
01281 const char* CEvalNumExpr::getErrorString (TReturnState state) const
01282 {
01283         return _ErrorString[state];
01284 }
01285 
01286 // ***************************************************************************
01287 
01288 const int CEvalNumExpr::_OperatorPrecedence[]=
01289 {
01290         0,      // Not
01291         0,      // Tilde
01292         1,      // Mul
01293         1,      // Div
01294         1,      // Remainder
01295         2,      // Plus
01296         2,      // Minus
01297         3,      // ULeftShift
01298         3,      // URightShift
01299         3,      // SLeftShift
01300         3,      // SRightShift
01301         4,      // Inferior
01302         4,      // InferiorEqual
01303         4,      // Superior
01304         4,      // SuperiorEqual
01305         5,      // Equal
01306         5,      // NotEqual
01307         6,      // And
01308         7,      // Or
01309         8,      // Xor
01310         9,      // LogicalAnd
01311         10,     // LogicalOr
01312         11,     // LogicalXor
01313         0xffffffff,     // OperatorCount
01314         20,     // NotOperator
01315 };
01316 
01317 // ***************************************************************************
01318 
01319 }