Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10111 was 8351, checked in by rgrieder, 14 years ago

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

  • No support for CEGUI 0.5, Ogre 1.4 and boost 1.35 - 1.39 any more
  • In game console is not working in main menu for CEGUI 0.7
  • Tolua (just the C lib, not the application) and CEGUILua libraries are no longer in our repository. —> You will need to get these as well when compiling Orxonox
  • And of course lots of new bugs we don't yet know about
  • Property svn:eol-style set to native
File size: 12.6 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
36#include <cmath>
37#include <cstring>
38#include <cstdlib>
39#include "Math.h"
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
47#define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream
48
49namespace orxonox
50{
51    ExprParser::ExprParser()
52    {
53        this->failed_ = false;
54        this->variables_["pi"] = math::pi;
55        this->variables_["e"] = math::e;
56    }
57
58    void ExprParser::setVariable(const std::string& varname, float value)
59    {
60        this->variables_[varname] = value;
61    }
62
63    void ExprParser::parse(const std::string& str)
64    {
65        this->reading_stream = str.c_str();
66        if (str.size() == 0 || *reading_stream == '\0')
67        {
68            this->failed_ = true;
69            this->result_ = 0.0;
70        }
71        else
72        {
73            this->result_ = parse_expr_8();
74            this->remains_ = reading_stream;
75        }
76    }
77
78    //Private functions:
79    /******************/
80    float ExprParser::parse_argument()
81    {
82        float value = parse_expr_8();
83        if (*reading_stream == ',')
84        {
85            ++reading_stream;
86            return value;
87        }
88        else
89        {
90            this->failed_ = true;
91            return 0;
92        }
93    }
94
95    float ExprParser::parse_last_argument()
96    {
97        float value = parse_expr_8();
98        if (*reading_stream == ')')
99        {
100            ++reading_stream;
101            return value;
102        }
103        else
104        {
105            this->failed_ = true;
106            return 0;
107        }
108    }
109
110    float ExprParser::parse_expr_8()
111    {
112        float value = parse_expr_7();
113        for(;;)
114        {
115            switch (op)
116            {
117            case oder:
118                value = parse_expr_7() || value;
119                break;
120            default: return value;
121            }
122        };
123    }
124
125
126    float ExprParser::parse_expr_7()
127    {
128        float value = parse_expr_6();
129        for(;;)
130        {
131            switch (op)
132            {
133            case und:
134                value = value && parse_expr_6();
135                break;
136            default: return value;
137            }
138        };
139    }
140
141    float ExprParser::parse_expr_6()
142    {
143        float value = parse_expr_5();
144        for(;;)
145        {
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    }
159
160    float ExprParser::parse_expr_5()
161    {
162        float value = parse_expr_4();
163        for(;;)
164        {
165            switch (op)
166            {
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;
181            }
182        };
183    }
184
185    float ExprParser::parse_expr_4()
186    {
187        float value = parse_expr_3();
188        for(;;)
189        {
190            switch (op)
191            {
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;
200            }
201        };
202    }
203
204    float ExprParser::parse_expr_3()
205    {
206        float value = parse_expr_2();
207        for(;;)
208        {
209            switch (op)
210            {
211            case mal:
212                value *= parse_expr_2();
213                break;
214            case durch:
215                value /= parse_expr_2();
216                break;
217            case modulo:
218                {
219                    float temp = parse_expr_2();
220                    value = value - floor(value/temp)*temp;
221                    break;
222                }
223            default:
224                return value;
225            }
226        };
227    }
228
229    float ExprParser::parse_expr_2()
230    {
231        float value = parse_expr_1();
232        while (*reading_stream != '\0')
233        {
234            op = parse_binary_operator();
235            switch (op)
236            {
237            case hoch:
238                value = pow(value,parse_expr_1());
239                break;
240            default:
241                return value;
242            }
243        };
244        op = undef;
245        return value;
246    }
247
248    float ExprParser::parse_expr_1()
249    {
250        PARSE_BLANKS;
251        float value;
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        }
262        else if ((*reading_stream > 47 && *reading_stream < 59) || *reading_stream == 46)
263        {  // number
264            value = (float)strtod(reading_stream, const_cast<char**>(&reading_stream));
265        }
266        else if ((*reading_stream > 64 && *reading_stream < 91) || (*reading_stream > 96 && *reading_stream < 123) || *reading_stream == 46)
267        {  // variable or function
268            char* word = new char[256];
269            parse_word(word);
270            PARSE_BLANKS;
271            if (*reading_stream == '(')
272            {
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();
308                    value = 0.5f*log((value + 1.0f)/(value - 1.0f));
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();
327                    value = (value>0.0f ? 1.0f : (value<0.0f ? -1.0f : 0.0f));
328                }
329                CASE("sqrt")
330                    value = sqrt(parse_last_argument());
331                CASE("degrees")
332                    value = parse_last_argument()*180.0f/math::pi;
333                CASE("radians")
334                    value = parse_last_argument()*math::pi/180.0f;
335                CASE("mod")
336                {
337                    value = parse_argument();
338                    float value2 = parse_last_argument();
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                }
355            }
356            else
357            {
358                std::map<std::string, float>::const_iterator it = this->variables_.find(word);
359                if (it != this->variables_.end())
360                    value = it->second;
361                else
362                {
363                    this->failed_ = true;
364                    delete[] word;
365                    return 0;
366                }
367            }
368            delete[] word;
369        }
370        else if (*reading_stream == 40)
371        {  // expression in parenthesis
372            ++reading_stream;
373            value = parse_last_argument();
374        }
375        else
376        {
377            this->failed_ = true;
378            return 0;
379        }
380
381        PARSE_BLANKS;
382        switch (op)
383        {
384        case u_nicht: return !value;
385        case u_plus:  return  value;
386        case u_minus: return -value;
387        default:
388            this->failed_ = true;
389            return 0;
390        }
391    }
392
393    char* ExprParser::parse_word(char* str)
394    {
395        char* word = str;
396        int counter = 0;
397        while ((*reading_stream > 47 && *reading_stream < 58) || (*reading_stream > 64 && *reading_stream < 91) || (*reading_stream > 96 && *reading_stream < 123) || *reading_stream == 46)
398        {
399            *word++ = *reading_stream++;
400            counter++;
401            if (counter > 255)
402            {
403                this->failed_ = true;
404                return '\0';
405            }
406        };
407        *word = '\0';
408        return str;
409    }
410
411    ExprParser::binary_operator ExprParser::parse_binary_operator()
412    {
413        binary_operator op;
414        switch (*reading_stream)
415        {
416        case '+': op = b_plus; break;
417        case '-': op = b_minus; break;
418        case '*': op = mal; break;
419        case '/': op = durch; break;
420        case '^': op = hoch; break;
421        case '%': op = modulo; break;
422        case '&': op = und; break;
423        case '|': op = oder; break;
424        case '=': op = gleich; break;
425        case '!': op = b_nicht; break;
426        case '<': op = kleiner; break;
427        case '>': op = groesser; break;
428        default: return undef;
429        }
430        if (*++reading_stream == '=')
431        {
432            if (op > 9)
433            {
434                ++reading_stream;
435                return (binary_operator)(op + 3);
436            }
437            else
438            {
439                --reading_stream;
440                return undef;
441            }
442        }
443        else
444            return op;
445    }
446
447    ExprParser::unary_operator ExprParser::parse_unary_operator()
448    {
449        switch (*reading_stream)
450        {
451        case '!':
452            ++reading_stream;
453            return u_nicht;
454        case '+':
455            ++reading_stream;
456            return u_plus;
457        case '-':
458            ++reading_stream;
459            return u_minus;
460        default :
461            return u_plus;
462        }
463    }
464}
Note: See TracBrowser for help on using the repository browser.