在MySQL中,SQL語法分析器的輸出是語法樹;而在《flex&bison》中,分析器的輸出是逆波蘭式代碼。不過大同小異吧,作用其實是一樣的。這書裏面主要實現了select語句,作者說select是SQL中最複雜的語句了,想想也是,數據庫的最大的作用不就是提供查詢服務嘛!
select_stmt: SELECT select_opts select_expr_list
{ emit("SELECTNODATA %d %d", $2, $3); } ;
| SELECT select_opts select_expr_list
FROM table_references
opt_where opt_groupby opt_having opt_orderby opt_limit
opt_into_list { emit("SELECT %d %d %d", $2, $3, $5); } ;
;
上面這段語法規則算是select語句的頂層規則了。第一個有不規則就不用看了,算是一個特例了。我們主要研究第二個規則。首先,SELECT是一個終結符,直接匹配select關鍵字;select_opts是一些查詢的選項;select_expr_list是查詢的目標。因爲bison使用的是LALR(1)分析法,這是一個使用最左規約的方法。所以這個語法分析器分析出來的SQL是最後執行SELECT操作了。當然這並不一定,因爲SQL解析可以有很多實現。我看網上的資料,很多情況下SELECT操作並不是最後執行的。 然後table_references是一個比較複雜的非終結符號。SQL支持SELECT嵌套,也就是說table_references可以是一個SELECT語句的執行結果。這可以在規則文件中明顯的看出來。table_references: table_reference { $$ = 1; }
| table_references ',' table_reference { $$ = $1 + 1; }
;
table_reference: table_factor
| join_table
;
table_factor:
NAME opt_as_alias index_hint { emit("TABLE %s", $1); free($1); }
| NAME '.' NAME opt_as_alias index_hint { emit("TABLE %s.%s", $1, $3);
free($1); free($3); }
| table_subquery opt_as NAME { emit("SUBQUERYAS %s", $3); free($3); }
| '(' table_references ')' { emit("TABLEREFERENCES %d", $2); }
;
table_subquery: '(' select_stmt ')' { emit("SUBQUERY"); }
具體的邏輯就是table_references-->table_reference-->table_factor-->table_subquery-->( select_stmt )。