#include <stdio.h>
#include <string.h>
-
+#include <math.h>
struct parser_value_type {
double dval;
long long ival;
%token <v> NUMBER
%token <v> BYE
+%token <v> SUFFIX
%left '-' '+'
+%right SUFFIX
%left '*' '/'
+%right '^'
+%left '%'
%nonassoc UMINUS
%parse-param { long long *result }
%parse-param { double *dresult }
$$.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; };
%%