这篇文章主要讲解了“怎么理解PostgreSQL的词法分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解PostgreSQL的词法分析”吧!
一、词法分析
基本概念
首先来理清一些基本概念.
词法分析从左向右扫描输入的SQL语句,将其字符流分割成一个个的词(称为token),这些token是输入流中不可再分割的一串字符,类似于英语中单词,或汉语中的词。
SQL语句中token的类别是有限的,一般来说有常量(数值/字符/字符串等),操作符(算术操作符/逻辑操作符等),分隔符(逗号/分号/括号等),保留关键字,标识符(函数名/过程名等).如:1和200.13是数值常量token,’张三’和’广州市’是字符串常量token,+/-等是操作符token等.
Flex简介
在PostgreSQL中,使用了开源的Flex对SQL进行词法分析.
Flex全称为Fast LEXical analyser generator - scanner generator for lexing in C and C++.
Flex的输入文件格式为:
%{
Declarations(声明)
%}
Definitions(定义)
%%
Rules(规则)
%%
User subroutines(用户子过程)
如:
%{
#define T_ZEOR 0
int i = 0;
%}
NUM ([0-9]+)
%%
{NUM} printf("?"); //遇到数字,打印?
# return T_ZEOR; //遇到字符#,返回0
. ECHO; //遇到其他字符,打印该字符
%%
int main(int argc, char* argv[]) {
yylex();
return T_ZEOR;
}
int yywrap() {
return 1;
}
该例程的运行效果如下:
[root@localhost mytest]# ./mytest
1t33..q
?t?..q
#
SQL词法分析器
使用Flex可以实现一个简单的SQL词法分析器,简单分为以下几个步骤:
1.列出SQL中所有类型的token
2.为每种token分配一个唯一的编号,同时写出该token的正则表达式
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]+ { }
{SINGLE_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';
执行结果:
[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的词法分析”的内容了,经过本文的学习后,相信大家对怎么理解PostgreSQL的词法分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!