Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/ExprParser.cc @ 11743

Last change on this file since 11743 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 12.6 KB
RevLine 
[1118]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1505]3 *                    > www.orxonox.net <
[1118]4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30  @file
31  @brief Declaration of FloatParser
32*/
[1505]33
34#include "ExprParser.h"
[7184]35
[1505]36#include <cmath>
37#include <cstring>
[3196]38#include <cstdlib>
[7184]39#include "Math.h"
[1505]40
41// macros for easier if, else statements
42#define CASE_1(var) if (!strcmp(SWITCH,var))
43#define CASE(var) else if (!strcmp(SWITCH,var))
44#define CASE_ELSE else
45
46//! skip white spaces
[1894]47#define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream
[1505]48
[2171]49namespace orxonox
[1505]50{
[6417]51    ExprParser::ExprParser()
[1894]52    {
[2171]53        this->failed_ = false;
[8351]54        this->variables_["pi"] = math::pi;
55        this->variables_["e"] = math::e;
[6417]56    }
57
[8351]58    void ExprParser::setVariable(const std::string& varname, float value)
[6417]59    {
60        this->variables_[varname] = value;
61    }
62
63    void ExprParser::parse(const std::string& str)
64    {
[2171]65        this->reading_stream = str.c_str();
66        if (str.size() == 0 || *reading_stream == '\0')
[1894]67        {
[2171]68            this->failed_ = true;
69            this->result_ = 0.0;
[1894]70        }
[2171]71        else
[1894]72        {
[2171]73            this->result_ = parse_expr_8();
74            this->remains_ = reading_stream;
[1894]75        }
[2171]76    }
[1505]77
[2171]78    //Private functions:
79    /******************/
[8351]80    float ExprParser::parse_argument()
[1894]81    {
[8351]82        float value = parse_expr_8();
[2171]83        if (*reading_stream == ',')
[1894]84        {
[2171]85            ++reading_stream;
[1505]86            return value;
[1894]87        }
[2171]88        else
89        {
90            this->failed_ = true;
91            return 0;
92        }
93    }
[1505]94
[8351]95    float ExprParser::parse_last_argument()
[1894]96    {
[8351]97        float value = parse_expr_8();
[2171]98        if (*reading_stream == ')')
[1894]99        {
[2171]100            ++reading_stream;
[1505]101            return value;
[1894]102        }
[2171]103        else
104        {
105            this->failed_ = true;
106            return 0;
107        }
108    }
[1505]109
[8351]110    float ExprParser::parse_expr_8()
[1894]111    {
[8351]112        float value = parse_expr_7();
[2171]113        for(;;)
[1894]114        {
[2171]115            switch (op)
116            {
117            case oder:
118                value = parse_expr_7() || value;
119                break;
120            default: return value;
121            }
122        };
123    }
[1505]124
[2171]125
[8351]126    float ExprParser::parse_expr_7()
[1894]127    {
[8351]128        float value = parse_expr_6();
[2171]129        for(;;)
[1894]130        {
[2171]131            switch (op)
[1894]132            {
[2171]133            case und:
134                value = value && parse_expr_6();
[1894]135                break;
[2171]136            default: return value;
[1894]137            }
[2171]138        };
139    }
[1505]140
[8351]141    float ExprParser::parse_expr_6()
[1894]142    {
[8351]143        float value = parse_expr_5();
[2171]144        for(;;)
[1894]145        {
[2171]146            switch (op)
147            {
148            case gleich:
149                value = (value == parse_expr_5());
150                break;
151            case ungleich:
152                value = (value != parse_expr_5());
153                break;
154            default:
155                return value;
156            }
157        };
158    }
[1505]159
[8351]160    float ExprParser::parse_expr_5()
[1894]161    {
[8351]162        float value = parse_expr_4();
[2171]163        for(;;)
[1894]164        {
[2171]165            switch (op)
[1894]166            {
[2171]167            case kleiner:
168                value = (value < parse_expr_4());
169                break;
170            case kleinergleich:
171                value = (value <= parse_expr_4());
172                break;
173            case groesser:
174                value = (value > parse_expr_4());
175                break;
176            case groessergleich:
177                value = (value >= parse_expr_4());
178                break;
179            default:
180                return value;
[1894]181            }
[2171]182        };
183    }
184
[8351]185    float ExprParser::parse_expr_4()
[2171]186    {
[8351]187        float value = parse_expr_3();
[2171]188        for(;;)
189        {
190            switch (op)
[1894]191            {
[2171]192            case b_plus:
193                value += parse_expr_3();
194                break;
195            case b_minus:
196                value -= parse_expr_3();
197                break;
198            default:
199                return value;
[1894]200            }
[2171]201        };
202    }
203
[8351]204    float ExprParser::parse_expr_3()
[2171]205    {
[8351]206        float value = parse_expr_2();
[2171]207        for(;;)
208        {
209            switch (op)
[1894]210            {
[2171]211            case mal:
212                value *= parse_expr_2();
213                break;
214            case durch:
215                value /= parse_expr_2();
216                break;
217            case modulo:
218                {
[8351]219                    float temp = parse_expr_2();
[2171]220                    value = value - floor(value/temp)*temp;
221                    break;
222                }
223            default:
224                return value;
[1894]225            }
[2171]226        };
227    }
228
[8351]229    float ExprParser::parse_expr_2()
[2171]230    {
[8351]231        float value = parse_expr_1();
[2171]232        while (*reading_stream != '\0')
233        {
234            op = parse_binary_operator();
235            switch (op)
[1894]236            {
[2171]237            case hoch:
238                value = pow(value,parse_expr_1());
239                break;
240            default:
241                return value;
[1894]242            }
[2171]243        };
244        op = undef;
245        return value;
246    }
247
[8351]248    float ExprParser::parse_expr_1()
[2171]249    {
250        PARSE_BLANKS;
[8351]251        float value;
[2171]252
253        unary_operator op = parse_unary_operator();
254        PARSE_BLANKS;
255
256        if (*reading_stream == '\0')
257        {
258            // end of string
259            this->failed_ = true;
260            return 0;
261        }
[3196]262        else if ((*reading_stream > 47 && *reading_stream < 59) || *reading_stream == 46)
[2171]263        {  // number
[8351]264            value = (float)strtod(reading_stream, const_cast<char**>(&reading_stream));
[2171]265        }
[3196]266        else if ((*reading_stream > 64 && *reading_stream < 91) || (*reading_stream > 96 && *reading_stream < 123) || *reading_stream == 46)
[2171]267        {  // variable or function
268            char* word = new char[256];
269            parse_word(word);
270            PARSE_BLANKS;
271            if (*reading_stream == '(')
[1894]272            {
[2171]273                ++reading_stream;
274#define SWITCH word
275                CASE_1("sin")
276                    value = sin(parse_last_argument());
277                CASE("asin")
278                    value = asin(parse_last_argument());
279                CASE("sinh")
280                    value = sinh(parse_last_argument());
281                CASE("asinh")
282                {
283                    value = parse_last_argument();
284                    value = log(sqrt(pow(value, 2) + 1) + value);
285                }
286                CASE("cos")
287                    value = cos(parse_last_argument());
288                CASE("acos")
289                    value = acos(parse_last_argument());
290                CASE("cosh")
291                    value = cosh(parse_last_argument());
292                CASE("acosh")
293                {
294                    value = parse_last_argument();
295                    value = log(sqrt(pow(value, 2) - 1) + value);
296                }
297                CASE("tan")
298                    value = tan(parse_last_argument());
299                CASE("atan")
300                    value = atan(parse_last_argument());
301                CASE("atan2")
302                    value = atan2(parse_argument(),parse_last_argument());
303                CASE("tanh")
304                    value = tanh(parse_last_argument());
305                CASE("atanh")
306                {
307                    value = parse_last_argument();
[8351]308                    value = 0.5f*log((value + 1.0f)/(value - 1.0f));
[2171]309                }
310                CASE("int")
311                    value = floor(parse_last_argument());
312                CASE("floor")
313                    value = floor(parse_last_argument());
314                CASE("ceil")
315                    value = ceil(parse_last_argument());
316                CASE("abs")
317                    value = fabs(parse_last_argument());
318                CASE("exp")
319                    value = exp(parse_last_argument());
320                CASE("log")
321                    value = log10(parse_last_argument());
322                CASE("ln")
323                    value = log(parse_last_argument());
324                CASE("sign")
325                {
326                    value = parse_last_argument();
[8351]327                    value = (value>0.0f ? 1.0f : (value<0.0f ? -1.0f : 0.0f));
[2171]328                }
329                CASE("sqrt")
330                    value = sqrt(parse_last_argument());
331                CASE("degrees")
[8351]332                    value = parse_last_argument()*180.0f/math::pi;
[2171]333                CASE("radians")
[8351]334                    value = parse_last_argument()*math::pi/180.0f;
[2171]335                CASE("mod")
336                {
337                    value = parse_argument();
[8351]338                    float value2 = parse_last_argument();
[2171]339                    value = value - floor(value/value2)*value2;
340                }
341                CASE("pow")
342                    value = pow(parse_argument(),parse_last_argument());
343                CASE("div")
344                    value = floor(parse_argument()/parse_last_argument());
345                CASE("max")
346                    value = std::max(parse_argument(),parse_last_argument());
347                CASE("min")
348                    value = std::min(parse_argument(),parse_last_argument());
349                CASE_ELSE
350                {
351                    this->failed_ = true;
352                    delete[] word;
353                    return 0;
354                }
[1894]355            }
[2171]356            else
[1894]357            {
[8351]358                std::map<std::string, float>::const_iterator it = this->variables_.find(word);
[6417]359                if (it != this->variables_.end())
360                    value = it->second;
361                else
[2171]362                {
363                    this->failed_ = true;
364                    delete[] word;
365                    return 0;
366                }
[1894]367            }
[2171]368            delete[] word;
[1894]369        }
[2171]370        else if (*reading_stream == 40)
[6417]371        {  // expression in parenthesis
[2171]372            ++reading_stream;
373            value = parse_last_argument();
374        }
[1894]375        else
376        {
[2171]377            this->failed_ = true;
378            return 0;
[1894]379        }
[1505]380
[2171]381        PARSE_BLANKS;
382        switch (op)
[1894]383        {
[2171]384        case u_nicht: return !value;
385        case u_plus:  return  value;
386        case u_minus: return -value;
387        default:
[1894]388            this->failed_ = true;
[2171]389            return 0;
[1894]390        }
[2171]391    }
[1505]392
[11071]393    void ExprParser::parse_word(char* str)
[1894]394    {
[2171]395        char* word = str;
396        int counter = 0;
[3196]397        while ((*reading_stream > 47 && *reading_stream < 58) || (*reading_stream > 64 && *reading_stream < 91) || (*reading_stream > 96 && *reading_stream < 123) || *reading_stream == 46)
[2171]398        {
399            *word++ = *reading_stream++;
400            counter++;
401            if (counter > 255)
402            {
403                this->failed_ = true;
[11071]404                return;
[2171]405            }
406        };
407        *word = '\0';
[1894]408    }
[2171]409
410    ExprParser::binary_operator ExprParser::parse_binary_operator()
[1894]411    {
[2171]412        binary_operator op;
413        switch (*reading_stream)
[1894]414        {
[2171]415        case '+': op = b_plus; break;
416        case '-': op = b_minus; break;
417        case '*': op = mal; break;
418        case '/': op = durch; break;
419        case '^': op = hoch; break;
420        case '%': op = modulo; break;
421        case '&': op = und; break;
422        case '|': op = oder; break;
423        case '=': op = gleich; break;
424        case '!': op = b_nicht; break;
425        case '<': op = kleiner; break;
426        case '>': op = groesser; break;
427        default: return undef;
[1894]428        }
[2171]429        if (*++reading_stream == '=')
[1894]430        {
[2171]431            if (op > 9)
432            {
433                ++reading_stream;
434                return (binary_operator)(op + 3);
435            }
436            else
437            {
438                --reading_stream;
439                return undef;
440            }
[1894]441        }
[2171]442        else
443            return op;
[1894]444    }
[1505]445
[2171]446    ExprParser::unary_operator ExprParser::parse_unary_operator()
[1894]447    {
[2171]448        switch (*reading_stream)
449        {
450        case '!':
451            ++reading_stream;
452            return u_nicht;
453        case '+':
454            ++reading_stream;
455            return u_plus;
456        case '-':
457            ++reading_stream;
458            return u_minus;
459        default :
460            return u_plus;
461        }
[1894]462    }
[1505]463}
Note: See TracBrowser for help on using the repository browser.