| %{ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| #include "sqlhist-parse.h" |
| |
| #define scanner sb->scanner |
| |
| extern int yylex(YYSTYPE *yylval, void *); |
| extern void yyerror(struct sqlhist_bison *, char *fmt, ...); |
| |
| #define CHECK_RETURN_PTR(x) \ |
| do { \ |
| if (!(x)) { \ |
| printf("FAILED MEMORY: %s\n", #x); \ |
| return -ENOMEM; \ |
| } \ |
| } while (0) |
| |
| #define CHECK_RETURN_VAL(x) \ |
| do { \ |
| if ((x) < 0) { \ |
| printf("FAILED MEMORY: %s\n", #x); \ |
| return -ENOMEM; \ |
| } \ |
| } while (0) |
| |
| %} |
| |
| %define api.pure |
| |
| /* Change the globals to use tracefs_ prefix */ |
| %define api.prefix{tracefs_} |
| %code provides |
| { |
| #define YYSTYPE TRACEFS_STYPE |
| #define yylex tracefs_lex |
| #define yyerror tracefs_error |
| } |
| |
| %lex-param {void *scanner} |
| %parse-param {struct sqlhist_bison *sb} |
| |
| %union { |
| int s32; |
| char *string; |
| long number; |
| void *expr; |
| } |
| |
| %token AS SELECT FROM JOIN ON WHERE PARSE_ERROR CAST |
| %token <number> NUMBER field_type |
| %token <string> STRING |
| %token <string> FIELD |
| %token <string> LE GE EQ NEQ AND OR |
| |
| %left '+' '-' |
| %left '*' '/' |
| %left '<' '>' |
| %left AND OR |
| |
| %type <string> name label |
| |
| %type <expr> selection_expr field item named_field |
| %type <expr> selection_addition |
| %type <expr> compare compare_list compare_cmds compare_items |
| %type <expr> compare_and_or |
| %type <expr> str_val val |
| |
| %% |
| |
| start : |
| select_statement |
| ; |
| |
| label : AS name { CHECK_RETURN_PTR($$ = store_str(sb, $2)); } |
| | name { CHECK_RETURN_PTR($$ = store_str(sb, $1)); } |
| ; |
| |
| select : SELECT { table_start(sb); } |
| ; |
| |
| select_statement : |
| select selection_list table_exp |
| ; |
| |
| selection_list : |
| selection |
| | selection ',' selection_list |
| ; |
| |
| selection : |
| selection_expr |
| { |
| CHECK_RETURN_VAL(add_selection(sb, $1, NULL)); |
| } |
| | selection_expr label |
| { |
| CHECK_RETURN_VAL(add_selection(sb, $1, $2)); |
| } |
| ; |
| |
| selection_expr : |
| field |
| | '(' field ')' { $$ = $2; } |
| | selection_addition |
| | '(' selection_addition ')' { $$ = $2; } |
| | CAST '(' field AS FIELD ')' { |
| $$ = add_cast(sb, $3, $5); |
| CHECK_RETURN_PTR($$); |
| } |
| ; |
| |
| selection_addition : |
| field '+' field |
| { |
| $$ = add_compare(sb, $1, $3, COMPARE_ADD); |
| CHECK_RETURN_PTR($$); |
| } |
| | field '-' field |
| { |
| $$ = add_compare(sb, $1, $3, COMPARE_SUB); |
| CHECK_RETURN_PTR($$); |
| } |
| ; |
| |
| item : |
| named_field |
| | field |
| ; |
| |
| field : |
| FIELD { $$ = add_field(sb, $1, NULL); CHECK_RETURN_PTR($$); } |
| ; |
| |
| named_field : |
| FIELD label { $$ = add_field(sb, $1, $2); CHECK_RETURN_PTR($$); } |
| ; |
| |
| name : |
| FIELD |
| ; |
| |
| str_val : |
| STRING { $$ = add_string(sb, $1); CHECK_RETURN_PTR($$); } |
| ; |
| |
| val : |
| str_val |
| | NUMBER { $$ = add_number(sb, $1); CHECK_RETURN_PTR($$); } |
| ; |
| |
| |
| compare : |
| field '<' val { $$ = add_filter(sb, $1, $3, FILTER_LT); CHECK_RETURN_PTR($$); } |
| | field '>' val { $$ = add_filter(sb, $1, $3, FILTER_GT); CHECK_RETURN_PTR($$); } |
| | field LE val { $$ = add_filter(sb, $1, $3, FILTER_LE); CHECK_RETURN_PTR($$); } |
| | field GE val { $$ = add_filter(sb, $1, $3, FILTER_GE); CHECK_RETURN_PTR($$); } |
| | field '=' val { $$ = add_filter(sb, $1, $3, FILTER_EQ); CHECK_RETURN_PTR($$); } |
| | field EQ val { $$ = add_filter(sb, $1, $3, FILTER_EQ); CHECK_RETURN_PTR($$); } |
| | field NEQ val { $$ = add_filter(sb, $1, $3, FILTER_NE); CHECK_RETURN_PTR($$); } |
| | field "!=" val { $$ = add_filter(sb, $1, $3, FILTER_NE); CHECK_RETURN_PTR($$); } |
| | field '&' val { $$ = add_filter(sb, $1, $3, FILTER_BIN_AND); CHECK_RETURN_PTR($$); } |
| | field '~' str_val { $$ = add_filter(sb, $1, $3, FILTER_STR_CMP); CHECK_RETURN_PTR($$); } |
| ; |
| |
| compare_and_or : |
| compare_and_or OR compare_and_or { $$ = add_filter(sb, $1, $3, FILTER_OR); CHECK_RETURN_PTR($$); } |
| | compare_and_or AND compare_and_or { $$ = add_filter(sb, $1, $3, FILTER_AND); CHECK_RETURN_PTR($$); } |
| | '!' '(' compare_and_or ')' { $$ = add_filter(sb, $3, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); } |
| | '!' compare { $$ = add_filter(sb, $2, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); } |
| | compare |
| ; |
| |
| compare_items : |
| compare_items OR compare_items { $$ = add_filter(sb, $1, $3, FILTER_OR); CHECK_RETURN_PTR($$); } |
| | '(' compare_and_or ')' { $$ = add_filter(sb, $2, NULL, FILTER_GROUP); CHECK_RETURN_PTR($$); } |
| | '!' '(' compare_and_or ')' { $$ = add_filter(sb, $3, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); } |
| | '!' compare { $$ = add_filter(sb, $2, NULL, FILTER_NOT_GROUP); CHECK_RETURN_PTR($$); } |
| | compare |
| ; |
| |
| compare_cmds : |
| compare_items { CHECK_RETURN_VAL(add_where(sb, $1)); } |
| ; |
| |
| /* |
| * Top level AND is equal to ',' but the compare_cmds in them must |
| * all be of for the same event (start or end exclusive). |
| * That is, OR is not to be used between start and end events. |
| */ |
| compare_list : |
| compare_cmds |
| | compare_cmds ',' compare_list |
| | compare_cmds AND compare_list |
| ; |
| |
| where_clause : |
| WHERE compare_list |
| ; |
| |
| opt_where_clause : |
| /* empty */ |
| | where_clause |
| ; |
| |
| opt_join_clause : |
| /* empty set */ |
| | join_clause |
| ; |
| |
| table_exp : |
| from_clause opt_join_clause opt_where_clause |
| ; |
| |
| from_clause : |
| FROM item { CHECK_RETURN_VAL(add_from(sb, $2)); } |
| |
| /* |
| * Select from a from clause confuses the variable parsing. |
| * disable it for now. |
| |
| | FROM '(' select_statement ')' label |
| { |
| from_table_end($5); |
| $$ = store_printf("FROM (%s) AS %s", $3, $5); |
| } |
| */ |
| ; |
| |
| join_clause : |
| JOIN item ON match_clause { add_to(sb, $2); } |
| ; |
| |
| match : |
| item '=' item { CHECK_RETURN_VAL(add_match(sb, $1, $3)); } |
| | item EQ item { CHECK_RETURN_VAL(add_match(sb, $1, $3)); } |
| |
| ; |
| |
| match_clause : |
| match |
| | match ',' match_clause |
| ; |
| |
| %% |