Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/archive/tutorialHS08/src/util/ExprParser.cc

Last change on this file was 1639, checked in by rgrieder, 16 years ago

merged nico's fixes for gcc 4.3 back to trunk.
I'm not going to delete branch yet.

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