欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Postgres词法分析和语法分析

时间:2023-04-26

1: 基本概念

postgres数据库将用户输入的sql命令作为字符串传递给查询分析器,并对其进行词法分析和语法分析,最后生成分析数。

2: 使用工具

词法分析和语法分析是由Unix工具Yacc和Lex制作的。具体使用的是Bison和Flex。

3:postgres相关的文件

[1] kwlist.h: 声明keyword列表(包括保留关键字和非保留关键字)。

具体的:keyword: (name, token_value,category)。

[2] kwlookup.cpp: 定义ScanKeywordLookup函数实现,该函数判断输入的字符串是否是关键字,若是关键字,则返回关键字列表中单词的指针,采用二分查找。没有匹配的则返回NULL。

[3] scanup.c:提供几个词法分析时常用的函数。scanstr函数处理转义字符,downcase_truncate_identifier函数将大写英文字符转换为小写字符,truncate_identifier函数截断超过最大标识符长度的标识符,scanner_isspace函数判断输入字符是否为空白字符

[4] scan.l:定义词法结构,编译生成scan.c;这里会忽略comment等无用信息。

[5] gram.y:定义语法结构,编译生成gram.c;分析后生成语法分析树。

[6] check_keywords.pl: 检查在gram.y和kwlist.h中定义的关键字列表是否一致

4: postgres相关的执行顺序:

        

5: 函数入口raw_parser:

给一个sql语句进行词法分析和语法分析,最后生成一个解析树parsetree.

其中重要的三步:[1] 初始化flex scanner 

yyscanner = scanner_init(str, &yyextra.core_yy_extra,
                             ScanKeywords, NumScanKeywords);

[2]: 初始化bison parser:

parser_init(&yyextra);

[3]: parse解析;

yyresult = base_yyparse(yyscanner);

6:bison基本原理:生成语法分析器代码,将.y文件编译后生成.c和.h文件。
: 对输入文件的中的形式文法构架 LALR 分析表,并生成基于该分析表的 语法分析器 C 语言源程序.tab.c,其语法分析函数原型为int yyparse()、该语法分析器通过调用用户提供的词法分析函数int yylex()对输入串 进行扫描得到的终结符进行语法分析,如果分析成功,则函数返回 0, 否则返回非 0、其分析方法采用自底向上的移进/归约分析法,在完成归约时, yyparse()将执行 bison 源文件用户在当前归约产生式后附注的 C 语言 代码,bison 称之为语义动作 (Semantic Action).

%{ C语言说明部分:

%}

bison声明部分:

%% 语法规则部分:

%%

附加C语言代码:

7:Lex和Yacc

Flex:生成词法分析器的编译工具,生成词法分析器代码,将.l文件编译后生成.c和.h文件。
词法分析通常所做的就是在输入中寻找字符的模式(pattern)。它使用正则表达式匹配输入的字符串并且把它们转换成对应的标记,正则表达式就是一种对模式的简介明了的描述方式。 匹配正则表达式的规则,然后执行对应的动作。其实就是提取编程语言占用的各种保留字、操作符、特殊符号等等语言的元素。

.l文件:scan.l文件包含定义段、规则段、C程序代码段三部分,每个部分之间用“%%”分割。

[1]: %top{ ..、} 这部分,括号中内容将被原样copy到生成的scan.c中,并且位于C文件的最顶部。主要包含此文件描述、注释,以及需要的C头文件。

[2]: %{ ..、%}这部分的代码会被原样copy到生成的C文件中。这里可以重定义一些Flex中的宏,如YYSTYPE, 以及一些在规则段使用的函数声明、结构体声明和定义等

[3]: %option 此部分是Flex支持的一些参数,通过%option 来设置

[4]: %x 声明起始状态(有两种模式:%x声明独占模式 %s声明共享模式),起始状态代表进入一个特定的状态,在规则段只有定义了特定状态的规则才会匹配,这种规则通过来标识。例如 定义段定义了 %x xb 则在规则段只有开头的规则才会匹配,其他的的规则则不会被匹配。Lex开始时的标准状态是状态零,也称为INITIAL

[5]: 预定义正则表达式的代理,可以为一些要匹配的正则表达式命名,这样在规则段可以用这个代理名字,来代替这个表达式。例如space [ tnrf],给[ tnrf] 命名为space, 后面在规则段即可使用{space}来代替[ tnrf],同时代理也可以被嵌套,如whitespace ({space}+|{comment}) 这里定义了新的代理whitespace, 它代理了 ({space}+|{comment}) 其中{space}就被嵌套代理了。

[6]: 规则段:

{规则名} {

  该规则对应的执行的动作。

}

词法分析器调用yylex()函数来读取一小部分输入流匹配相应的规则然后返回一个记号流,每个记号实际上有两个组成部分,记号编号(token number)和记号值(token’s value)。
记号编号是一个较小的整数,数字随意,零值意味着文件的结束。Bison创建的语法分析器,会自动从258开始(目的是为了避免与文字字符记号产生冲突)

 

 

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。