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