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