Changeset 1494 for code/branches/network/src/util/ExprParser.cc
- Timestamp:
- May 31, 2008, 11:24:44 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/network/src/util/ExprParser.cc
- Property svn:eol-style set to native
r1120 r1494 1 1 /* 2 2 * ORXONOX - the hottest 3D action shooter ever to exist 3 * > www.orxonox.net < 4 * 3 * > www.orxonox.net < * 5 4 * 6 5 * License notice: … … 31 30 @brief Declaration of FloatParser 32 31 */ 33 34 #include "ExprParser.h" 35 #include <cmath> 36 #include <cstring> 37 38 // macros for easier if, else statements 39 #define CASE_1(var) if (!strcmp(SWITCH,var)) 40 #define CASE(var) else if (!strcmp(SWITCH,var)) 41 #define CASE_ELSE else 42 43 //! skip white spaces 44 #define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream; 45 46 ExprParser::ExprParser(const std::string& str) 47 { 48 this->failed_ = false; 49 this->reading_stream = str.c_str(); 50 if (str.size() == 0 || *reading_stream == '\0') 51 { 52 this->failed_ = true; 53 this->result_ = 0.0; 54 } 55 else 56 { 57 this->result_ = parse_expr_8(); 58 this->remains_ = reading_stream; 59 } 60 } 61 62 //Private functions: 63 /******************/ 64 double ExprParser::parse_argument() 65 { 66 double value = parse_expr_8(); 67 if (*reading_stream == ',') 68 { 69 ++reading_stream; 70 return value; 71 } 72 else 73 { 74 this->failed_ = true; 75 return 0; 76 } 77 } 78 79 double ExprParser::parse_last_argument() 80 { 81 double value = parse_expr_8(); 82 if (*reading_stream == ')') 83 { 84 ++reading_stream; 85 return value; 86 } 87 else 88 { 89 this->failed_ = true; 90 return 0; 91 } 92 } 93 94 double ExprParser::parse_expr_8() 95 { 96 double value = parse_expr_7(); 97 for(;;) 98 { 99 switch (op) 100 { 101 case oder: 102 value = parse_expr_7() || value; 103 break; 104 default: return value; 105 } 106 }; 107 } 108 109 110 double ExprParser::parse_expr_7() 111 { 112 double value = parse_expr_6(); 113 for(;;) 114 { 115 switch (op) 116 { 117 case und: 118 value = value && parse_expr_6(); 119 break; 120 default: return value; 121 } 122 }; 123 } 124 125 double ExprParser::parse_expr_6() 126 { 127 double value = parse_expr_5(); 128 for(;;) 129 { 130 switch (op) 131 { 132 case gleich: 133 value = (value == parse_expr_5()); 134 break; 135 case ungleich: 136 value = (value != parse_expr_5()); 137 break; 138 default: 139 return value; 140 } 141 }; 142 } 143 144 double ExprParser::parse_expr_5() 145 { 146 double value = parse_expr_4(); 147 for(;;) 148 { 149 switch (op) 150 { 151 case kleiner: 152 value = (value < parse_expr_4()); 153 break; 154 case kleinergleich: 155 value = (value <= parse_expr_4()); 156 break; 157 case groesser: 158 value = (value > parse_expr_4()); 159 break; 160 case groessergleich: 161 value = (value >= parse_expr_4()); 162 break; 163 default: 164 return value; 165 } 166 }; 167 } 168 169 double ExprParser::parse_expr_4() 170 { 171 double value = parse_expr_3(); 172 for(;;) 173 { 174 switch (op) 175 { 176 case b_plus: 177 value += parse_expr_3(); 178 break; 179 case b_minus: 180 value -= parse_expr_3(); 181 break; 182 default: 183 return value; 184 } 185 }; 186 } 187 188 double ExprParser::parse_expr_3() 189 { 190 double value = parse_expr_2(); 191 for(;;) 192 { 193 switch (op) 194 { 195 case mal: 196 value *= parse_expr_2(); 197 break; 198 case durch: 199 value /= parse_expr_2(); 200 break; 201 case modulo: 202 { 203 double temp = parse_expr_2(); 204 value = value - floor(value/temp)*temp; 205 break; 206 } 207 default: 208 return value; 209 } 210 }; 211 } 212 213 double ExprParser::parse_expr_2() 214 { 215 double value = parse_expr_1(); 216 while (*reading_stream != '\0') 217 { 218 op = parse_binary_operator(); 219 switch (op) 220 { 221 case hoch: 222 value = pow(value,parse_expr_1()); 223 break; 224 default: 225 return value; 226 } 227 }; 228 op = undef; 229 return value; 230 } 231 232 double ExprParser::parse_expr_1() 233 { 234 PARSE_BLANKS 235 double value; 236 237 unary_operator op = parse_unary_operator(); 238 PARSE_BLANKS 239 240 if (*reading_stream == '\0') 241 { 242 // end of string 243 this->failed_ = true; 244 return 0; 245 } 246 else if (*reading_stream > 47 && *reading_stream < 59 || *reading_stream == 46) 247 { // number 248 value = strtod(reading_stream, const_cast<char**>(&reading_stream)); 249 } 250 else if (*reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46) 251 { // variable or function 252 char* word = new char[256]; 253 parse_word(word); 254 PARSE_BLANKS 255 if (*reading_stream == '(') 256 { 257 ++reading_stream; 258 #define SWITCH word 259 CASE_1("sin") 260 value = sin(parse_last_argument()); 261 CASE("asin") 262 value = asin(parse_last_argument()); 263 CASE("sinh") 264 value = sinh(parse_last_argument()); 265 CASE("asinh") 266 { 267 value = parse_last_argument(); 268 value = log(sqrt(pow(value, 2) + 1) + value); 269 } 270 CASE("cos") 271 value = cos(parse_last_argument()); 272 CASE("acos") 273 value = acos(parse_last_argument()); 274 CASE("cosh") 275 value = cosh(parse_last_argument()); 276 CASE("acosh") 277 { 278 value = parse_last_argument(); 279 value = log(sqrt(pow(value, 2) - 1) + value); 280 } 281 CASE("tan") 282 value = tan(parse_last_argument()); 283 CASE("atan") 284 value = atan(parse_last_argument()); 285 CASE("atan2") 286 value = atan2(parse_argument(),parse_last_argument()); 287 CASE("tanh") 288 value = tanh(parse_last_argument()); 289 CASE("atanh") 290 { 291 value = parse_last_argument(); 292 value = 0.5*log((value + 1)/(value - 1)); 293 } 294 CASE("int") 295 value = floor(parse_last_argument()); 296 CASE("floor") 297 value = floor(parse_last_argument()); 298 CASE("ceil") 299 value = ceil(parse_last_argument()); 300 CASE("abs") 301 value = fabs(parse_last_argument()); 302 CASE("exp") 303 value = exp(parse_last_argument()); 304 CASE("log") 305 value = log10(parse_last_argument()); 306 CASE("ln") 307 value = log(parse_last_argument()); 308 CASE("sign") 309 { 310 value = parse_last_argument(); 311 value = (value>0 ? 1 : (value<0 ? -1 : 0)); 312 } 313 CASE("sqrt") 314 value = sqrt(parse_last_argument()); 315 CASE("degrees") 316 value = parse_last_argument()*180/3.1415926535897932; 317 CASE("radians") 318 value = parse_last_argument()*3.1415926535897932/180; 319 CASE("mod") 320 { 321 value = parse_argument(); 322 double value2 = parse_last_argument(); 323 value = value - floor(value/value2)*value2; 324 } 325 CASE("pow") 326 value = pow(parse_argument(),parse_last_argument()); 327 CASE("div") 328 value = floor(parse_argument()/parse_last_argument()); 329 CASE("max") 330 value = std::max(parse_argument(),parse_last_argument()); 331 CASE("min") 332 value = std::min(parse_argument(),parse_last_argument()); 333 CASE_ELSE 334 { 335 this->failed_ = true; 336 delete[] word; 337 return 0; 338 } 339 } 340 else 341 { 342 #define SWITCH word 343 CASE_1("pi") 344 value = 3.1415926535897932; 345 CASE("e") 346 value = 2.7182818284590452; 347 CASE_ELSE 348 { 349 this->failed_ = true; 350 delete[] word; 351 return 0; 352 } 353 } 354 delete[] word; 355 } 356 else if (*reading_stream == 40) 357 { // expresion in paranthesis 358 ++reading_stream; 359 value = parse_last_argument(); 360 } 361 else 362 { 363 this->failed_ = true; 364 return 0; 365 } 366 367 PARSE_BLANKS 368 switch (op) 369 { 370 case u_nicht: return !value; 371 case u_plus: return value; 372 case u_minus: return -value; 373 default: 374 { 375 this->failed_ = true; 376 return 0; 377 } 378 } 379 } 380 381 char* ExprParser::parse_word(char* str) 382 { 383 char* word = str; 384 int counter = 0; 385 while (*reading_stream > 47 && *reading_stream < 58 || *reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46) 386 { 387 *word++ = *reading_stream++; 388 counter++; 389 if (counter > 255) 390 { 391 this->failed_ = true; 392 return '\0'; 393 } 394 }; 395 *word = '\0'; 396 return str; 397 } 398 399 ExprParser::binary_operator ExprParser::parse_binary_operator() 400 { 401 binary_operator op; 402 switch (*reading_stream) 403 { 404 case '+': op = b_plus; break; 405 case '-': op = b_minus; break; 406 case '*': op = mal; break; 407 case '/': op = durch; break; 408 case '^': op = hoch; break; 409 case '%': op = modulo; break; 410 case '&': op = und; break; 411 case '|': op = oder; break; 412 case '=': op = gleich; break; 413 case '!': op = b_nicht; break; 414 case '<': op = kleiner; break; 415 case '>': op = groesser; break; 416 default: return undef; 417 } 418 if (*++reading_stream == '=') 419 { 420 if (op > 9) 421 { 422 ++reading_stream; 423 return (binary_operator)(op + 3); 424 } 425 else 426 { 427 --reading_stream; 428 return undef; 429 } 430 } 431 else 432 return op; 433 } 434 435 ExprParser::unary_operator ExprParser::parse_unary_operator() 436 { 437 switch (*reading_stream) 438 { 439 case '!': 440 ++reading_stream; 441 return u_nicht; 442 case '+': 443 ++reading_stream; 444 return u_plus; 445 case '-': 446 ++reading_stream; 447 return u_minus; 448 default : 449 return u_plus; 450 } 451 } 32 #include "ExprParser.h"#include <cmath>#include <cstring>// macros for easier if, else statements#define CASE_1(var) if (!strcmp(SWITCH,var))#define CASE(var) else if (!strcmp(SWITCH,var))#define CASE_ELSE else//! skip white spaces#define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream;ExprParser::ExprParser(const std::string& str){ this->failed_ = false; this->reading_stream = str.c_str(); if (str.size() == 0 || *reading_stream == '\0') { this->failed_ = true; this->result_ = 0.0; } else { this->result_ = parse_expr_8(); this->remains_ = reading_stream; }}//Private functions:/******************/double ExprParser::parse_argument(){ double value = parse_expr_8(); if (*reading_stream == ',') { ++reading_stream; return value; } else { this->failed_ = true; return 0; }}double ExprParser::parse_last_argument(){ double value = parse_expr_8(); if (*reading_stream == ')') { ++reading_stream; return value; } else { this->failed_ = true; return 0; }}double ExprParser::parse_expr_8(){ double value = parse_expr_7(); for(;;) { switch (op) { case oder: value = parse_expr_7() || value; break; default: return value; } };}double ExprParser::parse_expr_7(){ double value = parse_expr_6(); for(;;) { switch (op) { case und: value = value && parse_expr_6(); break; default: return value; } };}double ExprParser::parse_expr_6(){ double value = parse_expr_5(); for(;;) { switch (op) { case gleich: value = (value == parse_expr_5()); break; case ungleich: value = (value != parse_expr_5()); break; default: return value; } };}double ExprParser::parse_expr_5(){ double value = parse_expr_4(); for(;;) { switch (op) { case kleiner: value = (value < parse_expr_4()); break; case kleinergleich: value = (value <= parse_expr_4()); break; case groesser: value = (value > parse_expr_4()); break; case groessergleich: value = (value >= parse_expr_4()); break; default: return value; } };}double ExprParser::parse_expr_4(){ double value = parse_expr_3(); for(;;) { switch (op) { case b_plus: value += parse_expr_3(); break; case b_minus: value -= parse_expr_3(); break; default: return value; } };}double ExprParser::parse_expr_3(){ double value = parse_expr_2(); for(;;) { switch (op) { case mal: value *= parse_expr_2(); break; case durch: value /= parse_expr_2(); break; case modulo: { double temp = parse_expr_2(); value = value - floor(value/temp)*temp; break; } default: return value; } };}double ExprParser::parse_expr_2(){ double value = parse_expr_1(); while (*reading_stream != '\0') { op = parse_binary_operator(); switch (op) { case hoch: value = pow(value,parse_expr_1()); break; default: return value; } }; op = undef; return value;}double ExprParser::parse_expr_1(){ PARSE_BLANKS double value; unary_operator op = parse_unary_operator(); PARSE_BLANKS if (*reading_stream == '\0') { // end of string this->failed_ = true; return 0; } else if (*reading_stream > 47 && *reading_stream < 59 || *reading_stream == 46) { // number value = strtod(reading_stream, const_cast<char**>(&reading_stream)); } else if (*reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46) { // variable or function char* word = new char[256]; parse_word(word); PARSE_BLANKS if (*reading_stream == '(') { ++reading_stream;#define SWITCH word CASE_1("sin") value = sin(parse_last_argument()); CASE("asin") value = asin(parse_last_argument()); CASE("sinh") value = sinh(parse_last_argument()); CASE("asinh") { value = parse_last_argument(); value = log(sqrt(pow(value, 2) + 1) + value); } CASE("cos") value = cos(parse_last_argument()); CASE("acos") value = acos(parse_last_argument()); CASE("cosh") value = cosh(parse_last_argument()); CASE("acosh") { value = parse_last_argument(); value = log(sqrt(pow(value, 2) - 1) + value); } CASE("tan") value = tan(parse_last_argument()); CASE("atan") value = atan(parse_last_argument()); CASE("atan2") value = atan2(parse_argument(),parse_last_argument()); CASE("tanh") value = tanh(parse_last_argument()); CASE("atanh") { value = parse_last_argument(); value = 0.5*log((value + 1)/(value - 1)); } CASE("int") value = floor(parse_last_argument()); CASE("floor") value = floor(parse_last_argument()); CASE("ceil") value = ceil(parse_last_argument()); CASE("abs") value = fabs(parse_last_argument()); CASE("exp") value = exp(parse_last_argument()); CASE("log") value = log10(parse_last_argument()); CASE("ln") value = log(parse_last_argument()); CASE("sign") { value = parse_last_argument(); value = (value>0 ? 1 : (value<0 ? -1 : 0)); } CASE("sqrt") value = sqrt(parse_last_argument()); CASE("degrees") value = parse_last_argument()*180/3.1415926535897932; CASE("radians") value = parse_last_argument()*3.1415926535897932/180; CASE("mod") { value = parse_argument(); double value2 = parse_last_argument(); value = value - floor(value/value2)*value2; } CASE("pow") value = pow(parse_argument(),parse_last_argument()); CASE("div") value = floor(parse_argument()/parse_last_argument()); CASE("max") value = std::max(parse_argument(),parse_last_argument()); CASE("min") value = std::min(parse_argument(),parse_last_argument()); CASE_ELSE { this->failed_ = true; delete[] word; return 0; } } else {#define SWITCH word CASE_1("pi") value = 3.1415926535897932; CASE("e") value = 2.7182818284590452; CASE_ELSE { this->failed_ = true; delete[] word; return 0; } } delete[] word; } else if (*reading_stream == 40) { // expresion in paranthesis ++reading_stream; value = parse_last_argument(); } else { this->failed_ = true; return 0; } PARSE_BLANKS switch (op) { case u_nicht: return !value; case u_plus: return value; case u_minus: return -value; default: { this->failed_ = true; return 0; } }}char* ExprParser::parse_word(char* str){ char* word = str; int counter = 0; while (*reading_stream > 47 && *reading_stream < 58 || *reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46) { *word++ = *reading_stream++; counter++; if (counter > 255) { this->failed_ = true; return '\0'; } }; *word = '\0'; return str;}ExprParser::binary_operator ExprParser::parse_binary_operator(){ binary_operator op; switch (*reading_stream) { case '+': op = b_plus; break; case '-': op = b_minus; break; case '*': op = mal; break; case '/': op = durch; break; case '^': op = hoch; break; case '%': op = modulo; break; case '&': op = und; break; case '|': op = oder; break; case '=': op = gleich; break; case '!': op = b_nicht; break; case '<': op = kleiner; break; case '>': op = groesser; break; default: return undef; } if (*++reading_stream == '=') { if (op > 9) { ++reading_stream; return (binary_operator)(op + 3); } else { --reading_stream; return undef; } } else return op;}ExprParser::unary_operator ExprParser::parse_unary_operator(){ switch (*reading_stream) { case '!': ++reading_stream; return u_nicht; case '+': ++reading_stream; return u_plus; case '-': ++reading_stream; return u_minus; default : return u_plus; }}
Note: See TracChangeset
for help on using the changeset viewer.