《ANTLR 4权威指南》——2.2节实现一个语法分析器

简介:

本节书摘来自华章社区《ANTLR 4权威指南》一书中的第2章,第2.2节实现一个语法分析器,作者[美] 特恩斯·帕尔(Terence Parr),更多章节内容可以访问云栖社区“华章社区”公众号查看

2.2 实现一个语法分析器
ANTLR工具依据类似于我们之前看到的assign的语法规则,产生一个递归下降的语法分析器(recursive-descent parser)。递归下降的语法分析器实际上是若干递归方法的集合,每个方法对应一条规则。下降的过程就是从语法分析树的根节点开始,朝着叶节点(词法符号)进行解析的过程。首先调用的规则,即语义符号的起始点,就会成为语法分析树的根节点。在前一节的例子中,就是调用stat()方法作为起始点的。这种解析过程的更广为人知的名字是“自上而下的解析”,递归下降的语法分析器仅仅是自上而下的语法分析器的一种实现。
下面是一个ANTLR根据assign规则生成的方法(稍微经过格式整理),用于展示递归下降的语法分析器的实现细节:

递归下降的语法分析器最神奇的地方在于,通过方法stat()、assign()和expr()的调用描绘出的调用路线图映射到了语法分析树的节点上(请迅速回顾一下图2-1)。调用match()对应了语法分析树的叶子节点。在手工构造的语法分析器中,我们需要在每条规则对应的方法的开始位置插入“增加一个新的子树根节点”这样的操作,在match()方法中插入“增加一个新的叶子节点”这样的操作。
assign()方法仅仅验证所有的词汇符号都存在且顺序正确。当语法分析器进入assign()方法的内部时,仅有一个备选分支(alternative),无须做出选择。一个备选分支指的是规则的右侧定义的多个方案之一。例如,除了assign之外,下面的stat规则还可能对应其他多种语句。


621564bfd526b8252ba5378b132d755dbe1248c0

stat()方法必须通过检查下一个词法符号来做出语法分析决策(parsing decision)或者预测(prediction)。做出决策的过程实际上就是判断哪一个备选分支是正确的。在上面的例子中,一个WHILE关键字意味着它选择stat规则的第三个备选分支。因此,stat()方法将调用whilestat()方法。你可能听说过前瞻词法符号(lookahead token)这个术语,它其实就是下一个输入的词法符号。一个前瞻词法符号是指任何一个在被匹配和消费之前就由语法分析器嗅探出的词法符号。有些时候,语法分析器需要很多个前瞻词法符号来判断语义规则的哪个方案是正确的,甚至可能要从当前的词法符号的位置开始,一直分析到文件末尾才能做出判断!ANTLR默默地帮你完成了所有的这些工作,不过,对其决策过程的基本理解将会有助于调试ANTLR自动生成的语法分析器。
为了让语法分析的决策过程可视化,想象一个迷宫,它只有一个入口和一个出口,迷宫的地板上写着单词。每个从入口到出口的路径上的单词序列代表一个语句。这个迷宫的结构就好比是一种语言所定义的全部语法规则。为了测试一个语句是不是合法,我们将这个语句中的单词和迷宫的地板上的单词比较,然后沿着这个语句的单词所描述的路径在迷宫中前进。如果我们能够通过这个语句中的单词序列指定的路径到达出口,那么这个语句就是合法的。
为了到达迷宫的出口,我们必须在每个分岔路口选择一条正确的路径,就好像一个语法分析器要在多个备选分支中做出选择一样。我们必须将语句中接下来的若干个单词与站在路口所看到的不同岔路地板上的单词相比较,从而决定走哪条岔路。我们站在路口所看到的地板上的单词就好像是前瞻词法符号。显然,若每条岔路都以一个独一无二的单词开始,做出选择就会容易许多。在上例中的stat规则中,每个备选分支都是以一个独一无二的词法符号开始的,因此stat()方法可以通过检查第一个前瞻词法符号来区分不同的备选分支。
当每条岔路的起始单词有重复的时候,语法分析器就需要更多地进行前瞻,即通过扫描更多的单词来区分不同的备选分支。在每次语法分析决策中,ANTLR能够根据情况自动调整前瞻的数量。如果通过前瞻,我们能够经多条路径抵达迷宫出口(文件末尾),那就意味着能够用多种语义去解释当前的输入文本。解决这种歧义是我们下一节的任务,之后,我们将会学习如何使用语法分析树来构建语言类应用程序。

相关文章
|
算法 5G UED
5G 无线关键技术|带你读《5G无线网络规划与设计》之九
高频频段可泛指 6 GHz 以上频段,主要针对毫米波频段,该频段频谱资源丰富,易于获得大带宽连续频谱,适用于有极高用户体验速率和小区容量要求的热点区域。但其覆盖能力弱,无法实现连续覆盖,因此,5G 仍然需要依托中、低频段满足覆盖需求,保障网络的连续性和可靠性。
5G 无线关键技术|带你读《5G无线网络规划与设计》之九
|
编译器 C++ 前端开发
带你读《LLVM编译器实战教程》之三:工具和设计
本书的前半部分将向您介绍怎么样去配置、构建、和安装LLVM的不同软件库、工具和外部项目。接下来,本书的后半部分将向您介绍LLVM的各种设计细节,并逐步地讲解LLVM的各个编译步骤:前段、中间表示(IR)、后端、即时编译(JIT)引擎、跨平台编译和插件接口。本书包含有大量翔实的示例和代码片段,以帮助读者平稳顺利的掌握LLVM的编译器开发环境。
|
量子技术 算法
带你读《量子编程基础》之三:量子程序的语法与语义
本书讨论了如何扩展当前计算机的新程序设计方法和技术,以利用量子计算机的独特能力。相比于现有计算机系统,量子计算机在处理速度上具有显著优势。世界各地的政府和企业都投入了大量资金,希望建造实用的量子计算机。本书结合作者在量子计算领域多年的研究经验,并辅以大量的例子和插图,介绍了量子编程语言及其所需的重要工具和技术,对于学者、研究人员和开发人员来说都是非常宝贵的参考资料。
|
JavaScript Java Unix
《ANTLR 4权威指南 》一第一部分 Part 1
在本书的第一部分中,我们的目标是大体上知道ANTLR能做什么。除此之外,我们还希望探究语言类应用程序的架构。在概览之后的第2章中,我们将会通过许多真实的例子来循序渐进地、系统性地学习ANTLR。
3824 0
|
2天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
262 116
|
17天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
11天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
653 223