Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
May 31, 2008, 11:24:44 PM (16 years ago)
Author:
rgrieder
Message:
  • set the svn:eol-style property to all files so, that where ever you check out, you'll get the right line endings (had to change every file with mixed endings to windows in order to set the property)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/network/src/util/ExprParser.cc

    • Property svn:eol-style set to native
    r1120 r1494  
    11/*
    22 *   ORXONOX - the hottest 3D action shooter ever to exist
    3  *                    > www.orxonox.net <
    4  *
     3 *                    > www.orxonox.net < *
    54 *
    65 *   License notice:
     
    3130  @brief Declaration of FloatParser
    3231*/
    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.