《ANTLR 4权威指南》——3.4 构建一个语言类应用程序

简介:

本节书摘来自华章计算机《ANTLR 4权威指南》一书中的第3章,第3.4节,作者[美] 特恩斯·帕尔(Terence Parr),张博 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.4 构建一个语言类应用程序

我们继续完成能够处理数组初始化语句的示例程序,下一个目标是能够翻译初始化语句,而不仅仅是能够识别它们。例如,我们想要将Java中,类似{ 99, 3, 451 }的short数组翻译成"u0063u0003u01c3"。注意,其中十进制数字99的十六进制表示是63。

为了完成这项工作,程序必须能够从语法分析树中提取数据。最简单的方案是使用ANTLR内置的语法分析树遍历器进行深度优先遍历,然后在它触发的一系列回调函数中进行适当的操作。正如我们之前看到的那样,ANTLR能够自动生成一个监听器接口和一个默认的实现类。这样的监听器非常类似于图形界面程序控件上的回调函数(例如,当一个按钮被按下时,它会通知我们)或者XML解析器中的SAX事件。

我们如果想要通过编写程序来操纵输入的数据的话,只需要继承ArrayInitBaseListener类,然后覆盖其中必要的方法即可。我们的基本思想是,在遍历器进行语法分析树的遍历时,令每个监听器方法翻译输入数据的一部分并将结果打印出来。

监听器机制的优雅之处在于,我们不需要自己编写任何遍历语法分析树的代码。事实上,我们甚至都不知道ANTLR运行库是怎么遍历语法分析树、怎么调用我们的方法的。我们只知道,在语法规则对应的语句的开始和结束位置处,我们的监听器方法可以得到通知。在7.2节我们会看到,这种机制使得我们不需要了解太多ANTLR的知识——我们回到了自己熟悉的领域,即写普通的代码而不是处理语言识别问题。

一个进行翻译工作的项目意味着要处理这样的问题:如何将输入的词法符号或者词组翻译成输出字符串。为了达到这个目标,最好先从手工翻译一些有代表性的样例入手,想办法提取出通用的转换逻辑。在下例中,转换过程是非常直截了当的。
image

用自然语言解释,翻译过程就是一系列“X映射为Y”的过程:

1)将{翻译为"。
2)将}翻译为"。
3)将每个整数翻译为四位的十六进制形式,然后加前缀u。

为此,我们需要编写方法,在遇到对应的输入词法符号或者词组的时候,打印出转换后的字符串。内置的语法分析树遍历器会在各种词组的开始和结束位置触发监听器的回调函数。下面是遵循我们的翻译规则的一个监听器的实现类。

image

我们不需要覆盖每个enter/exit方法,我们只需要覆盖自己需要的那些。上述代码中唯一令我们不那么熟悉的一个表达式是ctx.INT(),它从上下文对象中获取INT词法符号对应的整数值,该词法符号由匹配value规则得来。现在,剩下的事情就是把之前的Test类扩展成一个翻译程序了。

image
image

这份代码和之前代码的唯一区别在于高亮标识的部分,它新建了一个语法分析树遍历器,令其对语法分析器生成的语法分析树进行遍历。在遍历器的遍历过程中,它触发了我们的ShortToUnicodeString监听器的回调函数。请注意:限于篇幅,为了使读者的注意力更加集中,在本书剩下的章节中,通常仅给出代码的关键部分而非完整代码。此外,你还可以从本书的网站上获取完整的代码压缩包。

最后,让我们一起完成这个翻译器,并使用样例输入来测试。
image

一切顺利。无须深入理解语法的细节,我们就完成了我们的第一个翻译器。我们所做的一切不过是实现了几个方法,在这些方法中打印出对输入文本的适当的翻译结果。另外,我们可以通过给遍历器传递一个不同的监听器以实现完全不同的输出。监听器有效地将语言类应用程序和语法进行了解耦,从而使得同一个语法能够被不同的程序复用。

下一章,我们将快速学习ANTLR语法的编写方法,以及让ANTLR语法如此强大和易用的关键特性。

相关文章
|
6月前
|
Go 开发者
Go语言自定义包:构建你的编程工具库
Go语言自定义包:构建你的编程工具库
51 0
|
7月前
|
Go 虚拟化 云计算
如何在 Go 语言开发的宿主程序中嵌入 WebAssembly
如何在 Go 语言开发的宿主程序中嵌入 WebAssembly
91 0
|
7月前
|
弹性计算 JavaScript 开发工具
语言入门-1:环境构建
本实验将介绍TypeScript语言的安装和基本用法。
36 0
|
9月前
|
算法 Java 程序员
01-C++核心语法|C++概述【C++简介、C++起源、可移植性和标准、为什么C++会成功、从一个简单的程序开始认识C++】
复习`C++核心语法`,且适当进行汇编探索底层实现原理,进一步夯实基础,为以后的`底层开发`、`音视频开发`、`跨平台开发`、`算法`等方向的进一步学习埋下伏笔。
01-C++核心语法|C++概述【C++简介、C++起源、可移植性和标准、为什么C++会成功、从一个简单的程序开始认识C++】
|
11月前
|
Rust 前端开发 JavaScript
2023年语言和框架我们值得关注什么?
前端新技术一如既往的更新迭代快:前几天 Next.js 大会,邀请了 vercel 的 CEO 来讲 vercel 的认知。顺带推出了 turbopack,号称比 webpack 快 700 倍,比 vite 快 10 倍。又有很多前端同学在问,我们要学 Rust 了吗?新的内容更新迭代太快了,我们跟不上?今年的终端 D2 会有哪些内容?会不会讲 Rust?
179 0
|
Rust 前端开发 JavaScript
2022年语言和框架我们值得关注什么?
前端新技术一如既往的更新迭代快:前几天Next.js大会,邀请了vercel的CEO来讲vercel的认知。顺带推出了turbopack,号称比webpack快700倍,比vite快10倍。又有很多前端同学在问,我们要学Rust了吗?新的内容更新迭代太快了,我们跟不上?今年的终端D2会有哪些内容?会不会讲Rust?
106 0
|
开发框架 自然语言处理 前端开发
一种新的DSL生成和通用语言框架:pypy
本文关键字:DSL框架和自动化生成工具,pypy as dsl framework and jit framework
808 0
一种新的DSL生成和通用语言框架:pypy
整装待发-实操程序国际化 | 带你学《Java语言高级特性》之二十九
在前两节了解了程序国际化的基本内容,并能够实现对相关功能的使用后,现在让我们一起来实操一个程序,使其完成国际化。
整装待发-实操程序国际化 | 带你学《Java语言高级特性》之二十九