共計 2574 個字符,預(yù)計需要花費(fèi) 7 分鐘才能閱讀完成。
這篇文章主要講解了“怎么理解 PostgreSQL 的詞法分析”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么理解 PostgreSQL 的詞法分析”吧!
一、詞法分析
基本概念
首先來理清一些基本概念.
詞法分析從左向右掃描輸入的 SQL 語句,將其字符流分割成一個個的詞(稱為 token), 這些 token 是輸入流中不可再分割的一串字符,類似于英語中單詞,或漢語中的詞。
SQL 語句中 token 的類別是有限的, 一般來說有常量(數(shù)值 / 字符 / 字符串等), 操作符(算術(shù)操作符 / 邏輯操作符等), 分隔符(逗號 / 分號 / 括號等), 保留關(guān)鍵字, 標(biāo)識符(函數(shù)名 / 過程名等). 如:1 和 200.13 是數(shù)值常量 token,’張三’和’廣州市’是字符串常量 token,+/- 等是操作符 token 等.
Flex 簡介
在 PostgreSQL 中, 使用了開源的 Flex 對 SQL 進(jìn)行詞法分析.
Flex 全稱為 Fast LEXical analyser generator – scanner generator for lexing in C and C++.
Flex 的輸入文件格式為:
%{Declarations(聲明)
Definitions(定義)
Rules(規(guī)則)
User subroutines(用戶子過程)
如:
%{
#define T_ZEOR 0
int i = 0;
NUM ([0-9]+)
{NUM} printf( ? // 遇到數(shù)字, 打印?
# return T_ZEOR; // 遇到字符 #, 返回 0
. ECHO; // 遇到其他字符, 打印該字符
int main(int argc, char* argv[]) { yylex();
return T_ZEOR;
int yywrap() { return 1;}
該例程的運(yùn)行效果如下:
[root@localhost mytest]# ./mytest
1t33..q
?t?..q
#
SQL 詞法分析器
使用 Flex 可以實(shí)現(xiàn)一個簡單的 SQL 詞法分析器, 簡單分為以下幾個步驟:
1. 列出 SQL 中所有類型的 token
2. 為每種 token 分配一個唯一的編號, 同時寫出該 token 的正則表達(dá)式
3. 寫出每種 token 的 rule
sql.l
%{
int current_linenum = 1;
void init();
void elog(char* msg, int line);
typedef enum {
T_EQUAL = 128 ,
T_SELECT ,
T_CONST ,
T_STRING ,
T_ID
} TokeType;
static char* string_token[] = {
T_EQUAL , T_SELECT , T_CONST , T_STRING , T_ID
};
INTEGER ([0-9]+)
UNTERM_STRING ([^ \n]*)
STRING ([^ \n]* )
IDENTIFIER ([_a-zA-Z][_a-zA-Z0-9]*)
OPERATOR ([+*-/%=,;! (){}])
SINGLE_COMMENT (// [^\n]*)
[\n] { current_linenum++; }
[ \t\r\a]+ { /* ignore all spaces */ }
{SINGLE_COMMENT} { /* skip for single line comment */ }
{OPERATOR} { return yytext[0]; }
= { return T_EQUAL; }
select { return T_SELECT; }
{INTEGER} { return T_CONST; }
{STRING} { return T_STRING; }
{IDENTIFIER} { return T_ID; }
EOF { return 0; }
{UNTERM_STRING} { elog( Unterminated string constant , current_linenum); }
. { elog( Unrecognized character , current_linenum); }
int main(int argc, char* argv[]) {
int token;
init();
while (token = yylex()) { if(token 128)
printf(%-20c , token);
else
printf(%-20s ,string_token[token - 128]);
puts(yytext);
}
return 0;
void init() {
printf( %-20s%s\n , TOKEN-TYPE , TOKEN-VALUE
printf( -------------------------------------------------\n
void elog(char* msg, int line) { printf( \nError at line %-3d: %s\n\n , line, msg);
int yywrap(void) { return 1;}
makefile
run: sql
./sql test.sql
sql: lex.yy.c
gcc -o $@ $
lex.yy.c: sql.l
flex $
樣例 SQL 腳本
select *
from test1
where c1 = TEST
執(zhí)行結(jié)果:
[root@localhost sql]# make
./sql test.sql
TOKEN-TYPE TOKEN-VALUE
-------------------------------------------------
T_SELECT select
* *
T_ID from
T_ID test1
T_ID where
T_ID c1
= =
T_STRING TEST
; ;
感謝各位的閱讀,以上就是“怎么理解 PostgreSQL 的詞法分析”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對怎么理解 PostgreSQL 的詞法分析這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!