Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/input/src/util/FloatParser.cpp @ 1113

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

here we go

File size: 11.9 KB
Line 
1//FloatParser.cpp
2
3#include "FloatParser.h"
4#include <string>
5#include <cmath>
6#include <cstring>
7
8using namespace std;
9
10//Makros, um Funktionen einfacher parser zu können
11#define CASE_1(var) if (!strcmp(SWITCH,var))
12#define CASE(var) else if (!strcmp(SWITCH,var))
13#define CASE_ELSE else
14
15#define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream;
16
17//static enumerations and variables
18static enum binary_operator { b_plus, b_minus, mal, durch, modulo, hoch, undef, oder, und, gleich, b_nicht, kleiner, groesser, ungleich, kleinergleich, groessergleich};
19static enum unary_operator { u_plus, u_minus, u_nicht };
20static binary_operator op;
21static char* reading_stream;
22static bool parse_float_failed = false;
23
24//static funtions
25static double parse_expr_1();
26static double parse_expr_2();
27static double parse_expr_3();
28static double parse_expr_4();
29static double parse_expr_5();
30static double parse_expr_6();
31static double parse_expr_7();
32static double parse_expr_8();
33static inline char* parse_word(char* str);
34static inline binary_operator parse_binary_operator();
35static inline unary_operator parse_unary_operator();
36static double parse_argument();
37static double parse_last_argument();
38
39//Public functions:
40/******************/
41bool parse_float(char* const string, char **endptr, double* result)
42{
43   parse_float_failed = false;
44   reading_stream = string;
45   double value = parse_expr_8();
46   if ( !parse_float_failed && (
47      *reading_stream == ')' || \
48      *reading_stream == '}' || \
49      *reading_stream == ']' || \
50      *reading_stream == ',' || \
51      *reading_stream == ';' || \
52      *reading_stream == '_' || \
53      *reading_stream == '\0' || \
54      *reading_stream > 64 && *reading_stream < 91 || \
55      *reading_stream > 96 && *reading_stream < 123))
56   {
57      endptr = &reading_stream;
58      *result = value;
59      return true;
60   }
61   else
62   {
63     *result = 0;
64     return false;
65   }
66}
67
68bool parse_float(char* const string, char** endptr, char delimiter, double* result)
69{
70   parse_float_failed = false;
71   reading_stream = string;
72   double value = parse_expr_8();
73   if (*reading_stream == delimiter && !parse_float_failed)
74   {
75      endptr = &reading_stream;
76      *result = value;
77      return true;
78   }
79   else
80   {
81     *result = 0;
82     return false;
83   }
84}
85
86bool parse_vector_float(char* const string, char** endptr, bool last_float, double* result)
87{
88   parse_float_failed = false;
89   reading_stream = string;
90   double value = parse_expr_4();
91   if (last_float)
92   {
93      if (*reading_stream == '>')
94      {
95         endptr = &reading_stream;
96         *result = value;
97      }
98      else
99        parse_float_failed = true;
100   }
101   else
102   {
103      if (*reading_stream == ',')
104      {
105         *endptr = reading_stream;
106         *result = value;
107      }
108      else
109        parse_float_failed = true;
110   }
111   if (parse_float_failed)
112   {
113     *result = 0;
114     return false;
115   }
116   else
117     return true;
118}
119
120//Private functions:
121/******************/
122static double parse_argument()
123{
124   double value = parse_expr_8();
125   if (*reading_stream == ',')
126   {
127      ++reading_stream;
128      return value;
129   }
130   else
131   {
132     parse_float_failed = true;
133     return 0;
134   }
135}
136
137static double parse_last_argument()
138{
139   double value = parse_expr_8();
140   if (*reading_stream == ')')
141   {
142      ++reading_stream;
143      return value;
144   }
145   else
146   {
147     parse_float_failed = true;
148     return 0;
149   }
150}
151
152static double parse_expr_8()
153{
154   double value = parse_expr_7();
155   for(;;)
156   {
157      switch (op)
158      {
159         case oder:
160            value = parse_expr_7() || value;
161            break;
162         default: return value;
163      }
164   };
165}
166
167
168static double parse_expr_7()
169{
170   double value = parse_expr_6();
171   for(;;)
172   {
173      switch (op)
174      {
175         case und:
176            value = value && parse_expr_6();
177            break;
178         default: return value;
179      }
180   };
181}
182
183static double parse_expr_6()
184{
185   double value = parse_expr_5();
186   for(;;)
187   {
188      switch (op)
189      {
190         case gleich:
191            value = (value == parse_expr_5());
192            break;
193         case ungleich:
194            value = (value != parse_expr_5());
195            break;
196         default:
197            return value;
198      }
199   };
200}
201
202static double parse_expr_5()
203{
204   double value = parse_expr_4();
205   for(;;)
206   {
207      switch (op)
208      {
209         case kleiner:
210            value = (value < parse_expr_4());
211            break;
212         case kleinergleich:
213            value = (value <= parse_expr_4());
214            break;
215         case groesser:
216            value = (value > parse_expr_4());
217            break;
218         case groessergleich:
219            value = (value >= parse_expr_4());
220            break;
221         default:
222            return value;
223      }
224   };
225}
226
227static double parse_expr_4()
228{
229   double value = parse_expr_3();
230   for(;;)
231   {
232      switch (op)
233      {
234         case b_plus:
235            value += parse_expr_3();
236            break;
237         case b_minus:
238            value -= parse_expr_3();
239            break;
240         default:
241            return value;
242      }
243   };
244}
245
246static double parse_expr_3()
247{
248   double value = parse_expr_2();
249   for(;;)
250   {
251      switch (op)
252      {
253         case mal:
254            value *= parse_expr_2();
255            break;
256         case durch:
257            value /= parse_expr_2();
258            break;
259         case modulo:
260         {
261            double temp = parse_expr_2();
262            value = value - floor(value/temp)*temp;
263            break;
264         }
265         default:
266            return value;
267      }
268   };
269}
270
271static double parse_expr_2()
272{
273   double value = parse_expr_1();
274   while (*reading_stream != '\0')
275   {
276      op = parse_binary_operator();
277      switch (op)
278      {
279         case hoch:
280            value = pow(value,parse_expr_1());
281            break;
282         default:
283            return value;
284      }
285   };
286   op = undef;
287   return value;
288}
289
290static double parse_expr_1()
291{
292   PARSE_BLANKS
293   double value;
294   
295   unary_operator op = parse_unary_operator();
296   PARSE_BLANKS
297
298   if (*reading_stream == '\0')
299   {
300     // end of string
301     parse_float_failed = true;
302     return 0;
303   }
304   else if (*reading_stream > 47 && *reading_stream < 59 || *reading_stream == 46)
305   {  //Zahl
306      value = strtod(reading_stream,&reading_stream);
307   }
308   else if (*reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46)
309   {  //Variable oder Funktion
310      char* word = new char[256];
311      parse_word(word);
312      PARSE_BLANKS
313      if (*reading_stream == '(')
314      {
315         ++reading_stream;
316#define SWITCH word
317         CASE_1("sin")
318            value = sin(parse_last_argument());
319         CASE("asin")
320            value = asin(parse_last_argument());
321         CASE("sinh")
322            value = sinh(parse_last_argument());
323         CASE("asinh")
324         {
325            value = parse_last_argument();
326            value = log(sqrt(pow(value, 2) + 1) + value);
327         }
328         CASE("cos")
329            value = cos(parse_last_argument());
330         CASE("acos")
331            value = acos(parse_last_argument());
332         CASE("cosh")
333            value = cosh(parse_last_argument());
334         CASE("acosh")
335         {
336            value = parse_last_argument();
337            value = log(sqrt(pow(value, 2) - 1) + value);
338         }
339         CASE("tan")
340            value = tan(parse_last_argument());
341         CASE("atan")
342            value = atan(parse_last_argument());
343         CASE("atan2")
344            value = atan2(parse_argument(),parse_last_argument());
345         CASE("tanh")
346            value = tanh(parse_last_argument());
347         CASE("atanh")
348         {
349            value = parse_last_argument();
350            value = 0.5*log((value + 1)/(value - 1));
351         }
352         CASE("int")
353            value = floor(parse_last_argument());
354         CASE("floor")
355            value = floor(parse_last_argument());
356         CASE("ceil")
357            value = ceil(parse_last_argument());
358         CASE("abs")
359            value = abs(parse_last_argument());
360         CASE("exp")
361            value = exp(parse_last_argument());
362         CASE("log")
363            value = log10(parse_last_argument());
364         CASE("ln")
365            value = log(parse_last_argument());
366         CASE("sign")
367         {
368            value = parse_last_argument();
369            value = (value>0 ? 1 : (value<0 ? -1 : 0));
370         }
371         CASE("sqrt")
372            value = sqrt(parse_last_argument());
373         CASE("degrees")
374            value = parse_last_argument()*180/3.1415926535897932;
375         CASE("radians")
376            value = parse_last_argument()*3.1415926535897932/180;
377         CASE("mod")
378         {
379            value = parse_argument();
380            double value2 = parse_last_argument();
381            value = value - floor(value/value2)*value2;
382         }
383         CASE("pow")
384            value = pow(parse_argument(),parse_last_argument());
385         CASE("div")
386            value = floor(parse_argument()/parse_last_argument());
387         CASE("max")
388            value = max(parse_argument(),parse_last_argument());
389         CASE("min")
390            value = min(parse_argument(),parse_last_argument());
391         CASE_ELSE
392         {
393           parse_float_failed = true;
394           return 0;
395         }
396      }
397      else
398      {
399         //TODO: Variablen-Liste durchsuchen
400         //Momentaner Ersatzwert für jede Variable:
401         //value = 0;
402         parse_float_failed = true;
403         return 0;
404      }
405      delete[] word;
406   }
407   else if (*reading_stream == 40)
408   {  //Audruck in Klammern
409      ++reading_stream;
410      value = parse_last_argument();
411   }
412   else
413   {
414     parse_float_failed = true;
415     return 0;
416   }
417 
418   PARSE_BLANKS
419   switch (op)
420   {
421      case u_nicht: return !value;
422      case u_plus:  return  value;
423      case u_minus: return -value;
424      default:
425        {
426          parse_float_failed = true;
427          return 0;
428        }
429   }
430}
431
432static inline char* parse_word(char* str)
433{
434   char* word = str;
435   int counter = 0;
436   while (*reading_stream > 47 && *reading_stream < 58 || *reading_stream > 64 && *reading_stream < 91 || *reading_stream > 96 && *reading_stream < 123 || *reading_stream == 46)
437   {
438      *word++ = *reading_stream++;
439      counter++;
440      if (counter > 255)
441      {
442        parse_float_failed = true;
443        return '\0';
444      }
445   };
446   *word = '\0';
447   return str;
448}
449
450static inline binary_operator parse_binary_operator()
451{
452   binary_operator op;
453   switch (*reading_stream)
454   {
455      case '+': op = b_plus; break;
456      case '-': op = b_minus; break;
457      case '*': op = mal; break;
458      case '/': op = durch; break;
459      case '^': op = hoch; break;
460      case '%': op = modulo; break;
461      case '&': op = und; break;
462      case '|': op = oder; break;
463      case '=': op = gleich; break;
464      case '!': op = b_nicht; break;
465      case '<': op = kleiner; break;
466      case '>': op = groesser; break;
467      default: return undef;
468   }
469   if (*++reading_stream == '=')
470   {
471      if (op > 9)
472      {
473         ++reading_stream;
474         return (binary_operator)(op + 3);
475      }
476      else
477      {
478         --reading_stream;
479         return undef;
480      }
481   }
482   else
483      return op;
484}
485
486static inline unary_operator parse_unary_operator()
487{
488   switch (*reading_stream)
489   {
490      case '!':
491         ++reading_stream;
492         return u_nicht;
493      case '+':
494         ++reading_stream;
495         return u_plus;
496      case '-':
497         ++reading_stream;
498         return u_minus;
499      default :
500         return u_plus;
501   }
502}
Note: See TracBrowser for help on using the repository browser.