00001
00040 #include <cmath>
00041 #include <cstdlib>
00042 #include <iomanip>
00043 #include <sstream>
00044 #include <string>
00045 #include <vector>
00046
00047 #include "popassert.h"
00048 #include "CVector3f.h"
00049 #include "compute.h"
00050 #include "CMathExpression.h"
00051
00052
00053
00062 inline bool In(const char* Formula, int min, int max)
00063 {
00064 int Counter = 0;
00065 for (int i = min; i < max; ++i)
00066 {
00067 if (Formula[i] == '(')
00068 ++Counter;
00069 if (Formula[i] == ')')
00070 --Counter;
00071 }
00072 return (Counter != 0);
00073 }
00074
00075
00076
00077
00081 CValue* CMathExpression::BuildFormula(const char* Formula,
00082 int min,
00083 int max)
00084 {
00085 POP_ASSERT(Formula != NULL, "Using a NULL pointer.");
00086
00087 if (min < max)
00088 {
00089 if (Formula[min] == ' ')
00090 return BuildFormula(Formula, min+1, max);
00091 if (Formula[max-1] == ' ')
00092 return BuildFormula(Formula, min, max-1);
00093 }
00094
00095
00096 int i, j;
00097
00098
00099 for (i = max-1; i > min-1; --i)
00100 if ((Formula[i] == '+') || (Formula[i] == '-'))
00101 if ( !(In(Formula, min, i)) )
00102 if (Formula[i] == '+')
00103 return(CValue::GetNewAddition(BuildFormula(Formula, min, i),
00104 BuildFormula(Formula, i+1, max)));
00105 else
00106 if (i == min)
00107 {
00108 return(CValue::GetNewOpposite(BuildFormula(Formula, i+1, max)));
00109 }
00110 else
00111 return(CValue::GetNewSubstraction(BuildFormula(Formula, min, i),
00112 BuildFormula(Formula, i+1, max)));
00113
00114
00115 for (i = max-1; i > min; --i)
00116 if ((Formula[i] == '*') || (Formula[i] == '/'))
00117 if ( !(In(Formula, min, i)) )
00118 if (Formula[i] == '*')
00119 return(CValue::GetNewProduct(BuildFormula(Formula, min, i),
00120 BuildFormula(Formula, i+1, max)));
00121 else
00122 return(CValue::GetNewDivision(BuildFormula(Formula, min, i),
00123 BuildFormula(Formula, i+1, max)));
00124
00125
00126 for (i = min; i < max; ++i)
00127 if ( (Formula[i] == 's') || (Formula[i] == 'c') ||
00128 (Formula[i] == 't') || (Formula[i] == 'e') ||
00129 (Formula[i] == 'l') || (Formula[i] == '^') )
00130 if ( !(In(Formula, min, i)) )
00131 switch (Formula[i])
00132 {
00133 case('s'):
00134 if ((Formula[i+1] == 'q') &&
00135 (Formula[i+2] == 'r') &&
00136 (Formula[i+3] == 't'))
00137 return(CValue::GetNewSqrt(BuildFormula(Formula, i+4, max)));
00138
00139 if ((Formula[i+1] == 'i') &&
00140 (Formula[i+2] == 'n'))
00141 return(CValue::GetNewSin(BuildFormula(Formula, i+3, max)));
00142
00143 break;
00144
00145 case('c'):
00146 if ((Formula[i+1] == 'o') &&
00147 (Formula[i+2] == 's'))
00148 return(CValue::GetNewCos(BuildFormula(Formula, i+3, max)));
00149 break;
00150
00151 case('t'):
00152 if ((Formula[i+1] == 'a') &&
00153 (Formula[i+2] == 'n'))
00154 return(CValue::GetNewTan(BuildFormula(Formula, i+3, max)));
00155 break;
00156
00157 case('e'):
00158 if ((Formula[i+1] == 'x') &&
00159 (Formula[i+2] == 'p'))
00160 return(CValue::GetNewExp(BuildFormula(Formula, i+3, max)));
00161 break;
00162
00163 case('l'):
00164 if (Formula[i+1] == 'n')
00165 return(CValue::GetNewLn(BuildFormula(Formula, i+2, max)));
00166 break;
00167
00168 case('^') :
00169 return(CValue::GetNewPow(BuildFormula(Formula, min, i),
00170 BuildFormula(Formula, i+1, max)));
00171 break;
00172 }
00173
00174
00175 for (i = min; i < max; ++i)
00176 if (Formula[i] == '(')
00177 for (j = max; j > i; --j)
00178 if (Formula[j-1] == ')')
00179 return(BuildFormula(Formula, i+1, j));
00180
00181
00182 for (i = min; i < max; ++i)
00183 if ((Formula[i] == 'x') || (Formula[i] == 'y') || (Formula[i] == 'z'))
00184 switch (Formula[i])
00185 {
00186 case('x'): return(new CVariable(CValue::TYPE_X)); break;
00187 case('y'): return(new CVariable(CValue::TYPE_Y)); break;
00188 case('z'): return(new CVariable(CValue::TYPE_Z)); break;
00189 }
00190
00191
00192 for (i = min; i < max; ++i)
00193 if ((Formula[i] <= '9') && (Formula[i] >= '0'))
00194 {
00195 j = i;
00196 while ( ( ( (Formula[j] <= '9') &&
00197 (Formula[j] >= '0') ) ||
00198 (Formula[j] == '.') )&&
00199 (j < max))
00200 {
00201 ++j;
00202 }
00203 char* buffer = new char[j-i+1];
00204 int k;
00205 for (k = i; k < j; ++k)
00206 buffer[k-i] = Formula[k];
00207 buffer[k-i] = '\0';
00208 float Value = atof(buffer);
00209 delete []buffer;
00210 return(new CNumber(Value));
00211 }
00212
00213
00214 if (min < max && Formula[min] == ' ')
00215 return(BuildFormula(Formula, min+1, max));
00216
00217
00218 POP_ILLEGAL("Nothing has been found in formula construction.");
00219 return 0;
00220 }
00221
00222
00226 CMathExpression::CMathExpression(const char * Formula)
00227 : m_pFormula(0), m_pFunction(0)
00228 {
00229 if (Formula)
00230 {
00231 int i;
00232 std::string strFormula(Formula);
00233
00234 for (i = 0; i < (int) strFormula.size(); ++i)
00235 {
00236 if (strFormula[i] == ' ' || strFormula[i] == '\t')
00237 {
00238 strFormula.erase(i, 1);
00239 --i;
00240 }
00241 }
00242
00243 for (i = strFormula.size() - 1; i >= 0 && strFormula[i] != '='; --i);
00244 m_pFormula =
00245 CValue::GetNewSubstraction(BuildFormula(strFormula.c_str(), 0, i),
00246 BuildFormula(strFormula.c_str(), i+1,
00247 strFormula.size())
00248 );
00249 Compile();
00250 }
00251 else
00252 {
00253 m_pFormula = 0;
00254 m_pFunction = 0;
00255 }
00256 }
00257
00258
00263 bool CMathExpression::Validate(const std::string& strFormula,
00264 int *value,
00265 int min,
00266 int max)
00267 {
00268 if (value)
00269 {
00270 value[0] = min;
00271 value[1] = max;
00272 }
00273
00274 int i, j;
00275
00276 if (min < 0 && max < 0)
00277 {
00278 for (i = 0; i < (int) strFormula.size() && strFormula[i] != '='; ++i);
00279 if (i == (int) strFormula.size())
00280 {
00281 return false;
00282 }
00283 else
00284 return (Validate(strFormula, value, 0, i) &&
00285 Validate(strFormula, value, i+1, strFormula.size()));
00286 }
00287
00288
00289 if (min < max)
00290 {
00291 if (strFormula[min] == ' ')
00292 return Validate(strFormula, value, min+1, max);
00293 if (strFormula[max-1] == ' ')
00294 return Validate(strFormula, value, min, max-1);
00295 }
00296
00297
00298 for (i = max-1; i > min-1; --i)
00299 if ((strFormula[i] == '+') || (strFormula[i] == '-'))
00300 if ( !(In(strFormula.c_str(), min, i)) )
00301 if (strFormula[i] == '+')
00302 return (Validate(strFormula, value, min, i) &&
00303 Validate(strFormula, value, i+1, max));
00304 else
00305 if (i == min)
00306 {
00307 return(Validate(strFormula, value, i+1, max));
00308 }
00309 else
00310 return (Validate(strFormula, value, min, i) &&
00311 Validate(strFormula, value, i+1, max));
00312
00313
00314 for (i = max-1; i > min; --i)
00315 if ((strFormula[i] == '*') || (strFormula[i] == '/'))
00316 if ( !(In(strFormula.c_str(), min, i)) )
00317 if (strFormula[i] == '*')
00318 return (Validate(strFormula, value, min, i) &&
00319 Validate(strFormula, value, i+1, max));
00320 else
00321 return (Validate(strFormula, value, min, i) &&
00322 Validate(strFormula, value, i+1, max));
00323
00324
00325 for (i = min; i < max; ++i)
00326 if ( (strFormula[i] == 's') || (strFormula[i] == 'c') ||
00327 (strFormula[i] == 't') || (strFormula[i] == 'e') ||
00328 (strFormula[i] == 'l') || (strFormula[i] == '^') )
00329 if ( !(In(strFormula.c_str(), min, i)) )
00330 switch (strFormula[i])
00331 {
00332 case('s'):
00333 if ((strFormula[i+1] == 'q') &&
00334 (strFormula[i+2] == 'r') &&
00335 (strFormula[i+3] == 't'))
00336 return(Validate(strFormula, value, i+4, max));
00337
00338 if ((strFormula[i+1] == 'i') &&
00339 (strFormula[i+2] == 'n'))
00340 return(Validate(strFormula, value, i+3, max));
00341
00342 break;
00343
00344 case('c'):
00345 if ((strFormula[i+1] == 'o') &&
00346 (strFormula[i+2] == 's'))
00347 return(Validate(strFormula, value, i+3, max));
00348 break;
00349
00350 case('t'):
00351 if ((strFormula[i+1] == 'a') &&
00352 (strFormula[i+2] == 'n'))
00353 return(Validate(strFormula, value, i+3, max));
00354 break;
00355
00356 case('e'):
00357 if ((strFormula[i+1] == 'x') &&
00358 (strFormula[i+2] == 'p'))
00359 return(Validate(strFormula, value, i+3, max));
00360 break;
00361
00362 case('l'):
00363 if (strFormula[i+1] == 'n')
00364 return(Validate(strFormula, value, i+2, max));
00365 break;
00366
00367 case('^') :
00368 return (Validate(strFormula, value, min, i) &&
00369 Validate(strFormula, value, i+1, max));
00370 break;
00371 }
00372
00373
00374 if (strFormula[min] == '(' && strFormula[max-1] == ')')
00375 return(Validate(strFormula, value, min+1, max-1));
00376
00377
00378 if ((strFormula[min] == 'x') || (strFormula[min] == 'y') || (strFormula[min] == 'z'))
00379 return (min == max - 1);
00380
00381
00382 int dotfound = 0;
00383 int digitfound = 0;
00384 if ( ( (strFormula[min] <= '9') && (strFormula[min] >= '0') ) ||
00385 (strFormula[min] == '.') )
00386 {
00387 j = min;
00388 while ( ( ( (strFormula[j] <= '9') &&
00389 (strFormula[j] >= '0') ) ||
00390 (strFormula[j] == '.') )&&
00391 (j < max))
00392 {
00393 if (strFormula[j] == '.')
00394 ++dotfound;
00395 if (strFormula[j] <= '9' && strFormula[j] >= '0')
00396 ++digitfound;
00397 if (dotfound > 1)
00398 {
00399 return false;
00400 }
00401 ++j;
00402 }
00403
00404 return (j == max && digitfound > 0);
00405 }
00406
00407 return false;
00408 }
00409
00410
00415 void CMathExpression::Compile(std::vector<char>& v) const
00416 {
00417 v = std::vector<char>();
00418
00419
00420 v.push_back('\x55');
00421
00422 v.push_back('\x89');
00423 v.push_back('\xe5');
00424
00425 v.push_back('\x8b');
00426 v.push_back('\x45');
00427 v.push_back('\x08');
00428
00429 v.push_back('\x9b');
00430 v.push_back('\xdb');
00431 v.push_back('\xe3');
00432
00433
00434
00435 int i = 0;
00436 m_pFormula->Compile(v, i);
00437
00438
00439
00440 v.push_back('\x89');
00441 v.push_back('\xec');
00442
00443 v.push_back('\x5d');
00444
00445 v.push_back('\xc3');
00446 }
00447
00448