Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/util/ExprParser.cc @ 4070

Last change on this file since 4070 was 3196, checked in by rgrieder, 16 years ago

Merged pch branch back to trunk.

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