日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql bison_使用flex和bison实现的sql引擎解析

發(fā)布時間:2024/3/26 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql bison_使用flex和bison实现的sql引擎解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

由于老師要求,最近在做oceanbase存儲過程的實(shí)現(xiàn),在oceanbase 0.4以前是不支持存儲過程的。實(shí)現(xiàn)的主要步驟主要包括 1、語法解析 2、詞法解析 3、具體執(zhí)行語法樹的步驟 現(xiàn)在先來說說語法解析吧,在這一塊主要是使用的flex( 詞法分析器生成工具) 和bison(語

由于老師要求,最近在做oceanbase存儲過程的實(shí)現(xiàn),在oceanbase 0.4以前是不支持存儲過程的。實(shí)現(xiàn)的主要步驟主要包括

1、語法解析

2、詞法解析

3、具體執(zhí)行語法樹的步驟

現(xiàn)在先來說說語法解析吧,在這一塊主要是使用的flex( 詞法分析器生成工具) 和bison(語法分析器生成器) 這兩個是對用戶輸入的存儲過程語句進(jìn)行解析的

來具體說說該怎么實(shí)現(xiàn)對sql語句的分析吧

1、首先建立一個lex的文件

%option noyywrap nodefault yylineno case-insensitive

%{

#include "prosql.tab.hpp"

#include #include #include #include #include //YYSTYPE yylval;

int oldstate;

extern "C" int yylex();

//extern "C" int yyparse();

extern "C" void yyerror(const char *s, ...);

extern char globalInputText[10000];

extern int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead );

#undef YY_INPUT

#define YY_INPUT(b,r,s) readInputForLexer(b,&r,s)

%}

%x COMMENT

%%

CREATE{ return CREATE; }

PROCEDURE{ return PROCEDURE; }

SQL{ return SQL; }

DECLARE{ return DECLARE; }

SET{ return SET; }

BEGIN{ return BEGINT; }

END{ return END; }

INT{ return INT; }

VARCHAR{ return VARCHAR; }

DATE{ return DATE; }

TIME{ return TIME; }

DOUBLE{ return DOUBLE; }

IF{ return IF; }

THEN{ return THEN; }

ELSE{ return ELSE; }

ENDIF{ return ENDIF; }

FOR{ return FOR; }

WHEN{ return WHEN; }

WHILE{ return WHILE; }

[0-9]+{ yylval.strval = strdup(yytext);/*printf("number=%s\n",yylval.strval);*/ return INTNUM; }/*number*/

[0-9]+"."[0-9]* |

"."[0-9]+|

[0-9]+E[-+]?[0-9]+|

[0-9]+"."[0-9]*E[-+]?[0-9]+ |

"."[0-9]*E[-+]?[0-9]+{ yylval.strval = strdup(yytext);/*printf("float=%s\n",yylval.strval);*/ return APPROXNUM; }/*double*/

TRUE{ yylval.strval = "1";/*printf("bool=%s\n",yylval.strval);*/ return BOOL; }/*bool*/

FALSE{ yylval.strval = "0";/*printf("bool=%s\n",yylval.strval);*/ return BOOL; }/*bool*/

'(\\.|''|[^'\n])*'|

\"(\\.|\"\"|[^"\n])*\" {

char *temp = strdup(yytext);

yylval.strval = strdup(yytext);

//GetCorrectString(yylval.strval, temp);

/*printf("string=%s\n",yylval.strval);*/

return STRING;

}/*string*/

'(\\.|[^'\n])*${ yyerror("Unterminated string %s", yytext); }

\"(\\.|[^"\n])*${ yyerror("Unterminated string %s", yytext); }

X'[0-9A-F]+' |

0X[0-9A-F]+ { yylval.strval = strdup(yytext); return STRING; }

0B[01]+ |

B'[01]+' { yylval.strval = strdup(yytext); return STRING; }

[-+&~|^/%*(),.;!] { return yytext[0]; }

"&&"{ return ANDOP; }

"||"{ return OR; }

""{ yylval.subtok = 2; return COMPARISON; }

"!="|

"<>"{ yylval.subtok = 3; return COMPARISON; }

"="{ yylval.subtok = 4; return COMPARISON; }

"<="{ yylval.subtok = 5; return COMPARISON; }

">="{ yylval.subtok = 6; return COMPARISON; }

"<=>"{ yylval.subtok = 12; return COMPARISON; }

"<>"{ yylval.subtok = 2; return SHIFT; }

[A-Za-z][A-Za-z0-9_]*{ yylval.strval = strdup(yytext);

/*printf("name 1=%s\n",yylval.strval);*/

return NAME; }

`[^`/\\.\n]+` { yylval.strval = strdup(yytext+1);

/*printf("name 2=%s\n",yylval.strval);*/

yylval.strval[yyleng-2] = 0;

return NAME; }

`[^`\n]*$ { yyerror("unterminated quoted name %s", yytext); }

@[0-9a-z_.$]+ |

@\"[^"\n]+\" |

@`[^`\n]+` |

@'[^'\n]+' { yylval.strval = strdup(yytext+1); return USERVAR; }

@\"[^"\n]*$ { yyerror("unterminated quoted user variable %s", yytext); }

@`[^`\n]*$ { yyerror("unterminated quoted user variable %s", yytext); }

@'[^'\n]*$ { yyerror("unterminated quoted user variable %s", yytext); }

":=" { return ASSIGN; }

#.*;

"--"[ \t].*;

"/*" { oldstate = YY_START; BEGIN COMMENT; }

"*/" { BEGIN oldstate; }

.|\n ;

<> { yyerror("unclosed comment"); }

[ \t\n] /* white space */

. { yyerror("mystery character '%c'", *yytext); }

%%

這一部分呢就是對 每個我們自定義的滿足正則的識別

接下來是對詞的語法識別

%{

#include #include #include #include #include char * parsetreeroot=NULL;

extern "C" int yylex();

extern "C" int yyparse();

extern "C" void yyerror(const char *s, ...);

char globalInputText[10000];

int globalReadOffset;

int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead );

char * mystrcat(char *s1,char *s2)

{

char *p1=(char *)malloc(strlen(s1)+strlen(s2)+1);

strcpy(p1,s1);

strcat(p1,s2);

return p1;

}

%}

%locations

%union {

int intval;

double floatval;

char *strval;

int subtok;

}

%token NAME

%token STRING

%token INTNUM

%token BOOL

%token APPROXNUM

%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 { $$=mystrcat($1,$2); parsetreeroot=$$;}

;

create_stmt: CREATE PROCEDURE NAME '(' para_list ')'

{

char *temp=mystrcat("create procedure ",$3);

temp=mystrcat(temp,"(");

temp=mystrcat(temp,$5);

$$=mystrcat(temp,")(create)\n");

}

;

/*

opt_if_not_exists: { $$ = 0; }

| IF NOT EXISTS { $$ = 1; }

;

*/

para_list: definition { $$=$1; }

|definition ',' para_list

{

char *temp=mystrcat($1,",");

$$=mystrcat(temp,$3);

}

;

definition: USERVAR data_type

{

char *temp=mystrcat($1," ");

$$=mystrcat(temp,$2);

}

;

data_type:

DATE {$$="date"; }

| TIME{$$="time"; }

| VARCHAR '(' INTNUM ')' {$$="varchar"; }

| INT {$$="int"; }

| DOUBLE {$$="double"; }

;

pro_block: BEGINT pro_parameters pro_body END

{

char *temp=mystrcat("begin\n",$2);

temp=mystrcat(temp,"");

temp=mystrcat(temp,$3);

$$=mystrcat(temp,"end");

//printf("pro_body %s\n",$3);

}

;

pro_parameters: declare_list ';' { $$=mystrcat($1,";(declare)\n");}

|pro_parameters declare_list ';'

{

char *temp=mystrcat($1,$2);

$$=mystrcat(temp,";(declare)\n");

}

|pro_parameters set_list ';'

{

char *temp=mystrcat($1,$2);

$$=mystrcat(temp,";(set)\n");

}

;

declare_list:

|DECLARE definition

{

$$=mystrcat("declare ",$2);

}

|declare_list ',' definition

{

char *temp=mystrcat($1,",");

$$=mystrcat(temp,$3);

}

;

set_list:

|SET assign_var

{

$$=mystrcat("set ",$2);

}

| set_list ',' assign_var

{

char *temp=mystrcat($1,",");

$$=mystrcat(temp,$3);

}

;

assign_var : USERVAR COMPARISON expr

{

char *temp=mystrcat($1,"=");

$$=mystrcat(temp,$3);

}

;

expr: NAME { $$=$1;}

| STRING { $$=$1;}

| INTNUM { $$=$1;}

| APPROXNUM { $$=$1;}

| BOOL { $$=$1;}

;

pro_body : pro_stmt_list { $$=$1; }

;

pro_stmt_list: sql_stmt {$$=$1; }

|pro_stmt_list sql_stmt

{

$$=mystrcat($1,$2);

}

;

sql_stmt:

|SQL NAME ';' { $$=mystrcat($2,";(sql)\n");}

;

%%

/*

int main(int argc, char* argv[])

{

yyparse();

}*/

int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead ) {

int numBytesToRead = maxBytesToRead;

int bytesRemaining = strlen(globalInputText)-globalReadOffset;

int i;

if ( numBytesToRead > bytesRemaining ) { numBytesToRead = bytesRemaining; }

for ( i = 0; i < numBytesToRead; i++ ) {

buffer[i] = globalInputText[globalReadOffset+i];

}

*numBytesRead = numBytesToRead;

globalReadOffset += numBytesToRead;

return 0;

}

void yyerror(const char *s, ...)

{

fprintf(stderr, "error: %s\n", s);

}

void zzerror(const char *s, ...)

{

extern int yylineno;

va_list ap;

va_start(ap, s);

fprintf(stderr, "%d: error: ", yylineno);

vfprintf(stderr, s, ap);

fprintf(stderr, "\n");

}

int yywrap(void)

{

return 1;

}

char* getsql()

{

return parsetreeroot;

}

這部分就是對上一個識別出來的詞 進(jìn)行順序上的確定,構(gòu)成一個完整的語法

這些需要在linux環(huán)境下進(jìn)行調(diào)試

bison -d 文件名

flex 文件名

本文原創(chuàng)發(fā)布php中文網(wǎng),轉(zhuǎn)載請注明出處,感謝您的尊重!

總結(jié)

以上是生活随笔為你收集整理的mysql bison_使用flex和bison实现的sql引擎解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。