《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的知识——我们回到了自己熟悉的领域,即写普通的代码而不是处理语言识别问题。

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

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

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

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

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

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

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

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

最后,让我们一起完成这个翻译器,并使用样例输入来测试。
《ANTLR 4权威指南》——3.4 构建一个语言类应用程序

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

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

上一篇:C#语言之“中英文混合字符串对齐”的方法【转】


下一篇:三大主流iSCSI Initiator软件对比分析