1.SQL解析系列(golang)--goyacc实战
2.Yacc简介
3.编译原理入门之 lex,源码 flex,yacc,bison等工具了解
4.TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现
5.ç¼è¯åçpdf
6.深入了解MySQL语法分析器Yacc的原理与实现mysqlyacc
SQL解析系列(golang)--goyacc实战
Lex & Yacc简介
Lex & Yacc是用于生成词法分析器和语法分析器的工具,与GNU用户熟悉的解析Flex&Bison相对应。它们在编译器领域和DSL或SQL解析领域有广泛应用。源码
Lex用于生成词法分析器,解析将输入分割成有意义的源码词块(token)。
Yacc用于生成语法解析器,解析夏日自助下单系统源码确定token之间的源码关联。
词法分析器流程如下图所示。解析
词法分析器
词法分析器获取token流。源码通过调用yylex()读取输入并返回token,解析然后循环读取并返回解析好的源码token。每个token包含两部分:类型和值。解析
计算器词法分析器规则定义示例。源码
语法分析器
语法分析器找出输入token之间的解析关系,使用巴科斯范式(BNF)书写规则。源码同样分为三部分,前两部分必须。
规则示例。
yacc语法规范整体结构
由三部分组成,包括规则定义和用户子程序。动作代码执行语法匹配时的操作。如日期解析规则。
移进/归约过程
移进:读取token无法匹配规则时,将其压入堆栈并切换状态。归约:发现能匹配规则的token,将符号从堆栈取出并压入新符号。
处理表达式如fred = + 的示例。
解决冲突:通过指定优先级和结合性。
goyacc
goyacc是golang版的Yacc,生成符合输入语法规则文件的go语言解析器。yyParse要求词法分析器符合特定接口。
接口示例。
goyacc样例:电话号码解析源代码。
json解析器源代码。
参考文档链接。
Yacc简介
Yacc,mallcloud源码全称为Yet Another Compiler Compiler,是一个在Unix/Linux系统上著名的工具,专门用于生成编译器。其主要作用是生成C语言编写的语法解析器(Parser),这类解析器是编译过程中的关键组件,负责理解并解析源代码的语法规则。在Yacc的使用中,通常需要与词法分析器Lex配合,通过它们的协同工作,将解析器和词法器的输出结合,形成完整的编译器代码。
起初,Yacc主要局限于Unix系统,但随着技术的发展,它已经成功移植到了Windows以及其他多种操作系统平台,使得更多的开发者能够在不同的环境中利用Yacc进行编译器的开发。无论是在学术研究还是工业实践中,Yacc都扮演着不可或缺的角色,它简化了编译器的创建过程,提高了开发者的工作效率。
总的来说,Yacc是一个强大的工具,它通过生成C语言解析器,帮助开发者构建功能完备的编译器,跨平台的特性使其在现代软件开发中扮演着重要角色。通过它,程序员能够更加专注于语言的语法设计,而不是底层的编译逻辑实现。
编译原理入门之 lex, flex,yacc,bison等工具了解
Lex,Flex,Yacc,bison是编译原理中常用的工具,分别用于词法分析和语法分析。Lex(或Flex)生成词法分析器,将字符流转换为标记;Yacc(或bison)生成语法分析器,eoenyoubbs源码执行语法规则解析。使用场景主要在编译器前端阶段,分别进行词法和语法分析。工作原理分别是通过正则表达式和BNF来描述规则并生成代码。
Lex与Flex相似,后者生成的扫描器具有可重入性,适用于多线程环境。Yacc与bison等效,后者具备更多功能与优化的错误报告,同样支持多线程,通过BNF描述语法规则生成代码。
综上,Lex和Flex用于生成词法分析器,Yacc和bison用于生成语法分析器,共同构成编译器的核心部分。这些工具通过将词法或语法规则转化为C语言代码,实现源代码到目标代码的转换。
拓展内容:Lex文件通常包含三部分:定义、规则和C代码。以下是一个简单的Lex文件示例,用于将输入文本分割成单词和数字,并输出它们。将此文件保存为`lexer.l`,使用Lex工具生成词法分析器。步骤如下:编写Lex文件,使用`lex lexer.l`生成C文件`lex.yy.c`,通过C编译器编译文件`gcc lex.yy.c -o lexer`,最后运行生成的程序`./lexer`。
TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现
本文是 TiDB 源码阅读系列文章的第五篇,主要内容围绕 SQL Parser 功能实现进行讲解。内容源自社区伙伴马震(GitHub ID:mz)的投稿。系列文章的目的是与数据库研究者及爱好者深入交流,收到了社区的积极反馈。后续,期待更多伙伴加入 TiDB 的methodinvocation源码探讨与分享。
TiDB 的源码阅读系列文章,帮助读者系统性地学习 TiDB 内部实现。最近的《SQL 的一生》一文,全面阐述了 SQL 语句处理流程,从接收网络数据、MySQL 协议解析、SQL 语法解析、查询计划制定与优化、执行直至返回结果。
其中,SQL Parser 的功能是将 SQL 语句按照 SQL 语法规则进行解析,将文本转换为抽象语法树(AST)。此功能需要一定背景知识,下文将尝试介绍相关知识,以帮助理解这部分代码。
TiDB 使用 goyacc 根据预定义的 SQL 语法规则文件 parser.y 生成 SQL 语法解析器。这一过程可在 TiDB 的 Makefile 文件中看到,通过构建 goyacc 工具,使用 goyacc 依据 parser.y 生成解析器 parser.go。
goyacc 是 yacc 的 Golang 版本,因此理解语法规则定义文件 parser.y 及解析器工作原理之前,需要对 Lex & Yacc 有所了解。Lex & Yacc 是用于生成词法分析器和语法分析器的工具,它们简化了编译器的编写。
下文将详细介绍 Lex & Yacc 的工作流程,以及生成解析器的过程。我们将从 Lex 根据用户定义的 patterns 生成词法分析器,词法分析器读取源代码并转换为 tokens 输出,以及 Yacc 根据用户定义的语法规则生成语法分析器等角度进行阐述。
生成词法分析器和语法分析器的过程,用户需为 Lex 提供 patterns 的定义,为 Yacc 提供语法规则文件。这两种配置都是文本文件,结构相同,分为三个部分。源码窗口我们将关注中间规则定义部分,并通过一个简单的例子来解释。
Lex 的输入文件中,规则定义部分使用正则表达式定义了变量、整数和操作符等 token 类型。例如整数 token 的定义,当输入字符串匹配正则表达式时,大括号内的动作会被执行,将整数值存储在变量yylval 中,并返回 token 类型 INTEGER 给 Yacc。
而 Yacc 的语法规则定义文件中,第一部分定义了 token 类型和运算符的结合性。四种运算符都是左结合,同一行的运算符优先级相同,不同行的运算符,后定义的行具有更高的优先级。语法规则使用 BNF 表达,大部分现代编程语言都可以使用 BNF 表示。
表达式解析是生成表达式的逆向操作,需要将语法树归约到一个非终结符。Yacc 生成的语法分析器使用自底向上的归约方式进行语法解析,同时使用堆栈保存中间状态。通过一个表达式 x + y * z 的解析过程,我们可以理解这一过程。
在这一过程中,读取的 token 压入堆栈,当发现堆栈中的内容匹配了某个产生式的右侧,则将匹配的项从堆栈中弹出,将该产生式左侧的非终结符压入堆栈。这个过程持续进行,直到读取完所有的 tokens,并且只有启始非终结符保留在堆栈中。
产生式右侧的大括号中定义了该规则关联的动作,例如将三项从堆栈中弹出,两个表达式相加,结果再压回堆栈顶。这里可以使用 $position 的形式访问堆栈中的项,$1 引用第一项,$2 引用第二项,以此类推。$$ 代表归约操作执行后的堆栈顶。本例的动作是将三项从堆栈中弹出,两个表达式相加,结果再压回堆栈顶。
在上述例子中,动作不仅完成了语法解析,还完成了表达式求值。一般希望语法解析的结果是一颗抽象语法树(AST),可以定义语法规则关联的动作。这样,解析完成时,我们就能得到由 nodeType 构成的抽象语法树,对这个语法树进行遍历访问,可以生成机器代码或解释执行。
至此,我们对 Lex & Yacc 的原理有了大致了解,虽然还有许多细节,如如何消除语法的歧义,但这些概念对于理解 TiDB 的代码已经足够。
下一部分,我们介绍 TiDB SQL Parser 的实现。有了前面的背景知识,对 TiDB 的 SQL Parser 模块的理解会更易上手。TiDB 使用手写的词法解析器(出于性能考虑),语法解析采用 goyacc。我们先来看 SQL 语法规则文件 parser.y,这是生成 SQL 语法解析器的基础。
parser.y 文件包含 多行代码,初看可能令人感到复杂,但该文件仍然遵循我们之前介绍的结构。我们只需要关注第一部分 definitions 和第二部分 rules。
第一部分定义了 token 类型、优先级、结合性等。注意 union 结构体,它定义了在语法解析过程中被压入堆栈的项的属性和类型。压入堆栈的项可能是终结符,也就是 token,它的类型可以是 item 或 ident;也可能是非终结符,即产生式的左侧,它的类型可以是 expr、statement、item 或 ident。
goyacc 根据这个 union 在解析器中生成对应的 struct。在语法解析过程中,非终结符会被构造成抽象语法树(AST)的节点 ast.ExprNode 或 ast.StmtNode。抽象语法树相关的数据结构定义在 ast 包中,它们大都实现了 ast.Node 接口。
ast.Node 接口有一个 Accept 方法,接受 Visitor 参数,后续对 AST 的处理主要依赖这个 Accept 方法,以 Visitor 模式遍历所有的节点以及对 AST 做结构转换。例如 plan.preprocess 是对 AST 做预处理,包括合法性检查以及名字绑定。
union 后面是对 token 和非终结符按照类型分别定义。第一部分的最后是对优先级和结合性的定义。文件的第二部分是 SQL 语法的产生式和每个规则对应的 aciton。SQL 语法非常复杂,大部分内容都是产生式的定义。例如 SELECT 语法的定义,我们可以在 parser.y 中找到 SELECT 语句的产生式。
完成语法规则文件 parser.y 的定义后,使用 goyacc 生成语法解析器。TiDB 对 lexer 和 parser.go 进行封装,对外提供 parser.yy_parser 进行 SQL 语句的解析。
最后,我们通过一个简单的例子,使用 TiDB 的 SQL Parser 进行 SQL 语法解析,构建出抽象语法树,并通过 visitor 遍历 AST。我实现的 visitor 只输出节点的类型,运行结果依次输出遍历过程中遇到的节点类型。
了解 TiDB SQL Parser 的实现后,我们有可能实现当前不支持的语法,如添加内置函数。这为我们学习查询计划以及优化打下了基础。希望这篇文章对读者有所帮助。
作者介绍:马震,金蝶天燕架构师,负责中间件、大数据平台的研发,今年转向 NewSQL 领域,关注 OLTP/AP 融合,目前在推动金蝶下一代 ERP 引入 TiDB 作为数据库存储服务。
ç¼è¯åçpdf
ç¼è¯åçpdfæ¯è®¡ç®æºä¸ä¸çä¸é¨éè¦ä¸ä¸è¯¾ãç¼è¯åçæ¯è®¡ç®æºä¸ä¸çä¸é¨éè¦ä¸ä¸è¯¾ï¼æ¨å¨ä»ç»ç¼è¯ç¨åºæé çä¸è¬åçååºæ¬æ¹æ³ãå 容å æ¬è¯è¨åææ³ãè¯æ³åæãè¯æ³åæãè¯æ³å¶å¯¼ç¿»è¯ãä¸é´ä»£ç çæãåå¨ç®¡çã代ç ä¼ååç®æ 代ç çæã
ç¼è¯åçæ¯è®¡ç®æºä¸ä¸è®¾ç½®çä¸é¨éè¦çä¸ä¸è¯¾ç¨ãè½ç¶åªæå°æ°äººä»äºç¼è¯æ¹é¢çå·¥ä½ï¼ä½æ¯è¿é¨è¯¾å¨ç论ãææ¯ãæ¹æ³ä¸é½å¯¹å¦çæä¾äºç³»ç»èææçè®ç»ï¼æå©äºæé«è½¯ä»¶äººåçç´ è´¨åè½åã
ç¼è¯åç课ç¨æ¯è®¡ç®æºç¸å ³ä¸ä¸å¦ççå¿ ä¿®è¯¾ç¨åé«çå¦æ ¡å¹å »è®¡ç®æºä¸ä¸äººæçåºç¡åæ ¸å¿è¯¾ç¨ï¼åæ¶ä¹æ¯è®¡ç®æºä¸ä¸è¯¾ç¨ä¸æé¾åæææå¦ä¹ è½åç课ç¨ä¹ä¸ãç¼è¯åç课ç¨å 容主è¦æ¯åçæ§è´¨ï¼é«åº¦æ½è±¡ã
å¦ä¹ ç¼è¯åçpdfçæ¹æ³ï¼
1ã端æ£è®¤è¯ï¼ç¼è¯åçå¨éæææ¬å¤çä¸æ广æ³åºç¨ï¼æHTMLæ件转å为纯ææ¬ï¼å©ç¨ç¼è¯åçæ¥å®ç°é常ç®åãç解ç¼è¯åççå®ç¨æ§ï¼å¯ä»¥æé«å¦ä¹ å ´è¶£ã
2ãåå¤ç书ï¼æ¯åºæ¬çæ¹æ³ï¼ç书å¯ä»¥è¯»æå¾å¤å 容ã
3ãç»åæºç å¦ä¹ ï¼çæ代ç ï¼æè½è¯´çæ£ç解ç论ãè¦å®å ¨çæyaccç代ç ï¼å·¥ä½éå¾å¤§ï¼åæ ·è¦å ç解ç论ã
4ãå ç¹å°±ç®ï¼é¿é就轻ã对äºè¯æ³åæï¼å¯é¿å èªå¨æºç论åéå论æ¨æ¼çä»ç»ï¼ç´æ¥æ¬åºæºç ï¼éä½ç解é¾åº¦ï¼å¯¹äºè¯æ³åæéå½ä¸éåLLææ³åç¸åºçæºç å¯ç®åä»ç»ï¼è对LRææ³ç解å³å¯ï¼è¿æ ·å¯çæ¶é´å ç¼ååºä¸ä¸ªè½å¤è¿è¡çè¯æ³åæå¨åè¯æ³åæå¨ï¼å¯ä»¥æé«å¦ä¹ 积ææ§ã
深入了解MySQL语法分析器Yacc的原理与实现mysqlyacc
深入了解MySQL语法分析器Yacc的原理与实现
MySQL是一种开源的关系型数据库管理系统,用于管理数据。而Yacc是MySQL语法分析器的重要组成部分,它的功能是将SQL语句转化为内部语法结构,使得数据库可以对这些语句进行解释和处理。在本文中,我们将深入了解MySQL语法分析器Yacc的原理和实现。
一、MySQL语法分析器的工作原理
MySQL语法分析器的工作原理可以简单地概括为:将输入的SQL语句转换为内部数据库结构。其中,语法分析器是一个重要的组件,它的主要作用是将SQL语句解析成MySQL内部数据结构。语法分析器的实现使用了一种叫做Yacc的技术。Yacc是一种工具,它可以解析输入的文本,并且根据指定的语法规则生成分析树。
二、Yacc的基本原理
Yacc是一种基于LR分析算法的语法分析器生成器,它可以自动生成语法分析器。LR分析算法是一种自底向上的语法分析算法,它采用一个堆栈来保存已识别的语法符号,并且可以将它们组合成更多复杂的语法结构。在Yacc中,用户需要定义一组语法规则,以指定输入文本的正确结构和语义。
Yacc的基本原理如下:
1.读取输入文本,将其转换为词汇符号。
2.利用先前定义的语法规则进行分析,并且产生一棵语法分析树。
3.在语法分析树的基础上生成可执行代码,用于执行相应的操作。
三、Yacc与MySQL语法分析器的实现
MySQL语法分析器的实现基于Yacc技术,用户需要使用Yacc的语法描述文件来描述MySQL的语法。在使用Yacc创建MySQL语法分析器时,我们需要依次完成以下步骤:
1.定义MySQL语法的文法:可以使用BNF范式来描述MySQL语法的文法。例如,下面是一条符合MySQL语法的INSERT语句的BNF描述:
INSERT INTO table_name [(column_list)] VALUES (value_list);
2.编写Yacc语法描述文件:用户需要编写一个Yacc语法描述文件来定义MySQL语法分析器的分析规则。该文件包含输入文本的词汇符号、语法规则和语义处理子程序。
3.运行Yacc生成MySQL语法分析器:用户需要运行Yacc生成MySQL语法分析器的源代码。
4.编译生成的源文件:用户需要使用C或C++编译器编译Yacc生成的MySQL语法分析器源文件,生成可执行文件。
5.使用MySQL语法分析器:用户可以使用生成的可执行文件来解析输入的SQL语句,以执行相应的查询操作。
四、示例代码
下面是一个示例Yacc语法描述文件,用于解析MySQL INSERT语句:
%token NAME COMMA LPAREN RPAREN SEMI
%token STRING NUMBER
%%
stmt: INSERT INTO table_name values
{ handle_insert($3,$5); } ;
table_name : NAME
{ $$ = strdup($1); };
values: LPAREN list_of_values RPAREN
{ $$ = $2; } ;
list_of_values: value_list
{ $$ = $1; } ;
value_list: value
{ $$ = new ValueList($1); }
| value_list COMMA value
{ $$ = $1->append($3); } ;
value: STRING
| NUMBER
| NULL_TOKEN
| CURRENT_TIMESTAMP
| function_call
| arithmetic_expression
| logical_expression ;
%%
在上面的语法描述文件中,$表示用来引用匹配的元素。其他的代码用于定义token、规则和语义处理子程序。通过运行Yacc对该文件进行编译,可以自动产生MySQL语法解析器的源代码。接着,我们需要使用C或C++编译器编译该源代码,生成可执行文件。
总结
MySQL语法分析器是MySQL数据库的重要组成部分,它的功能是将输入的SQL语句转化为内部语法结构,使得数据库可以对这些语句进行解释和处理。Yacc是MySQL语法分析器的一个重要工具。它基于LR分析算法,并且可以自动生成语法分析器。通过理解MySQL语法分析器和Yacc的工作原理,我们可以更深入地了解MySQL数据库的内部运作。
编译原理基础内容简介
本书深入剖析了程序设计语言翻译的核心原理和技术,涵盖了编译器构造的关键环节:词法分析、语法分析,通过解析源代码结构;语义分析与中间代码生成,确保程序的正确性;代码优化,提升程序性能;以及目标代码的生成,实现从高级语言到机器语言的转换。
书中详细讲解了编译器编写工具LEx和YAcc的内部机制和实际应用,让读者理解这些工具如何辅助编译过程。此外,还特别关注了语法制导翻译与属性计算、类型与类型检查、数据流分析等前沿技术,这些都是现代编译器构造和程序分析不可或缺的部分。
《编译原理基础》既适合计算机专业的本科和研究生作为教材,也适合软件开发者和程序设计语言爱好者作为参考书。特别地,配套的电子教案资源可在出版社网站免费获取,为学习者提供了丰富的学习辅助材料。