《ANTLR 4权威指南》——2.5 语法分析树监听器和访问器

简介:

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

2.5 语法分析树监听器和访问器

ANTLR的运行库提供了两种遍历树的机制。默认情况下,ANTLR使用内建的遍历器访问生成的语法分析树,并为每个遍历时可能触发的事件生成一个语法分析树监听器接口(parse-tree listener interface)。监听器非常类似于XML解析器生成的SAX文档对象。SAX监听器接收类似startDocument()和endDocument()的事件通知。一个监听器的方法实际上就是回调函数,正如我们在图形界面程序中响应复选框点击事件一样。除了监听器的方式,我们还将介绍另外一种遍历语法分析树的方式:访问者模式(vistor pattern)。

1.语法分析树监听器

为了将遍历树时触发的事件转化为监听器的调用,ANTLR运行库提供了ParseTree-Walker类。我们可以自行实现ParseTreeListener接口,在其中填充自己的逻辑代码(通常是调用程序的其他部分),从而构建出我们自己的语言类应用程序。

ANTLR为每个语法文件生成一个ParseTreeListener的子类,在该类中,语法中的每条规则都有对应的enter方法和exit方法。例如,当遍历器访问到assign规则对应的节点时,它就会调用enterAssign()方法,然后将对应的语法分析树节点——AssignContext的实例——当作参数传递给它。在遍历器访问了assign节点的全部子节点之后,它会调用exitAssign()。图2-4用粗虚线标识了ParseTreeWalker对语法分析树进行深度优先遍历的过程。

image

除此之外,图2-4中还标识出了遍历过程中ParseTreeWalker调用assign规则的enter和exit方法的时机(其中未显示监听器其他方法的调用)。图2-5显示了在我们的赋值语句生成的语法分析树中,ParseTreeWalker对监听器方法的完整的调用顺序。

image

监听器机制的优秀之处在于,这一切都是自动进行的。我们不需要编写对语法分析树的遍历代码,也不需要让我们的监听器显式地访问子节点。

2.语法分析树访问器

有时候,我们希望控制遍历语法分析树的过程,通过显式的方法调用来访问子节点。在命令行中加入-visitor选项可以指示ANTLR为一个语法生成访问器接口(visitor interface),语法中的每条规则对应接口中的一个visit方法。图2-6是使用常见的访问者模式对我们的语法分析树进行操作的过程。

image

其中,粗虚线显示了对语法分析树进行深度优先遍历的过程。细虚线标示出访问器方法的调用顺序。我们可以在自己的程序代码中实现这个访问器接口,然后调用visit()方法来开始对语法分析树的一次遍历。
image

ANTLR内部为访问者模式提供的支持代码会在根节点处调用visitStat()方法。接下来,visitStat()方法的实现将会调用visit()方法,并将所有子节点当作参数传递给它,从而继续遍历的过程。或者,visitMethod()方法可以显式调用visitAssign()方法等。

ANTLR会提供访问器接口和一个默认实现类,免去我们一切都要自行实现的麻烦。这样,我们就可以专注于那些我们感兴趣的方法,而无须覆盖接口中的方法。我们将在第7章中深入介绍访问器和监听器。

image

迄今为止,我们已经大体上了解了ANTLR的工作原理。在本章中,我们认识了从字符序列到语法分析树的整个流程,学习了ANTLR运行库的一些关键类。此外,我们还简单了解了监听器和访问器机制,它们是连接语法分析器和特定程序代码的桥梁。在下一章中,我们将通过一个实际的例子来使大家加深对上述概念的理解。

相关文章
|
5天前
|
Python 缓存
Python ChainMap:链式映射的妙用与实战解析
【4月更文挑战第1天】Python中的`collections`模块提供了一个名为`ChainMap`的类,它实现了多个字典的链式查找。`ChainMap`将多个字典组织成一个逻辑上的单一字典,允许你像操作单个字典一样来访问这些字典。当在`ChainMap`中查找一个键时,它会按照字典被添加的顺序从前向后依次查找,直到找到匹配的键为止。如果找不到,就会抛出`KeyError`。
|
5天前
|
算法 编译器 C++
【C++ 函数 基本教程 第二篇 】深度剖析C++:作用域与函数查找机制
【C++ 函数 基本教程 第二篇 】深度剖析C++:作用域与函数查找机制
35 0
|
SQL 数据库
CRUP为后面使用框架在页面上增删改查做下铺垫.(一)
CRUP为后面使用框架在页面上增删改查做下铺垫.(一)
117 0
CRUP为后面使用框架在页面上增删改查做下铺垫.(一)
CRUP为后面使用框架在页面上增删改查做下铺垫.(二)
CRUP为后面使用框架在页面上增删改查做下铺垫.(二)
74 0
|
JavaScript 前端开发 API
WebApi入门第六章( DOM节点 )
WebApi入门第六章( DOM节点 )
110 0
WebApi入门第六章( DOM节点 )
|
存储 Java
初识二叉树,领悟树的概念 | 带你学《Java语言高级特性》之三十八
在之前的学习中我们接触过链表数据结构的相关内容,其查询操作的时间复杂度为O(n),这对大量数据来说显然是很损耗性能的。本节将为读者介绍一种新的数据结构:二叉树。
初识二叉树,领悟树的概念 | 带你学《Java语言高级特性》之三十八
|
Web App开发 Android开发
第二十章:异步和文件I/O.(二十三)
回到网上在本章之前,本书中唯一的异步代码涉及使用可移植类库WebRequest中唯一可用于此目的的合理类进行Web访问。 WebRequest类使用称为异步编程模型或APM的旧异步协议。 APM涉及两种方法,在WebRequest的情况下,这些方法称为BeginGetResponse和EndGetResponse。
718 0