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 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 %token MIN MAX IF ELSE SMT_ON 31 %left MIN MAX IF 32 %left '|' 33 %left '^' 34 %left '&' 35 %left '-' '+' 36 %left '*' '/' '%' 37 %left NEG NOT 38 %type <num> expr if_expr 39 40 %{ 41 static void expr_error(double *final_val __maybe_unused, 42 struct parse_ctx *ctx __maybe_unused, 43 void *scanner, 44 const char *s) 45 { 46 pr_debug("%s\n", s); 47 } 48 49 static int lookup_id(struct parse_ctx *ctx, char *id, double *val) 50 { 51 int i; 52 53 for (i = 0; i < ctx->num_ids; i++) { 54 if (!strcasecmp(ctx->ids[i].name, id)) { 55 *val = ctx->ids[i].val; 56 return 0; 57 } 58 } 59 return -1; 60 } 61 62 %} 63 %% 64 65 start: 66 EXPR_PARSE all_expr 67 | 68 EXPR_OTHER all_other 69 70 all_other: all_other other 71 | 72 73 other: ID 74 { 75 if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) { 76 pr_err("failed: way too many variables"); 77 YYABORT; 78 } 79 80 ctx->ids[ctx->num_ids++].name = $1; 81 } 82 | 83 MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' 84 85 86 all_expr: if_expr { *final_val = $1; } 87 ; 88 89 if_expr: 90 expr IF expr ELSE expr { $$ = $3 ? $1 : $5; } 91 | expr 92 ; 93 94 expr: NUMBER 95 | ID { if (lookup_id(ctx, $1, &$$) < 0) { 96 pr_debug("%s not found\n", $1); 97 YYABORT; 98 } 99 } 100 | expr '|' expr { $$ = (long)$1 | (long)$3; } 101 | expr '&' expr { $$ = (long)$1 & (long)$3; } 102 | expr '^' expr { $$ = (long)$1 ^ (long)$3; } 103 | expr '+' expr { $$ = $1 + $3; } 104 | expr '-' expr { $$ = $1 - $3; } 105 | expr '*' expr { $$ = $1 * $3; } 106 | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; } 107 | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; } 108 | '-' expr %prec NEG { $$ = -$2; } 109 | '(' if_expr ')' { $$ = $2; } 110 | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } 111 | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } 112 | SMT_ON { $$ = smt_on() > 0; } 113 ; 114 115 %% 116