123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- %{
- #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);
- char* catstr(char* s1, char* s2);
- 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;
- %}
- %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
- %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
- %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> where_condition_item where_conditions identifier identifier_or_const_value the_whole_where_smt
- %type <jv> delete_stmt select_stmt select_item select_items
- %type <jv> data_value_list identifier_or_const_value_or_const_value_list
- %type <jv> search_expr compare_expr single_expr expr where_expr logical_expr negative_expr
- // %left OR
- // %left AND
- // %right NOT
- // %nonassoc '=' '>' '<'
- // %left '+' '-'
- // %left '*' '/'
- %start statement
- %%
- statement: NEWLINE
- | QUIT {printf("bye!\n"); exit(0); }
- | sql_statement
- ;
- sql_statement: create_table_stmt
- | insert_stmt
- | update_stmt
- | delete_stmt
- | select_stmt
- ;
- create_table_stmt: CREATE TABLE IDENTIFIER NEWLINE
- {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "create_table");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "cols", cJSON_CreateArray());
- cJSON_AddItemToArray(jroot, node);
- }
- create_table_stmt: CREATE TABLE IDENTIFIER '(' create_col_list ')' NEWLINE {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "create_table");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "cols", $5);
- cJSON_AddItemToArray(jroot, node);
- $$=node;
- };
- create_col_list: create_definition {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- // printf("得create_definition %s\n", cJSON_Print($1));
- }
- | create_col_list ',' create_definition {
- // printf("迭代 create_col_list\n %s", cJSON_Print($1));
- // printf("迭代 create_definition\n %s", cJSON_Print($3));
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- // printf("迭代\n %s", cJSON_Print($$));
- }
- ;
- create_definition: IDENTIFIER data_type col_options {
- // fprintf(stderr, "得列 %s %s with options %s: %d\n", $1, $2, $3, strlen($3));
- 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 ')' NEWLINE {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "insert");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "values", $6);
- cJSON_AddItemToArray(jroot, node);
- $$=node;
- };
- insert_list: data_value {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- // printf("得create_definition %s\n", cJSON_Print($1));
- }
- | insert_list ',' data_value {
- // printf("迭代 create_col_list\n %s", cJSON_Print($1));
- // printf("迭代 create_definition\n %s", cJSON_Print($3));
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- // printf("迭代\n %s", cJSON_Print($$));
- }
- ;
- 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 NEWLINE {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "update");
- cJSON_AddStringToObject(node, "table_name", $2);
- cJSON_AddItemToObject(node, "set", $4);
- cJSON_AddItemToObject(node, "where", $6);
- cJSON_AddItemToArray(jroot, node);
- $$=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;
- }
- ;
- the_whole_where_smt: {$$=cJSON_CreateObject();}
- | WHERE where_expr {$$=$2;}
- ;
- // where 后的条件跟 select 中的有本质区别
- // select 中的只是常量或者字段名, 而 where 中的是表达式
- single_expr: identifier {$$=$1;}
- | IDENTIFIER '.' IDENTIFIER {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "table_field");
- cJSON_AddStringToObject(node, "table", $1);
- cJSON_AddStringToObject(node, "field", $3);
- $$=node;
- }
- | data_value {$$=$1;}
- | '(' single_expr ')' {$$=$2;}
- ;
- where_expr: logical_expr {$$=$1;};
- ;
- compare_expr: compare_expr bin_cmp_op compare_expr {SIMPLE_OP_NODE($$, $2, $1, $3);}
- | single_expr {$$=$1;}
- ;
- negative_expr: NOT negative_expr {SIMPLE_OP_NODE_ONLY_LEFT($$, "非", $2);}
- | compare_expr {$$=$1;}
- ;
- logical_expr: negative_expr bin_logical_op negative_expr {SIMPLE_OP_NODE($$, $2, $1, $3);}
- | single_expr {$$=$1;}
- ;
- // expr: compare_expr
- // | negative_expr
- // | logical_expr
- // ;
- // compare_expr: expr bin_cmp_op single_expr
- // expr: expr bin_cmp_op expr {SIMPLE_OP_NODE($$, $2, $1, $3)}
- // | expr bin_cmp_op '(' expr ')' {SIMPLE_OP_NODE($$, $2, $1, $4)}
- // // | '(' expr ')' {$$=$2;}
- // // | NOT expr {SIMPLE_OP_NODE_ONLY_LEFT($$, "非", $2);
- // // fprintf(stderr, "非asd %s\n", cJSON_Print($2));
- // // }
- // ;
- // // expr: expr bin_logical_op expr {SIMPLE_OP_NODE($$, $2, $1, $3)}
- // expr_list: expr{
- // cJSON* node = cJSON_CreateArray();
- // cJSON_AddItemToArray(node, $1);
- // $$=node;
- // }
- // | expr_list ',' expr {
- // fprintf(stderr, "迭代 expr_list\n %s", cJSON_Print($1));
- // cJSON_AddItemToArray($1, $3);
- // $$=$1;
- // }
- // expr: expr bin_contains_op '(' expr_list ')' {SIMPLE_OP_NODE($$, $2, $1, $4)}
- // | expr bin_contains_op '(' select_stmt ')' {SIMPLE_OP_NODE($$, $2, $1, $4)}
- where_conditions: where_condition_item {
- $$=$1;
- }
- | '(' where_condition_item ')' {
- $$=$2;
- }
- | where_conditions bin_logical_op where_condition_item {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", $2);
- cJSON_AddItemToObject(node, "left", $1);
- cJSON_AddItemToObject(node, "right", $3);
- $$=node;
- }
- | unary_compare_op where_condition_item {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", $1);
- cJSON_AddItemToObject(node, "right", $2);
- $$=node;
- }
- | where_conditions bin_logical_op '(' where_conditions ')' {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", $2);
- cJSON_AddItemToObject(node, "left", $1);
- cJSON_AddItemToObject(node, "right", $4);
- $$=node;
- }
- ;
- 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;}
- ;
- data_value_list: data_value {
- cJSON* node = cJSON_CreateArray();
- cJSON_AddItemToArray(node, $1);
- $$=node;
- }
- | data_value_list ',' data_value {
- cJSON_AddItemToArray($1, $3);
- $$=$1;
- }
- ;
- identifier_or_const_value_or_const_value_list: identifier_or_const_value{$$=$1;}
- | data_value_list {$$=$1;}
- where_condition_item: identifier_or_const_value bin_cmp_op identifier_or_const_value {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", $2);
- cJSON_AddItemToObject(node, "left", $1);
- cJSON_AddItemToObject(node, "right", $3);
- $$=node;
- }
- | identifier_or_const_value bin_contains_op '(' data_value_list ')' {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", $2);
- cJSON_AddItemToObject(node, "left", $1);
- cJSON_AddItemToObject(node, "right", $4);
- $$=node;
- }
- ;
- bin_cmp_op: '=' {$$ = "相等";}
- | '>' {$$ = "大于";}
- | '<' {$$ = "小于";}
- | ">=" {$$ = "大等";}
- | "<=" {$$ = "小等";}
- | "!=" {$$ = "不等";}
- | IN {$$ = "包含于";}
- ;
- unary_compare_op: NOT {$$ = "非";};
- bin_logical_op: AND {$$ = "且";}
- | OR {$$ = "或";}
- bin_contains_op: IN {$$ = "包含于";}
- | NOT IN {$$ = "不包含于";}
- delete_stmt: DELETE FROM IDENTIFIER the_whole_where_smt NEWLINE {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "delete");
- cJSON_AddStringToObject(node, "table_name", $3);
- cJSON_AddItemToObject(node, "where", $4);
- cJSON_AddItemToArray(jroot, node);
- $$=node;
- };
- select_stmt: SELECT select_items FROM IDENTIFIER the_whole_where_smt NEWLINE {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "select");
- cJSON_AddItemToObject(node, "select_cols", $2);
- cJSON_AddStringToObject(node, "table_name", $4);
- cJSON_AddItemToObject(node, "where", $5);
- $$=node;
- cJSON_AddItemToArray(jroot, 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: identifier_or_const_value {
- cJSON* node = cJSON_CreateObject();
- cJSON_AddStringToObject(node, "type", "select_column");
- cJSON_AddItemToObject(node, "target", $1);
- $$=node;
- }
- | identifier_or_const_value 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");
- $$=node;
- }
- |
- ;
- %%
- int main(int ac, char** av) {
- jroot = cJSON_CreateArray();
- if (ac != 2) {
- printf("Usage: %s <sql>\n", av[0]);
- exit(1);
- }
- // yyin = av[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);
- }
- char* catstr(char* s1, char* s2) {
- char* s = malloc(strlen(s1)+strlen(s2)+1);
- strcpy(s, s1);
- strcat(s, s2);
- return s;
- }
|