123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- %{
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <cjson/cJSON.h>
- #include <signal.h>
- extern int yylex();
- extern int yyparse();
- extern FILE* yyin;
- extern char* yytext;
- int yydebug=1;
- void yyerror(const char* s);
- cJSON* jroot;
- #define SIMPLE_OP_NODE(res, type, left, right) \
- fprintf(stderr, "SIMPLE_OP_NODE type: %s %s %s\n", (type), cJSON_Print(left), cJSON_Print(right)); \
- cJSON* node = cJSON_CreateObject(); \
- cJSON_AddStringToObject(node, "type", type); \
- cJSON_AddItemToObject(node, "left", left); \
- cJSON_AddItemToObject(node, "right", right); \
- res = node;
- #define SIMPLE_OP_NODE_ONLY_LEFT(res, type, left) \
- fprintf(stderr, "SIMPLE_OP_NODE_ONLY_LEFT type: %s %s %s\n", (type), cJSON_Print(left)); \
- cJSON* node = cJSON_CreateObject(); \
- cJSON_AddStringToObject(node, "type", type); \
- cJSON_AddItemToObject(node, "left", left); \
- res = node;
- #define SIMPLE_TYPE_VALUE_OBJECT(res, type_name, json_type_name, value) \
- cJSON* node = cJSON_CreateObject(); \
- cJSON_AddStringToObject(node, "type", #type_name); \
- cJSON_Add##json_type_name##ToObject(node, "value", value); \
- res = node;
- #define MEET(msg) fprintf(stderr, "MEET %s\n", #msg);
- #define MEET_VAR(msg, msg2) fprintf(stderr, "MEET %s %s\n", #msg, msg2);
- #define MEET_JSON(msg, msg2) MEET_VAR(msg, cJSON_Print(msg2));
- #define ADD_TO_ROOT(node) cJSON_AddItemToArray(jroot, node);
- %}
- %union {
- int iv;
- double fv;
- char* sv;
- cJSON* jv;
- int subtok;
- }
- %token IDENTIFIER
- %token SELECT FROM WHERE INSERT INTO VALUES DELETE UPDATE SET JOIN CREATE TABLE DROP
- %token AS ON
- %token AND OR NOT IN
- %token INT_V FLOAT_V STRING_V // 作为 value 出现的
- %token INT_T FLOAT_T STRING_T // 作为 字面量 type 出现的情况
- %token LPAREN RPAREN COMMA
- %token PRIMARY_KEY
- %token QUIT NEWLINE
- %type <iv> INT_V
- %type <fv> FLOAT_V
- %type <sv> STRING_V NOT table_name
- %type <sv> IDENTIFIER data_type PRIMARY_KEY col_options bin_cmp_op bin_logical_op unary_compare_op bin_contains_op
- %type <jv> create_definition create_col_list create_table_stmt data_value
- %type <jv> insert_stmt insert_list
- %type <jv> update_stmt update_list single_assign_item
- %type <jv> identifier identifier_or_const_value
- %type <jv> delete_stmt select_stmt select_item select_items drop_stmt
- %type <jv> compare_expr single_expr where_expr logical_expr negative_expr op_where_expr expr_list contains_expr
- %type <jv> op_join table_field column_name
- %type <jv> table_name_list
- %left OR
- %left AND
- %right NOT
- %nonassoc '=' '>' '<'
- // %left '+' '-'
- // %left '*' '/'
- %start statements
- %%
- statements: statement
- | statements statement
- ;
- statement: NEWLINE
- | QUIT {printf("bye!\n"); exit(0); }
- | sql_statement
- ;
- sql_statement: create_table_stmt NEWLINE {cJSON_AddItemToArray(jroot, $1);}
- | insert_stmt NEWLINE {cJSON_AddItemToArray(jroot, $1);}
- | update_stmt NEWLINE {cJSON_AddItemToArray(jroot, $1);}
- | delete_stmt NEWLINE {cJSON_AddItemToArray(jroot, $1);}
- | select_stmt NEWLINE {cJSON_AddItemToArray(jroot, $1);}
- | drop_stmt NEWLINE {cJSON_AddItemToArray(jroot, $1);}
- ;
- create_table_stmt: CREATE TABLE IDENTIFIER
- {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "create_stmt");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "cols", cJSON_CreateArray());
- $$ = node;
- }
- ;
- create_table_stmt: CREATE TABLE IDENTIFIER '(' create_col_list ')' {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "create_stmt");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "cols", $5);
- $$ = node;
- }
- ;
- create_col_list: create_definition {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$ = node;
- }
- | create_col_list ',' create_definition {
- cJSON_AddItemToArray($1, $3);
- $$ = $1;
- }
- ;
- create_definition: IDENTIFIER data_type col_options {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "create_column");
- cJSON_AddStringToObject(node, "column_name", $1);
- cJSON_AddStringToObject(node, "data_type", $2);
- if (strlen($3) > 0){
- cJSON_AddTrueToObject(node, "primary_key");
- } else {
- cJSON_AddFalseToObject(node, "primary_key");
- }
- $$ = node;
- }
- ;
- col_options: {$$ = "";}
- | PRIMARY_KEY {
- // printf("得到主键 %s\n", $1);
- $$ = $1;
- }
- ;
- data_type: INT_T
- | FLOAT_T
- | STRING_T
- ;
- insert_stmt: INSERT INTO IDENTIFIER VALUES '(' insert_list ')' {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "insert_stmt");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "values", $6);
- $$=node;
- }
- ;
- insert_list: data_value {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- }
- | insert_list ',' data_value {
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- }
- ;
- data_value: INT_V {SIMPLE_TYPE_VALUE_OBJECT($$, int, Number, $1);}
- | FLOAT_V {SIMPLE_TYPE_VALUE_OBJECT($$, float, Number, $1);}
- | STRING_V {SIMPLE_TYPE_VALUE_OBJECT($$, string, String, $1);}
- ;
- update_stmt: UPDATE IDENTIFIER SET update_list WHERE where_expr {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "update_stmt");
- cJSON_AddStringToObject(node, "table_name", $2);
- cJSON_AddItemToObject(node, "set", $4);
- cJSON_AddItemToObject(node, "where", $6);
- $$=node;
- }
- ;
- update_list: single_assign_item {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- }
- | update_list ',' single_assign_item {
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- }
- ;
- single_assign_item: identifier '=' identifier_or_const_value {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "assign_const");
- cJSON_AddItemToObject(node, "left", $1);
- cJSON_AddItemToObject(node, "right", $3);
- $$=node;
- }
- ;
- table_field: IDENTIFIER '.' IDENTIFIER {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "table_field");
- cJSON_AddStringToObject(node, "table", $1);
- cJSON_AddStringToObject(node, "field", $3);
- $$=node;
- }
- ;
- column_name: table_field {$$=$1;} | identifier {$$=$1;};
- single_expr: identifier {$$=$1;}
- | table_field {$$=$1;}
- | data_value {$$=$1;}
- // | '(' single_expr ')' {$$=$2;}
- ;
- where_expr: logical_expr {
- MEET_JSON(logical_expr from where_expr, $1);
- $$=$1;
- }
- ;
- op_where_expr: {$$=cJSON_CreateObject();}
- | WHERE where_expr {$$=$2;}
- ;
- compare_expr: compare_expr bin_cmp_op compare_expr {
- fprintf(stderr, "compare_expr %s\n", $2);
- SIMPLE_OP_NODE($$, $2, $1, $3);
- cJSON_AddStringToObject($$, "op_type", "bin_cmp_op");
- }
- | single_expr {MEET_JSON(single_expr from compare_expr, $1); $$=$1;}
- | '(' where_expr ')' {MEET(括号where_expr from compare_expr); $$=$2;}
- ;
- negative_expr: NOT negative_expr {SIMPLE_OP_NODE_ONLY_LEFT($$, "非", $2);}
- | compare_expr {MEET_JSON(compare_expr from negative_expr, $1) $$=$1;}
- | '(' negative_expr ')' {MEET_JSON(negative_expr from negative_expr, $2) $$=$2;}
- ;
- contains_expr: identifier bin_contains_op '(' select_stmt ')' {
- MEET_JSON(logical_expr bin_contains_op select_stmt, $2);
- SIMPLE_OP_NODE($$, $2, $1, $4);
- cJSON_AddStringToObject($$, "op_type", "bin_contains_op");
- }
- | identifier bin_contains_op '(' expr_list ')' {
- MEET_VAR(logical_expr bin_contains_op expr_list, $2);
- SIMPLE_OP_NODE($$, $2, $1, $4);
- cJSON_AddStringToObject($$, "op_type", "bin_contains_op");
- }
- | negative_expr {MEET_JSON(negative_expr from contains_expr, $1); $$=$1;}
- ;
- logical_expr: logical_expr bin_logical_op contains_expr {
- fprintf(stderr, "logical_expr %s\n", $2);
- SIMPLE_OP_NODE($$, $2, $1, $3);
- cJSON_AddStringToObject($$, "op_type", "bin_logical_op");
- }
- | contains_expr {MEET_JSON(contains_expr from logical_expr, $1); $$=$1;}
- | single_expr {MEET_JSON(single_expr from logical_expr, $1) $$=$1;}
- | negative_expr {MEET_JSON(negative_expr from logical_expr, $1); $$=$1;}
- ;
- expr_list: {
- MEET(empty expr_list);
- cJSON* node = cJSON_CreateArray();
- $$=node;
- }
- | logical_expr {
- MEET_JSON(where_expr from expr_list, $1);
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- }
- | expr_list ',' logical_expr {
- fprintf(stderr, "迭代 expr_list\n %s", cJSON_Print($1));
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- }
- ;
- identifier: IDENTIFIER {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "identifier");
- cJSON_AddStringToObject(node, "value", $1);
- $$=node;
- }
- ;
- identifier_or_const_value: identifier {$$=$1;} | data_value {$$=$1;}
- ;
- bin_cmp_op: '=' {$$ = "相等";}
- | '>' {$$ = "大于";}
- | '<' {$$ = "小于";}
- | ">=" {$$ = "大等";}
- | "<=" {$$ = "小等";}
- | "!=" {$$ = "不等";}
- ;
- unary_compare_op: NOT {$$ = "非";}
- ;
- bin_logical_op: AND {MEET(and from bin_log) $$ = "且";}
- | OR {MEET(or from bin_log) $$ = "或";}
- ;
- bin_contains_op: IN {$$ = "包含于";}
- | NOT IN {$$ = "不包含于";}
- ;
- delete_stmt: DELETE FROM IDENTIFIER op_where_expr {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "delete_stmt");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "where", $4);
- $$=node;
- }
- ;
- op_join: {$$ = NULL;}
- | JOIN column_name ON where_expr {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "join_options");
- cJSON_AddItemToObject(node, "join_with", $2);
- cJSON_AddItemToObject(node, "on", $4);
- $$=node;
- }
- ;
- table_name: IDENTIFIER {$$=$1;}
- ;
- table_name_list: table_name {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, cJSON_CreateString($1));
- $$=node;
- }
- | table_name_list ',' table_name {
- cJSON_AddItemToArray($1, cJSON_CreateString($3));
- $$=$1;
- }
- ;
- select_stmt: SELECT select_items FROM table_name_list op_join op_where_expr {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "select_stmt");
- cJSON_AddItemToObject(node, "select_cols", $2);
- MEET_JSON(table_names, $4);
- cJSON_AddItemToObject(node, "table_names", $4);
- if ($5 != NULL) {
- cJSON_AddItemToObject(node, "join_options", $5);
- }
- cJSON_AddItemToObject(node, "where", $6);
- $$=node;
- }
- ;
- select_items: select_item {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- }
- | select_items ',' select_item {
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- }
- ;
- select_item: single_expr {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "select_column");
- cJSON_AddItemToObject(node, "target", $1);
- $$=node;
- }
- | single_expr AS IDENTIFIER {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "select_column");
- cJSON_AddItemToObject(node, "target", $1);
- cJSON_AddStringToObject(node, "alias", $3);
- $$=node;
- }
- | '*' {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "select_all_column");
- cJSON* node_select_all = cJSON_CreateObject();
- cJSON_AddStringToObject(node_select_all, "type", "select_all_column");
- cJSON_AddStringToObject(node_select_all, "value", "select_all_column");
- cJSON_AddItemToObject(node, "target", node_select_all);
- $$=node;
- }
- ;
- drop_stmt: DROP TABLE IDENTIFIER {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "drop_stmt");
- cJSON_AddStringToObject(node, "table_name", $3);
- $$=node;
- }
- ;
- %%
- int main(int ac, char** av) {
- jroot = cJSON_CreateArray();
- if (ac != 2) {
- printf("Usage: %s <sql>\n", av[0]);
- exit(1);
- }
- yy_scan_string(av[1]);
- int res = yyparse();
- printf("%s\n", cJSON_Print(jroot));
- return res;
- }
- void yyerror(const char *s) {
- fprintf(stderr, "error: %s at %s\n", s, yytext);
- exit(1);
- }
|