1 /* Simple expression parser */ 2 %{ 3 #define YYDEBUG 1 4 #include <stdio.h> 5 #include "util.h" 6 #include "util/debug.h" 7 #include <stdlib.h> // strtod() 8 #define IN_EXPR_Y 1 9 #include "expr.h" 10 #include "smt.h" 11 #include <string.h> 12 13 static double d_ratio(double val0, double val1) 14 { 15 if (val1 == 0) { 16 return 0; 17 } 18 return val0 / val1; 19 } 20 21 %} 22 23 %define api.pure full 24 25 %parse-param { double *final_val } 26 %parse-param { struct expr_parse_ctx *ctx } 27 %parse-param {void *scanner} 28 %lex-param {void* scanner} 29 30 %union { 31 double num; 32 char *str; 33 } 34 35 %token EXPR_PARSE EXPR_OTHER EXPR_ERROR 36 %token <num> NUMBER 37 %token <str> ID 38 %destructor { free ($$); } <str> 39 %token MIN MAX IF ELSE SMT_ON D_RATIO 40 %left MIN MAX IF 41 %left '|' 42 %left '^' 43 %left '&' 44 %left '<' '>' 45 %left '-' '+' 46 %left '*' '/' '%' 47 %left NEG NOT 48 %type <num> expr if_expr 49 50 %{ 51 static void expr_error(double *final_val __maybe_unused, 52 struct expr_parse_ctx *ctx __maybe_unused, 53 void *scanner, 54 const char *s) 55 { 56 pr_debug("%s\n", s); 57 } 58 59 %} 60 %% 61 62 start: 63 EXPR_PARSE all_expr 64 | 65 EXPR_OTHER all_other 66 67 all_other: all_other other 68 | 69 70 other: ID 71 { 72 expr__add_id(ctx, $1); 73 } 74 | 75 MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' 76 | 77 '<' | '>' | D_RATIO 78 79 all_expr: if_expr { *final_val = $1; } 80 ; 81 82 if_expr: 83 expr IF expr ELSE expr { $$ = $3 ? $1 : $5; } 84 | expr 85 ; 86 87 expr: NUMBER 88 | ID { 89 struct expr_id_data *data; 90 91 if (expr__resolve_id(ctx, $1, &data)) { 92 free($1); 93 YYABORT; 94 } 95 96 $$ = data->val; 97 free($1); 98 } 99 | expr '|' expr { $$ = (long)$1 | (long)$3; } 100 | expr '&' expr { $$ = (long)$1 & (long)$3; } 101 | expr '^' expr { $$ = (long)$1 ^ (long)$3; } 102 | expr '<' expr { $$ = $1 < $3; } 103 | expr '>' expr { $$ = $1 > $3; } 104 | expr '+' expr { $$ = $1 + $3; } 105 | expr '-' expr { $$ = $1 - $3; } 106 | expr '*' expr { $$ = $1 * $3; } 107 | expr '/' expr { if ($3 == 0) { 108 pr_debug("division by zero\n"); 109 YYABORT; 110 } 111 $$ = $1 / $3; 112 } 113 | expr '%' expr { if ((long)$3 == 0) { 114 pr_debug("division by zero\n"); 115 YYABORT; 116 } 117 $$ = (long)$1 % (long)$3; 118 } 119 | '-' expr %prec NEG { $$ = -$2; } 120 | '(' if_expr ')' { $$ = $2; } 121 | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } 122 | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } 123 | SMT_ON { $$ = smt_on() > 0; } 124 | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); } 125 ; 126 127 %% 128