由於老師要求,最近在做oceanbase儲存過程的實現,在oceanbase 0.4以前是不支援儲存過程的。實現的主要步驟主要包括
現在先來說說語法解析吧,在這一塊主要是使用的flex( 詞法分析器生成工具) 和bison(語法分析器生成器) 這兩個是對使用者輸入的儲存過程語句進行解析的
來具體說說該怎麼實現對sql語句的分析吧
1、首先建立乙個lex的檔案
%option noyywrap nodefault yylineno case-insensitive
%%x comment
%%create
procedure
sql
declare
set
begin
end
int
varchar
date
time
double
if
then
else
endif
for
when
while
[0-9]+ /*number*/
[0-9]+"."[0-9]* |
"."[0-9]+ |
[0-9]+e[-+]?[0-9]+ |
[0-9]+"."[0-9]*e[-+]?[0-9]+ |
true /*bool*/
false /*bool*/
'(\\.|''|[^'\n])*' |
\"(\\.|\"\"|[^"\n])*\" /*string*/
'(\\.|[^'\n])*$
\"(\\.|[^"\n])*$
x'[0-9a-f]+' |
0x[0-9a-f]+
0b[01]+ |
b'[01]+'
[-+&~|^/%*(),.;!]
"&&"
"||"
"">"
"!=" |
"<>"
"="
"<="
">="
"<=>"
"<
">>"
[a-za-z][a-za-z0-9_]*
`[^`/\\.\n]+`
`[^`\n]*$
@[0-9a-z_.$]+ |
@\"[^"\n]+\" |
@`[^`\n]+` |
@'[^'\n]+'
@\"[^"\n]*$
@`[^`\n]*$
@'[^'\n]*$
":="
#.* ;
"--"[ \t].* ;
"/*"
"*/"
.|\n ;
<>
[ \t\n] /* white space */
.
%%
這一部分呢就是對 每個我們自定義的滿足正則的識別
接下來是對詞的語法識別
%
%}%locations
%union
%token name
%token string
%token intnum
%token bool
%token uservar
%type stmt_root create_stmt para_list definition data_type pro_block pro_parameters declare_list set_list
%type assign_var pro_body pro_stmt_list sql_stmt expr
%right assign
%left or
%left xor
%left andop
%left not '!'
%left between
%left comparison /* = <> < > <= >= <=> */
%left '|'
%left '&'
%left shift /* << >> */
%left '+' '-'
%left '*' '/' '%' mod
%left '^'
%token create
%token procedure
%token proname
%token declare
%token set
%token begint
%token end
%token sql
%token int
%token varchar
%token date
%token time
%token double
%token if
%token not
%token exists
%token then
%token else
%token endif
%token for
%token when
%token while
%start stmt_root
%%stmt_root: create_stmt pro_block
;create_stmt: create procedure name '(' para_list ')' ;
/*opt_if_not_exists:
| if not exists
;*/para_list: definition
|definition ',' para_list ;
definition: uservar data_type ;
data_type:
date
| time
| varchar '(' intnum ')'
| int
| double
;pro_block: begint pro_parameters pro_body end ;
pro_parameters: declare_list ';'
|pro_parameters declare_list ';'
|pro_parameters set_list ';' ;
declare_list:
|declare definition
|declare_list ',' definition ;
set_list:
|set assign_var
| set_list ',' assign_var ;
assign_var : uservar comparison expr ;
expr: name
| string
| intnum
| bool
;pro_body : pro_stmt_list
;pro_stmt_list: sql_stmt
|pro_stmt_list sql_stmt ;
sql_stmt:
|sql name ';' ;%%
/*int main(int argc, char* argv)
*/int readinputforlexer( char *buffer, int *numbytesread, int maxbytestoread )
for ( i = 0; i < numbytestoread; i++ )
*numbytesread = numbytestoread;
globalreadoffset += numbytestoread;
return 0;
}void yyerror(const char *s, ...)
void zzerror(const char *s, ...)
int yywrap(void)
char* getsql()
這部分就是對上乙個識別出來的詞 進行順序上的確定,構成乙個完整的語法
這些需要在linux環境下進行除錯
bison -d 檔名
flex 檔名
使用bison和flex工具 zz
這裡有乙個使用bison建立乙個簡單的計算器的例子 使用bison和flex工具學習編譯原理,遠比單獨看書然後自己編寫一些程式生動的多。這樣你就不會在那些複雜的字元處理,正規表示式的處理上浪費精力,最後費盡心力,卻沒有結果,失去了學習的興趣。我這裡有乙個簡單的計算器的程式,可以實現加 減 乘 除運算...
程式中,呼叫Bison和Flex結合的小例子
網上的很多程式,對初次接觸bison和flex的人而言,都有點複雜,看最簡單的例子更好些 我稍微修改一下,說說自己的理解,也作為乙個備忘 flex程式 1 root lex total cat lexer.l 2 12 13 digit 0 9 14 1516 17 18 19 2021 22voi...
利用 flex 和 bison 寫乙個計算器
實現實數範圍內的加減乘除 乘方 開方,三角函式sin cos運算 a 在命令提示符下依次執行一下兩行命令 flex 檔名.lex bison o檔名.c 檔名.y編譯的話,可用命令提示符,不過需要自己搭建環境 gcc o 可執行程式名稱 lex.yy.c bison生成的檔名.c當然可以用其他的方法...