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 %} 14 15 %define api.pure full 16 17 %parse-param { double *final_val } 18 %parse-param { struct expr_parse_ctx *ctx } 19 %parse-param {void *scanner} 20 %lex-param {void* scanner} 21 22 %union { 23 double num; 24 char *str; 25 } 26 27 %token EXPR_PARSE EXPR_OTHER EXPR_ERROR 28 %token <num> NUMBER 29 %token <str> ID 30 %destructor { free ($$); } <str> 31 %token MIN MAX IF ELSE SMT_ON 32 %left MIN MAX IF 33 %left '|' 34 %left '^' 35 %left '&' 36 %left '-' '+' 37 %left '*' '/' '%' 38 %left NEG NOT 39 %type <num> expr if_expr 40 41 %{ 42 static void expr_error(double *final_val __maybe_unused, 43 struct expr_parse_ctx *ctx __maybe_unused, 44 void *scanner, 45 const char *s) 46 { 47 pr_debug("%s\n", s); 48 } 49 50 %} 51 %% 52 53 start: 54 EXPR_PARSE all_expr 55 | 56 EXPR_OTHER all_other 57 58 all_other: all_other other 59 | 60 61 other: ID 62 { 63 expr__add_id(ctx, $1, 0.0); 64 } 65 | 66 MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' 67 68 69 all_expr: if_expr { *final_val = $1; } 70 ; 71 72 if_expr: 73 expr IF expr ELSE expr { $$ = $3 ? $1 : $5; } 74 | expr 75 ; 76 77 expr: NUMBER 78 | ID { if (expr__get_id(ctx, $1, &$$)) { 79 pr_debug("%s not found\n", $1); 80 free($1); 81 YYABORT; 82 } 83 free($1); 84 } 85 | expr '|' expr { $$ = (long)$1 | (long)$3; } 86 | expr '&' expr { $$ = (long)$1 & (long)$3; } 87 | expr '^' expr { $$ = (long)$1 ^ (long)$3; } 88 | expr '+' expr { $$ = $1 + $3; } 89 | expr '-' expr { $$ = $1 - $3; } 90 | expr '*' expr { $$ = $1 * $3; } 91 | expr '/' expr { if ($3 == 0) { 92 pr_debug("division by zero\n"); 93 YYABORT; 94 } 95 $$ = $1 / $3; 96 } 97 | expr '%' expr { if ((long)$3 == 0) { 98 pr_debug("division by zero\n"); 99 YYABORT; 100 } 101 $$ = (long)$1 % (long)$3; 102 } 103 | '-' expr %prec NEG { $$ = -$2; } 104 | '(' if_expr ')' { $$ = $2; } 105 | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } 106 | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } 107 | SMT_ON { $$ = smt_on() > 0; } 108 ; 109 110 %% 111