2017-03-20 13:17:05 -07:00
/* Simple expression parser */
%{
2020-02-28 10:36:13 +01:00
#define YYDEBUG 1
#include <stdio.h>
2017-03-20 13:17:05 -07:00
#include "util.h"
#include "util/debug.h"
2019-08-29 16:18:59 -03:00
#include <stdlib.h> // strtod()
2017-03-20 13:17:05 -07:00
#define IN_EXPR_Y 1
#include "expr.h"
2017-08-11 16:26:23 -07:00
#include "smt.h"
2017-03-20 13:17:05 -07:00
#include <string.h>
2020-06-10 16:58:22 -07:00
static double d_ratio(double val0, double val1)
{
if (val1 == 0) {
return 0;
}
return val0 / val1;
}
2017-03-20 13:17:05 -07:00
%}
2020-01-12 20:22:59 +01:00
%define api.pure full
2017-03-20 13:17:05 -07:00
%parse-param { double *final_val }
2020-04-02 02:03:34 +05:30
%parse-param { struct expr_parse_ctx *ctx }
2020-02-28 10:36:13 +01:00
%parse-param {void *scanner}
%lex-param {void* scanner}
2017-03-20 13:17:05 -07:00
%union {
2020-02-28 10:36:13 +01:00
double num;
char *str;
2017-03-20 13:17:05 -07:00
}
2020-02-28 10:36:13 +01:00
%token EXPR_PARSE EXPR_OTHER EXPR_ERROR
2017-03-20 13:17:05 -07:00
%token <num> NUMBER
2020-02-28 10:36:13 +01:00
%token <str> ID
2020-05-12 17:03:18 -07:00
%destructor { free ($$); } <str>
2020-06-10 16:58:22 -07:00
%token MIN MAX IF ELSE SMT_ON D_RATIO
2017-08-11 16:26:23 -07:00
%left MIN MAX IF
2017-03-20 13:17:05 -07:00
%left '|'
%left '^'
%left '&'
2020-06-10 16:58:23 -07:00
%left '<' '>'
2017-03-20 13:17:05 -07:00
%left '-' '+'
%left '*' '/' '%'
%left NEG NOT
2017-08-11 16:26:23 -07:00
%type <num> expr if_expr
2017-03-20 13:17:05 -07:00
%{
2020-02-28 10:36:13 +01:00
static void expr_error(double *final_val __maybe_unused,
2020-04-02 02:03:34 +05:30
struct expr_parse_ctx *ctx __maybe_unused,
2020-02-28 10:36:13 +01:00
void *scanner,
2017-03-20 13:17:05 -07:00
const char *s)
{
pr_debug("%s\n", s);
}
%}
%%
2020-02-28 10:36:13 +01:00
start:
EXPR_PARSE all_expr
|
EXPR_OTHER all_other
all_other: all_other other
|
other: ID
{
2020-07-19 20:13:03 +02:00
expr__add_id(ctx, $1);
2020-02-28 10:36:13 +01:00
}
|
2020-05-01 10:33:25 -07:00
MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ','
2020-06-10 16:58:22 -07:00
|
2020-06-10 16:58:23 -07:00
'<' | '>' | D_RATIO
2020-02-28 10:36:13 +01:00
2017-08-11 16:26:23 -07:00
all_expr: if_expr { *final_val = $1; }
;
if_expr:
expr IF expr ELSE expr { $$ = $3 ? $1 : $5; }
| expr
2017-03-20 13:17:05 -07:00
;
expr: NUMBER
2020-07-19 20:13:04 +02:00
| ID {
struct expr_id_data *data;
2020-07-19 20:13:12 +02:00
if (expr__resolve_id(ctx, $1, &data)) {
2020-07-19 20:13:04 +02:00
free($1);
YYABORT;
}
2020-07-19 20:13:12 +02:00
2020-08-26 08:30:55 -07:00
$$ = expr_id_data__value(data);
2020-05-12 17:03:18 -07:00
free($1);
2017-03-20 13:17:05 -07:00
}
2017-08-11 16:26:23 -07:00
| expr '|' expr { $$ = (long)$1 | (long)$3; }
| expr '&' expr { $$ = (long)$1 & (long)$3; }
| expr '^' expr { $$ = (long)$1 ^ (long)$3; }
2020-06-10 16:58:23 -07:00
| expr '<' expr { $$ = $1 < $3; }
| expr '>' expr { $$ = $1 > $3; }
2017-03-20 13:17:05 -07:00
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
2020-05-01 10:33:31 -07:00
| expr '/' expr { if ($3 == 0) {
pr_debug("division by zero\n");
YYABORT;
}
$$ = $1 / $3;
}
| expr '%' expr { if ((long)$3 == 0) {
pr_debug("division by zero\n");
YYABORT;
}
$$ = (long)$1 % (long)$3;
}
2017-03-20 13:17:05 -07:00
| '-' expr %prec NEG { $$ = -$2; }
2017-08-11 16:26:23 -07:00
| '(' if_expr ')' { $$ = $2; }
| MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
| MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
| SMT_ON { $$ = smt_on() > 0; }
2020-06-10 16:58:22 -07:00
| D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); }
2017-03-20 13:17:05 -07:00
;
%%