Since ANTLR 4.2
1 解析树匹配
使用访问器和监听器可以实现DOM访问和模拟SAX事件处理。
如,只关心Java方法声明,并且有一个Java.g4文件,可以在JavaBaseListener中覆盖方法。ParseTreeWalker可以在遍历树时调用覆盖后的方法。
这种机制是建立在节点粒度的。也就是说,对于子树中的节点也可能被调用。
常用于以下用途:
- 收集在特定上下文(如嵌套方法)中收集方法声明。
- 根据模式分组翻译。
- 收集整个树中的变量赋值。
因为讨论的是解析树,而不是抽象语法树,因此可以使用更加具体的模式。
2 解析树模式
用于验证子树是否具有特定结构。
定义如下:
1 | <ID> = <expr>; |
其中,expr代表任意记号或规则。
使用如下:
1 | ParseTree t = ...; // assume t is a statement |
如需要找出加0的记号:
1 | ParseTree t = ...; // assume t is an expression |
输出匹配的子树,此处为记号:
1 | String id = m.get("ID"); |
设置tag分割符?
1 | ParseTreePatternMatcher m = new ParseTreePatternMatcher(); |
This would allow pattern <<ID>> = <<expr>> ;$<< ick $>>
to be interpreted as elements: ID
, =
, expr
, and ;<< ick >>
.
(1) 模式标签
get()和getAll()可用于获取匹配的子树。
其中get()只返回匹配的第一个子树。
可以使用标签标记记号或规则。匹配的结果将包含标签显式标记的记号或规则,以及标记和未标记的完整集合。
如对于标签foo,将返回:
<foo:anyRuleName>和<foo:AnyTokenName>
<anyLabel:foo>
<foo>
(2) 使用模式matcher创建解析树
ParseTreePattern.getPatternTree()
3 使用XPath识别解析树节点集合
XPath path是代表节点或子树的字符串。
path通常有节点名称和以下分隔符组成:
Expression | Description |
---|---|
nodename | 标记或规则的节点名称 |
/ | 根节点 |
// | 所有匹配的节点 |
! | 除此以外的节点 |
理解:路径匹配
示例:
1 | /prog/func, -> all funcs under prog at root |
常见的遍历方法:
1 | for (ParseTree t : XPath.findAll(tree, xpath, parser) ) { |
示例:获取匹配规则或记号的名称
1 | List<String> nodes = new ArrayList<String>(); |
4 结合XPath和树模式
1 | // assume we are parsing Java |