千家信息网

怎么理解PostgreSQL的词法分析

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,这篇文章主要讲解了"怎么理解PostgreSQL的词法分析",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么理解PostgreSQL的词法分析"吧!一
千家信息网最后更新 2025年02月02日怎么理解PostgreSQL的词法分析

这篇文章主要讲解了"怎么理解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]+          { /* 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;          }<>             { 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.sqlsql: lex.yy.c    gcc -o $@ $

样例SQL脚本

select *from test1where c1 = 'TEST';

执行结果:

[root@localhost sql]# make./sql < test.sqlTOKEN-TYPE          TOKEN-VALUE-------------------------------------------------T_SELECT            select*                   *T_ID                fromT_ID                test1T_ID                whereT_ID                c1=                   =T_STRING            'TEST';                   ;

感谢各位的阅读,以上就是"怎么理解PostgreSQL的词法分析"的内容了,经过本文的学习后,相信大家对怎么理解PostgreSQL的词法分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0