xref: /aosp_15_r20/external/libtracefs/src/sqlhist.y (revision 287e80b3a36113050663245e7f2c00d274188f18)
1 %{
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 
7 #include "sqlhist-parse.h"
8 
9 #define scanner sb->scanner
10 
11 extern int yylex(YYSTYPE *yylval, void *);
12 extern void yyerror(struct sqlhist_bison *, char *fmt, ...);
13 
14 #define CHECK_RETURN_PTR(x)					\
15 	do {							\
16 		if (!(x)) {					\
17 			printf("FAILED MEMORY: %s\n", #x);	\
18 			return -ENOMEM;				\
19 		}						\
20 	} while (0)
21 
22 #define CHECK_RETURN_VAL(x)					\
23 	do {							\
24 		if ((x) < 0) {					\
25 			printf("FAILED MEMORY: %s\n", #x);	\
26 			return -ENOMEM;				\
27 		}						\
28 	} while (0)
29 
30 %}
31 
32 %define api.pure
33 
34 /* Change the globals to use tracefs_ prefix */
35 %define api.prefix{tracefs_}
36 %code provides
37 {
38   #define YYSTYPE TRACEFS_STYPE
39   #define yylex tracefs_lex
40   #define yyerror tracefs_error
41 }
42 
43 %lex-param {void *scanner}
44 %parse-param {struct sqlhist_bison *sb}
45 
46 %union {
47 	int	s32;
48 	char	*string;
49 	long	number;
50 	void	*expr;
51 }
52 
53 %token AS SELECT FROM JOIN ON WHERE PARSE_ERROR CAST
54 %token <number> NUMBER field_type
55 %token <string> STRING
56 %token <string> FIELD
57 %token <string> LE GE EQ NEQ AND OR
58 
59 %left '+' '-'
60 %left '*' '/'
61 %left '<' '>'
62 %left AND OR
63 
64 %type <string> name label
65 
66 %type <expr>  selection_expr field item named_field
67 %type <expr>  selection_addition
68 %type <expr>  compare compare_list compare_cmds compare_items
69 %type <expr>  compare_and_or
70 %type <expr>  str_val val
71 
72 %%
73 
74 start :
75    select_statement
76  ;
77 
78 label : AS name { CHECK_RETURN_PTR($$ = store_str(sb, $2)); }
79  | name { CHECK_RETURN_PTR($$ = store_str(sb, $1)); }
80  ;
81 
82 select : SELECT  { table_start(sb); }
83   ;
84 
85 select_statement :
86     select selection_list table_exp
87   ;
88 
89 selection_list :
90    selection
91  | selection ',' selection_list
92  ;
93 
94 selection :
95     selection_expr
96 				{
97 					CHECK_RETURN_VAL(add_selection(sb, $1, NULL));
98 				}
99   | selection_expr label
100 				{
101 					CHECK_RETURN_VAL(add_selection(sb, $1, $2));
102 				}
103   ;
104 
105 selection_expr :
106    field
107  | '(' field ')'		{  $$ = $2; }
108  | selection_addition
109  | '(' selection_addition ')'	{  $$ = $2; }
110  | CAST '(' field AS FIELD ')'	{
111 					 $$ = add_cast(sb, $3, $5);
112 					 CHECK_RETURN_PTR($$);
113 				}
114  ;
115 
116 selection_addition :
117    field '+' field
118 				{
119 					$$ = add_compare(sb, $1, $3, COMPARE_ADD);
120 					CHECK_RETURN_PTR($$);
121 				}
122  | field '-' field
123 				{
124 					$$ = add_compare(sb, $1, $3, COMPARE_SUB);
125 					CHECK_RETURN_PTR($$);
126 				}
127  ;
128 
129 item :
130    named_field
131  | field
132  ;
133 
134 field :
135    FIELD	{ $$ = add_field(sb, $1, NULL); CHECK_RETURN_PTR($$); }
136  ;
137 
138 named_field :
139    FIELD label { $$ = add_field(sb, $1, $2); CHECK_RETURN_PTR($$); }
140  ;
141 
142 name :
143    FIELD
144  ;
145 
146 str_val :
147    STRING	{ $$ = add_string(sb, $1); CHECK_RETURN_PTR($$); }
148  ;
149 
150 val :
151    str_val
152  | NUMBER	{ $$ = add_number(sb, $1); CHECK_RETURN_PTR($$); }
153  ;
154 
155 
156 compare :
157    field '<' val	{ $$ = add_filter(sb, $1, $3, FILTER_LT); CHECK_RETURN_PTR($$); }
158  | field '>' val	{ $$ = add_filter(sb, $1, $3, FILTER_GT); CHECK_RETURN_PTR($$); }
159  | field LE val	{ $$ = add_filter(sb, $1, $3, FILTER_LE); CHECK_RETURN_PTR($$); }
160  | field GE val	{ $$ = add_filter(sb, $1, $3, FILTER_GE); CHECK_RETURN_PTR($$); }
161  | field '=' val	{ $$ = add_filter(sb, $1, $3, FILTER_EQ); CHECK_RETURN_PTR($$); }
162  | field EQ val	{ $$ = add_filter(sb, $1, $3, FILTER_EQ); CHECK_RETURN_PTR($$); }
163  | field NEQ val	{ $$ = add_filter(sb, $1, $3, FILTER_NE); CHECK_RETURN_PTR($$); }
164  | field "!=" val	{ $$ = add_filter(sb, $1, $3, FILTER_NE); CHECK_RETURN_PTR($$); }
165  | field '&' val	{ $$ = add_filter(sb, $1, $3, FILTER_BIN_AND); CHECK_RETURN_PTR($$); }
166  | field '~' str_val	{ $$ = add_filter(sb, $1, $3, FILTER_STR_CMP); CHECK_RETURN_PTR($$); }
167 ;
168 
169 compare_and_or :
170    compare_and_or OR compare_and_or	{ $$ = add_filter(sb, $1, $3, FILTER_OR); CHECK_RETURN_PTR($$); }
171  | compare_and_or AND compare_and_or	{ $$ = add_filter(sb, $1, $3, FILTER_AND); CHECK_RETURN_PTR($$); }
172  | '!' '(' compare_and_or ')'		{ $$ = add_filter(sb, $3, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); }
173  | '!' compare				{ $$ = add_filter(sb, $2, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); }
174  | compare
175  ;
176 
177 compare_items :
178    compare_items OR compare_items	{ $$ = add_filter(sb, $1, $3, FILTER_OR); CHECK_RETURN_PTR($$); }
179  | '(' compare_and_or ')'		{ $$ = add_filter(sb, $2, NULL, FILTER_GROUP); CHECK_RETURN_PTR($$); }
180  | '!' '(' compare_and_or ')'		{ $$ = add_filter(sb, $3, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); }
181  | '!' compare				{ $$ = add_filter(sb, $2, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); }
182  | compare
183  ;
184 
185 compare_cmds :
186    compare_items		{ CHECK_RETURN_VAL(add_where(sb, $1)); }
187  ;
188 
189 /*
190  * Top level AND is equal to ',' but the compare_cmds in them must
191  * all be of for the same event (start or end exclusive).
192  * That is, OR is not to be used between start and end events.
193  */
194 compare_list :
195    compare_cmds
196  | compare_cmds ',' compare_list
197  | compare_cmds AND compare_list
198  ;
199 
200 where_clause :
201    WHERE compare_list
202  ;
203 
204 opt_where_clause :
205    /* empty */
206  | where_clause
207 ;
208 
209 opt_join_clause :
210   /* empty set */
211   | join_clause
212  ;
213 
214 table_exp :
215    from_clause opt_join_clause opt_where_clause
216  ;
217 
218 from_clause :
219    FROM item		{ CHECK_RETURN_VAL(add_from(sb, $2)); }
220 
221 /*
222  * Select from a from clause confuses the variable parsing.
223  * disable it for now.
224 
225    | FROM '(' select_statement ')' label
226 				{
227 					from_table_end($5);
228 					$$ = store_printf("FROM (%s) AS %s", $3, $5);
229 				}
230 */
231  ;
232 
233 join_clause :
234  JOIN item ON match_clause	{ add_to(sb, $2); }
235  ;
236 
237 match :
238    item '=' item { CHECK_RETURN_VAL(add_match(sb, $1, $3)); }
239  | item EQ item { CHECK_RETURN_VAL(add_match(sb, $1, $3)); }
240 
241  ;
242 
243 match_clause :
244    match
245  | match ',' match_clause
246  ;
247 
248 %%
249