Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pch/src/util/ExprParser.cc @ 3146

Last change on this file since 3146 was 3146, checked in by rgrieder, 15 years ago

Found another few unnecessary includes in util (and added two others that followed due to this change).

  • Property svn:eol-style set to native
File size: 12.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
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*/
33
34#include "ExprParser.h"
35#include <cmath>
36#include <cstring>
37#include <cstdlib>
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
45#define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream
46
47namespace orxonox
48{
49    ExprParser::ExprParser(const std::string& str)
50    {
51        this->failed_ = false;
52        this->reading_stream = str.c_str();
53        if (str.size() == 0 || *reading_stream == '\0')
54        {
55            this->failed_ = true;
56            this->result_ = 0.0;
57        }
58        else
59        {
60            this->result_ = parse_expr_8();
61            this->remains_ = reading_stream;
62        }
63    }
64
65    //Private functions:
66    /******************/
67    double ExprParser::parse_argument()
68    {
69        double value = parse_expr_8();
70        if (*reading_stream == ',')
71        {
72            ++reading_stream;
73            return value;
74        }
75        else
76        {
77            this->failed_ = true;
78            return 0;
79        }
80    }
81
82    double ExprParser::parse_last_argument()
83    {
84        double value = parse_expr_8();
85        if (*reading_stream == ')')
86        {
87            ++reading_stream;
88            return value;
89        }
90        else
91        {
92            this->failed_ = true;
93            return 0;
94        }
95    }
96
97    double ExprParser::parse_expr_8()
98    {
99        double value = parse_expr_7();
100        for(;;)
101        {
102            switch (op)
103            {
104            case oder:
105                value = parse_expr_7() || value;
106                break;
107            default: return value;
108            }
109        };
110    }
111
112
113    double ExprParser::parse_expr_7()
114    {
115        double value = parse_expr_6();
116        for(;;)
117        {
118            switch (op)
119            {
120            case und:
121                value = value && parse_expr_6();
122                break;
123            default: return value;
124            }
125        };
126    }
127
128    double ExprParser::parse_expr_6()
129    {
130        double value = parse_expr_5();
131        for(;;)
132        {
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    }
146
147    double ExprParser::parse_expr_5()
148    {
149        double value = parse_expr_4();
150        for(;;)
151        {
152            switch (op)
153            {
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;
168            }
169        };
170    }
171
172    double ExprParser::parse_expr_4()
173    {
174        double value = parse_expr_3();
175        for(;;)
176        {
177            switch (op)
178            {
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;
187            }
188        };
189    }
190
191    double ExprParser::parse_expr_3()
192    {
193        double value = parse_expr_2();
194        for(;;)
195        {
196            switch (op)
197            {
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;
212            }
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)
223            {
224            case hoch:
225                value = pow(value,parse_expr_1());
226                break;
227            default:
228                return value;
229            }
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        }
249        else if (*reading_stream > 47 && *reading_stream < 59 || *reading_stream == 46)
250        {  // number
251            value = strtod(reading_stream, const_cast<char**>(&reading_stream));
252        }
253        else if (*reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46)
254        {  // variable or function
255            char* word = new char[256];
256            parse_word(word);
257            PARSE_BLANKS;
258            if (*reading_stream == '(')
259            {
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                }
342            }
343            else
344            {
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                }
356            }
357            delete[] word;
358        }
359        else if (*reading_stream == 40)
360        {  // expresion in paranthesis
361            ++reading_stream;
362            value = parse_last_argument();
363        }
364        else
365        {
366            this->failed_ = true;
367            return 0;
368        }
369
370        PARSE_BLANKS;
371        switch (op)
372        {
373        case u_nicht: return !value;
374        case u_plus:  return  value;
375        case u_minus: return -value;
376        default:
377            this->failed_ = true;
378            return 0;
379        }
380    }
381
382    char* ExprParser::parse_word(char* str)
383    {
384        char* word = str;
385        int counter = 0;
386        while (*reading_stream > 47 && *reading_stream < 58 || *reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46)
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;
398    }
399
400    ExprParser::binary_operator ExprParser::parse_binary_operator()
401    {
402        binary_operator op;
403        switch (*reading_stream)
404        {
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;
418        }
419        if (*++reading_stream == '=')
420        {
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            }
431        }
432        else
433            return op;
434    }
435
436    ExprParser::unary_operator ExprParser::parse_unary_operator()
437    {
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        }
452    }
453}
Note: See TracBrowser for help on using the repository browser.