18c2ecf20Sopenharmony_ci/* Simple expression parser */
28c2ecf20Sopenharmony_ci%{
38c2ecf20Sopenharmony_ci#define YYDEBUG 1
48c2ecf20Sopenharmony_ci#include <stdio.h>
58c2ecf20Sopenharmony_ci#include "util.h"
68c2ecf20Sopenharmony_ci#include "util/debug.h"
78c2ecf20Sopenharmony_ci#include <stdlib.h> // strtod()
88c2ecf20Sopenharmony_ci#define IN_EXPR_Y 1
98c2ecf20Sopenharmony_ci#include "expr.h"
108c2ecf20Sopenharmony_ci#include "smt.h"
118c2ecf20Sopenharmony_ci#include <string.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cistatic double d_ratio(double val0, double val1)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	if (val1 == 0) {
168c2ecf20Sopenharmony_ci		return 0;
178c2ecf20Sopenharmony_ci	}
188c2ecf20Sopenharmony_ci	return  val0 / val1;
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci%}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci%define api.pure full
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci%parse-param { double *final_val }
268c2ecf20Sopenharmony_ci%parse-param { struct expr_parse_ctx *ctx }
278c2ecf20Sopenharmony_ci%parse-param {void *scanner}
288c2ecf20Sopenharmony_ci%lex-param {void* scanner}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci%union {
318c2ecf20Sopenharmony_ci	double	 num;
328c2ecf20Sopenharmony_ci	char	*str;
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci%token EXPR_PARSE EXPR_OTHER EXPR_ERROR
368c2ecf20Sopenharmony_ci%token <num> NUMBER
378c2ecf20Sopenharmony_ci%token <str> ID
388c2ecf20Sopenharmony_ci%destructor { free ($$); } <str>
398c2ecf20Sopenharmony_ci%token MIN MAX IF ELSE SMT_ON D_RATIO
408c2ecf20Sopenharmony_ci%left MIN MAX IF
418c2ecf20Sopenharmony_ci%left '|'
428c2ecf20Sopenharmony_ci%left '^'
438c2ecf20Sopenharmony_ci%left '&'
448c2ecf20Sopenharmony_ci%left '<' '>'
458c2ecf20Sopenharmony_ci%left '-' '+'
468c2ecf20Sopenharmony_ci%left '*' '/' '%'
478c2ecf20Sopenharmony_ci%left NEG NOT
488c2ecf20Sopenharmony_ci%type <num> expr if_expr
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci%{
518c2ecf20Sopenharmony_cistatic void expr_error(double *final_val __maybe_unused,
528c2ecf20Sopenharmony_ci		       struct expr_parse_ctx *ctx __maybe_unused,
538c2ecf20Sopenharmony_ci		       void *scanner,
548c2ecf20Sopenharmony_ci		       const char *s)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	pr_debug("%s\n", s);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci%}
608c2ecf20Sopenharmony_ci%%
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistart:
638c2ecf20Sopenharmony_ciEXPR_PARSE all_expr
648c2ecf20Sopenharmony_ci|
658c2ecf20Sopenharmony_ciEXPR_OTHER all_other
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ciall_other: all_other other
688c2ecf20Sopenharmony_ci|
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciother: ID
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	expr__add_id(ctx, $1);
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci|
758c2ecf20Sopenharmony_ciMIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ','
768c2ecf20Sopenharmony_ci|
778c2ecf20Sopenharmony_ci'<' | '>' | D_RATIO
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ciall_expr: if_expr			{ *final_val = $1; }
808c2ecf20Sopenharmony_ci	;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ciif_expr:
838c2ecf20Sopenharmony_ci	expr IF expr ELSE expr { $$ = $3 ? $1 : $5; }
848c2ecf20Sopenharmony_ci	| expr
858c2ecf20Sopenharmony_ci	;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciexpr:	  NUMBER
888c2ecf20Sopenharmony_ci	| ID			{
898c2ecf20Sopenharmony_ci					struct expr_id_data *data;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci					if (expr__resolve_id(ctx, $1, &data)) {
928c2ecf20Sopenharmony_ci						free($1);
938c2ecf20Sopenharmony_ci						YYABORT;
948c2ecf20Sopenharmony_ci					}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci					$$ = data->val;
978c2ecf20Sopenharmony_ci					free($1);
988c2ecf20Sopenharmony_ci				}
998c2ecf20Sopenharmony_ci	| expr '|' expr		{ $$ = (long)$1 | (long)$3; }
1008c2ecf20Sopenharmony_ci	| expr '&' expr		{ $$ = (long)$1 & (long)$3; }
1018c2ecf20Sopenharmony_ci	| expr '^' expr		{ $$ = (long)$1 ^ (long)$3; }
1028c2ecf20Sopenharmony_ci	| expr '<' expr		{ $$ = $1 < $3; }
1038c2ecf20Sopenharmony_ci	| expr '>' expr		{ $$ = $1 > $3; }
1048c2ecf20Sopenharmony_ci	| expr '+' expr		{ $$ = $1 + $3; }
1058c2ecf20Sopenharmony_ci	| expr '-' expr		{ $$ = $1 - $3; }
1068c2ecf20Sopenharmony_ci	| expr '*' expr		{ $$ = $1 * $3; }
1078c2ecf20Sopenharmony_ci	| expr '/' expr		{ if ($3 == 0) {
1088c2ecf20Sopenharmony_ci					pr_debug("division by zero\n");
1098c2ecf20Sopenharmony_ci					YYABORT;
1108c2ecf20Sopenharmony_ci				  }
1118c2ecf20Sopenharmony_ci				  $$ = $1 / $3;
1128c2ecf20Sopenharmony_ci	                        }
1138c2ecf20Sopenharmony_ci	| expr '%' expr		{ if ((long)$3 == 0) {
1148c2ecf20Sopenharmony_ci					pr_debug("division by zero\n");
1158c2ecf20Sopenharmony_ci					YYABORT;
1168c2ecf20Sopenharmony_ci				  }
1178c2ecf20Sopenharmony_ci				  $$ = (long)$1 % (long)$3;
1188c2ecf20Sopenharmony_ci	                        }
1198c2ecf20Sopenharmony_ci	| '-' expr %prec NEG	{ $$ = -$2; }
1208c2ecf20Sopenharmony_ci	| '(' if_expr ')'	{ $$ = $2; }
1218c2ecf20Sopenharmony_ci	| MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
1228c2ecf20Sopenharmony_ci	| MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
1238c2ecf20Sopenharmony_ci	| SMT_ON		 { $$ = smt_on() > 0; }
1248c2ecf20Sopenharmony_ci	| D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); }
1258c2ecf20Sopenharmony_ci	;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci%%
128