xref: /linux/tools/perf/util/expr.l (revision cea0f76a483d1270ac6f6513964e3e75193dda48)
1 %option prefix="expr_"
2 %option reentrant
3 %option bison-bridge
4 
5 %{
6 #include <linux/compiler.h>
7 #include "expr.h"
8 #include "expr-bison.h"
9 
10 char *expr_get_text(yyscan_t yyscanner);
11 YYSTYPE *expr_get_lval(yyscan_t yyscanner);
12 
13 static double __value(YYSTYPE *yylval, char *str, int token)
14 {
15 	double num;
16 
17 	errno = 0;
18 	num = strtod(str, NULL);
19 	if (errno)
20 		return EXPR_ERROR;
21 
22 	yylval->num = num;
23 	return token;
24 }
25 
26 static int value(yyscan_t scanner)
27 {
28 	YYSTYPE *yylval = expr_get_lval(scanner);
29 	char *text = expr_get_text(scanner);
30 
31 	return __value(yylval, text, NUMBER);
32 }
33 
34 /*
35  * Allow @ instead of / to be able to specify pmu/event/ without
36  * conflicts with normal division.
37  */
38 static char *normalize(char *str, int runtime)
39 {
40 	char *ret = str;
41 	char *dst = str;
42 
43 	while (*str) {
44 		if (*str == '@')
45 			*dst++ = '/';
46 		else if (*str == '\\')
47 			*dst++ = *++str;
48 		 else if (*str == '?') {
49 			char *paramval;
50 			int i = 0;
51 			int size = asprintf(&paramval, "%d", runtime);
52 
53 			if (size < 0)
54 				*dst++ = '0';
55 			else {
56 				while (i < size)
57 					*dst++ = paramval[i++];
58 				free(paramval);
59 			}
60 		}
61 		else
62 			*dst++ = *str;
63 		str++;
64 	}
65 
66 	*dst = 0x0;
67 	return ret;
68 }
69 
70 static int str(yyscan_t scanner, int token, int runtime)
71 {
72 	YYSTYPE *yylval = expr_get_lval(scanner);
73 	char *text = expr_get_text(scanner);
74 
75 	yylval->str = normalize(strdup(text), runtime);
76 	if (!yylval->str)
77 		return EXPR_ERROR;
78 
79 	yylval->str = normalize(yylval->str, runtime);
80 	return token;
81 }
82 %}
83 
84 number		([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)
85 
86 sch		[-,=]
87 spec		\\{sch}
88 sym		[0-9a-zA-Z_\.:@?]+
89 symbol		({spec}|{sym})+
90 
91 %%
92 	struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
93 
94 	{
95 		int start_token = sctx->start_token;
96 
97 		if (sctx->start_token) {
98 			sctx->start_token = 0;
99 			return start_token;
100 		}
101 	}
102 
103 max		{ return MAX; }
104 min		{ return MIN; }
105 if		{ return IF; }
106 else		{ return ELSE; }
107 #smt_on		{ return SMT_ON; }
108 {number}	{ return value(yyscanner); }
109 {symbol}	{ return str(yyscanner, ID, sctx->runtime); }
110 "|"		{ return '|'; }
111 "^"		{ return '^'; }
112 "&"		{ return '&'; }
113 "-"		{ return '-'; }
114 "+"		{ return '+'; }
115 "*"		{ return '*'; }
116 "/"		{ return '/'; }
117 "%"		{ return '%'; }
118 "("		{ return '('; }
119 ")"		{ return ')'; }
120 ","		{ return ','; }
121 .		{ }
122 %%
123 
124 int expr_wrap(void *scanner __maybe_unused)
125 {
126 	return 1;
127 }
128