107516736SAndi Kleen /* Simple expression parser */ 207516736SAndi Kleen %{ 326226a97SJiri Olsa #define YYDEBUG 1 4edfe7f55SIan Rogers #include <math.h> 507516736SAndi Kleen #include "util/debug.h" 67f8fdcbbSIan Rogers #include "smt.h" 707516736SAndi Kleen #define IN_EXPR_Y 1 807516736SAndi Kleen #include "expr.h" 907516736SAndi Kleen %} 1007516736SAndi Kleen 11fc8c0a99SJiri Olsa %define api.pure full 12fc8c0a99SJiri Olsa 1307516736SAndi Kleen %parse-param { double *final_val } 14aecce63eSJiri Olsa %parse-param { struct expr_parse_ctx *ctx } 1526226a97SJiri Olsa %parse-param {void *scanner} 1626226a97SJiri Olsa %lex-param {void* scanner} 1707516736SAndi Kleen 1807516736SAndi Kleen %union { 1907516736SAndi Kleen double num; 2026226a97SJiri Olsa char *str; 2107516736SAndi Kleen } 2207516736SAndi Kleen 23aed0d6f8SIan Rogers %token ID NUMBER MIN MAX IF ELSE SMT_ON D_RATIO EXPR_ERROR EXPR_PARSE EXPR_OTHER 24d73bad06SAndi Kleen %left MIN MAX IF 2507516736SAndi Kleen %left '|' 2607516736SAndi Kleen %left '^' 2707516736SAndi Kleen %left '&' 28ff1a12f9SIan Rogers %left '<' '>' 2907516736SAndi Kleen %left '-' '+' 3007516736SAndi Kleen %left '*' '/' '%' 3107516736SAndi Kleen %left NEG NOT 32aed0d6f8SIan Rogers %type <num> NUMBER 33aed0d6f8SIan Rogers %type <str> ID 34aed0d6f8SIan Rogers %destructor { free ($$); } <str> 35d73bad06SAndi Kleen %type <num> expr if_expr 3607516736SAndi Kleen 3707516736SAndi Kleen %{ 3826226a97SJiri Olsa static void expr_error(double *final_val __maybe_unused, 39aecce63eSJiri Olsa struct expr_parse_ctx *ctx __maybe_unused, 4026226a97SJiri Olsa void *scanner, 4107516736SAndi Kleen const char *s) 4207516736SAndi Kleen { 4307516736SAndi Kleen pr_debug("%s\n", s); 4407516736SAndi Kleen } 4507516736SAndi Kleen 46e87576c5SIan Rogers #define BINARY_LONG_OP(RESULT, OP, LHS, RHS) \ 47e87576c5SIan Rogers RESULT = (long)LHS OP (long)RHS; 48e87576c5SIan Rogers 49e87576c5SIan Rogers #define BINARY_OP(RESULT, OP, LHS, RHS) \ 50e87576c5SIan Rogers RESULT = LHS OP RHS; 51e87576c5SIan Rogers 5207516736SAndi Kleen %} 5307516736SAndi Kleen %% 5407516736SAndi Kleen 5526226a97SJiri Olsa start: 5626226a97SJiri Olsa EXPR_PARSE all_expr 5726226a97SJiri Olsa | 5826226a97SJiri Olsa EXPR_OTHER all_other 5926226a97SJiri Olsa 6026226a97SJiri Olsa all_other: all_other other 6126226a97SJiri Olsa | 6226226a97SJiri Olsa 6326226a97SJiri Olsa other: ID 6426226a97SJiri Olsa { 65332603c2SJiri Olsa expr__add_id(ctx, $1); 6626226a97SJiri Olsa } 6726226a97SJiri Olsa | 68cb59fa79SIan Rogers MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' 693e21a28aSIan Rogers | 70ff1a12f9SIan Rogers '<' | '>' | D_RATIO 7126226a97SJiri Olsa 72d73bad06SAndi Kleen all_expr: if_expr { *final_val = $1; } 73d73bad06SAndi Kleen 74*c924e0ccSIan Rogers if_expr: expr IF expr ELSE expr 75*c924e0ccSIan Rogers { 76*c924e0ccSIan Rogers $$ = $3 ? $1 : $5; 77*c924e0ccSIan Rogers } 78d73bad06SAndi Kleen | expr 7907516736SAndi Kleen ; 8007516736SAndi Kleen 8107516736SAndi Kleen expr: NUMBER 82*c924e0ccSIan Rogers { 83*c924e0ccSIan Rogers $$ = $1; 84*c924e0ccSIan Rogers } 85*c924e0ccSIan Rogers | ID 86*c924e0ccSIan Rogers { 875c5f5e83SJiri Olsa struct expr_id_data *data; 885c5f5e83SJiri Olsa 89edfe7f55SIan Rogers $$ = NAN; 90edfe7f55SIan Rogers if (expr__resolve_id(ctx, $1, &data) == 0) 9129396cd5SIan Rogers $$ = expr_id_data__value(data); 92edfe7f55SIan Rogers 9363657578SIan Rogers free($1); 9407516736SAndi Kleen } 95e87576c5SIan Rogers | expr '|' expr { BINARY_LONG_OP($$, |, $1, $3); } 96e87576c5SIan Rogers | expr '&' expr { BINARY_LONG_OP($$, &, $1, $3); } 97e87576c5SIan Rogers | expr '^' expr { BINARY_LONG_OP($$, ^, $1, $3); } 98e87576c5SIan Rogers | expr '<' expr { BINARY_OP($$, <, $1, $3); } 99e87576c5SIan Rogers | expr '>' expr { BINARY_OP($$, >, $1, $3); } 100e87576c5SIan Rogers | expr '+' expr { BINARY_OP($$, +, $1, $3); } 101e87576c5SIan Rogers | expr '-' expr { BINARY_OP($$, -, $1, $3); } 102e87576c5SIan Rogers | expr '*' expr { BINARY_OP($$, *, $1, $3); } 103*c924e0ccSIan Rogers | expr '/' expr 104*c924e0ccSIan Rogers { 105*c924e0ccSIan Rogers if ($3 == 0) { 1069be27a5dSIan Rogers pr_debug("division by zero\n"); 1079be27a5dSIan Rogers YYABORT; 1089be27a5dSIan Rogers } 1099be27a5dSIan Rogers $$ = $1 / $3; 1109be27a5dSIan Rogers } 111*c924e0ccSIan Rogers | expr '%' expr 112*c924e0ccSIan Rogers { 113*c924e0ccSIan Rogers if ((long)$3 == 0) { 1149be27a5dSIan Rogers pr_debug("division by zero\n"); 1159be27a5dSIan Rogers YYABORT; 1169be27a5dSIan Rogers } 1179be27a5dSIan Rogers $$ = (long)$1 % (long)$3; 1189be27a5dSIan Rogers } 119*c924e0ccSIan Rogers | D_RATIO '(' expr ',' expr ')' 120*c924e0ccSIan Rogers { 121*c924e0ccSIan Rogers if ($5 == 0) { 1227f8fdcbbSIan Rogers $$ = 0; 1237f8fdcbbSIan Rogers } else { 1247f8fdcbbSIan Rogers $$ = $3 / $5; 1257f8fdcbbSIan Rogers } 1267f8fdcbbSIan Rogers } 127*c924e0ccSIan Rogers | '-' expr %prec NEG 128*c924e0ccSIan Rogers { 129*c924e0ccSIan Rogers $$ = -$2; 130*c924e0ccSIan Rogers } 131*c924e0ccSIan Rogers | '(' if_expr ')' 132*c924e0ccSIan Rogers { 133*c924e0ccSIan Rogers $$ = $2; 134*c924e0ccSIan Rogers } 135*c924e0ccSIan Rogers | MIN '(' expr ',' expr ')' 136*c924e0ccSIan Rogers { 137*c924e0ccSIan Rogers $$ = $3 < $5 ? $3 : $5; 138*c924e0ccSIan Rogers } 139*c924e0ccSIan Rogers | MAX '(' expr ',' expr ')' 140*c924e0ccSIan Rogers { 141*c924e0ccSIan Rogers $$ = $3 > $5 ? $3 : $5; 142*c924e0ccSIan Rogers } 143*c924e0ccSIan Rogers | SMT_ON 144*c924e0ccSIan Rogers { 145*c924e0ccSIan Rogers $$ = smt_on() > 0 ? 1.0 : 0.0; 146*c924e0ccSIan Rogers } 14707516736SAndi Kleen ; 14807516736SAndi Kleen 14907516736SAndi Kleen %% 150