SE04-Parse Tree

Parboiled 在规则执行阶段以可选的方式支持构建一个解析树。查看解析树可以更好的理解你的解析器对输入的消费过程,因此有助于解析器的开发和调试。

由 Parboiled 创建的解析树由一系列实现 Node 接口的不可变对象组成。除了基本的树节点功能(父亲、儿子)之外,该接口定义了节点名、所匹配输入文本的起始终止位置,以及一个自定义值对象。一些工具类为解析树提供了额外的处理方法,有 ParseTreeUtils、TreeUtils、GraphUtils。

需要注意的是解析树的节点是不可变的,即一旦被创建则不再能被修改。这实际上意味着它们的子节点结构和它们的值对象“引用”不能被修改。(尽管它们的值对象可以是可变的,或者仍然能够被修改。)整个解析树会从底向上被构建,先从叶子节点开始。通常来说,如果开启了解析树构建选项,匹配成功的每个规则都会创建一个解析树节点,该节点将匹配成功的子规则所创建的节点作为子节点。匹配失败的规则不会创建节点。解析树可以被认为是“已匹配规则的记录”。Parboiled 将解析树节点的 value 字段值设置为节点构造时值栈的栈顶元素。因此产看解析树值对象可以为你提供解析器如何使用值栈的线索。

或许对解析树最有用的使用方式是使用 ParseTreeUtils 的 printNodeTree 来将其打印出来。

在 Java 中开启解析树构建

可以在解析器实现类上添加 @BuildParseTree 注解来开启解析树构建。还可以在解析器方法上使用 @SuppressNode/@SuppresssSubnodes/@SkipNode 来对解析树进行微调。

在 Scala 中开启解析树构建

在 Scala 中,Parser 特质拥有一个 buildParseTree 标记方法,将其设置为 true 则可以开启解析树构建。最简单的方式是在解析器类的构造方法上调用 .withParseTreeBuilding() 方法。类似 Java API,可以使用 Parser$RuleOption 中的选项来对解析树的构建过程进行微调。