xref: /openbmc/linux/tools/perf/util/expr.y (revision c924e0cc0576b4e45b9c495174cd785aa41d51ad)
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