exp: fix shift/reduce conflict complaints
[fio.git] / exp / expression-parser.y
index dbd8b6c27c40bf58c598564a8ca2d9283edde74e..6ab6408874b829d2dffbf0ed6fa82ebc9558414d 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <stdio.h>
 #include <string.h>
 
 #include <stdio.h>
 #include <string.h>
-
+#include <math.h>
 struct parser_value_type {
        double dval;
        long long ival;
 struct parser_value_type {
        double dval;
        long long ival;
@@ -55,8 +55,12 @@ extern void yyrestart(FILE *file);
 
 %token <v> NUMBER
 %token <v> BYE
 
 %token <v> NUMBER
 %token <v> BYE
+%token <v> SUFFIX 
 %left '-' '+'
 %left '-' '+'
+%right SUFFIX
 %left '*' '/'
 %left '*' '/'
+%right '^'
+%left '%'
 %nonassoc UMINUS
 %parse-param { long long *result }
 %parse-param { double *dresult }
 %nonassoc UMINUS
 %parse-param { long long *result }
 %parse-param { double *dresult }
@@ -119,6 +123,59 @@ expression:        expression '+' expression {
                        $$.has_error = $2.has_error;
                }
        |       '(' expression ')' { $$ = $2; }
                        $$.has_error = $2.has_error;
                }
        |       '(' expression ')' { $$ = $2; }
+       |       expression SUFFIX {
+                       if (!$1.has_dval && !$2.has_dval)
+                               $$.ival = $1.ival * $2.ival;
+                       else
+                               $$.ival = (long long) $1.dval * $2.dval;
+                       if ($1.has_dval || $2.has_dval)
+                               $$.dval = $1.dval * $2.dval;
+                       else
+                               $$.dval = $1.ival * $2.ival;
+                       $$.has_error = $1.has_error || $2.has_error;
+               }
+       |       expression '%' expression {
+                       if ($1.has_dval || $3.has_dval)
+                               yyerror(0, 0, 0, 0, "modulo on floats");
+                       if ($3.ival == 0)
+                               yyerror(0, 0, 0, 0, "divide by zero");
+                       else {
+                               $$.ival = $1.ival % $3.ival;
+                               $$.dval = $$.ival;
+                       }
+                       $$.has_error = $1.has_error || $3.has_error;
+               }
+       |       expression '^' expression {
+                       $$.has_error = $1.has_error || $3.has_error;
+                       if (!$1.has_dval && !$3.has_dval) {
+                               int i;
+
+                               if ($3.ival == 0) {
+                                       $$.ival = 1;
+                               } else if ($3.ival > 0) {
+                                       long long tmp = $1.ival;
+                                       $$.ival = 1.0;
+                                       for (i = 0; i < $3.ival; i++)
+                                               $$.ival *= tmp;
+                               }  else {
+                                       /* integers, 2^-3, ok, we now have doubles */
+                                       double tmp;
+                                       if ($1.ival == 0 && $3.ival == 0) {
+                                               tmp = 1.0;
+                                               $$.has_error = 1;
+                                       } else {
+                                               double x = (double) $1.ival;
+                                               double y = (double) $3.ival;
+                                               tmp = pow(x, y);
+                                       }
+                                       $$.ival = (long long) tmp;
+                               }
+                               $$.dval = pow($1.dval, $3.dval);
+                       } else {
+                               $$.dval = pow($1.dval, $3.dval);
+                               $$.ival = (long long) $$.dval;
+                       }
+               }
        |       NUMBER { $$ = $1; }
        |       BYE { $$ = $1; *bye = 1; };
 %%
        |       NUMBER { $$ = $1; }
        |       BYE { $$ = $1; *bye = 1; };
 %%