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