%{ #include #include #include #include #include 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 INT_V %type FLOAT_V %type STRING_V NOT %type IDENTIFIER data_type PRIMARY_KEY col_options bin_cmp_op bin_logical_op unary_compare_op bin_contains_op %type create_definition create_col_list create_table_stmt data_value %type insert_stmt insert_list %type update_stmt update_list single_assign_item %type where_condition_item where_conditions identifier identifier_or_const_value the_whole_where_smt %type delete_stmt select_stmt select_item select_items %type data_value_list identifier_or_const_value_or_const_value_list %type 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 \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; }