我有以下语法
GUID : GUIDBLOCK GUIDBLOCK '-' GUIDBLOCK '-' GUIDBLOCK '-' GUIDBLOCK
'-'
GUIDBLOCK GUIDBLOCK GUIDBLOCK;
SELF : 'self(' GUID ')';
fragment
GUIDBLOCK: [A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9];
atom : SELF # CurrentGuid
这是我的访客
@Override
public String visitCurrentGuid(CalcParser.CurrentRecordContext ctx) {
System.out.println("Guid is : " + ctx.getText());
System.out.println("Guid is : " + ctx.getChild(0));
return ctx.getText();
}
输入“ self(5827389b-c8ab-4804-8194-e23fbdd1e370)”
只有一个孩子是整个输入本身“ self(5827389b-c8ab-4804-8194-e23fbdd1e370)”
我应该如何获得引导部分?
据我了解,如果我的语法结构是按AST构造的,那么我应该能够打印出树。
我应该如何更新语法?
谢谢
答案 0 :(得分:1)
片段根本不会在AST中出现-基本上就像对待片段一样,直接将它们的内容写在使用它们的词法分析器规则中。因此,将代码移到片段中可以使您的代码更易于阅读,但完全不会影响所生成的AST。
其他词法分析器规则使用的词法分析器规则在该上下文中也被视为片段。也就是说,如果一个词法分析器规则使用另一个词法分析器规则,它仍然会生成一个没有嵌套结构的单个标记-就像您使用了一个片段一样。这是一条词法分析器规则,而不是一个片段,只有在模式独立出现而没有成为较大模式的一部分时,它才有所不同。
关键是词法分析器规则总是产生单个标记,而标记没有子标记。它们是AST的叶子。具有子节点的节点是根据解析器规则生成的。
您拥有的唯一解析器规则是atom
。 atom
仅调用另一个规则SELF
。因此,生成的树将由一个atom
组成,其中包含一个SELF
标记作为其唯一的子代,并且如前所述,标记是叶子,所以这就是树的结尾。
要获得有用的树,您可能要做的是使GUIDBLOCK
成为词法分析器规则(实际上是您唯一的词法分析器规则),然后将其他所有内容转换为解析器规则。这也意味着您可以摆脱atom
(如果需要,可以将SELF
重命名为atom
)。
然后,您将最终得到一棵由self
(如果重命名为atom
)节点组成的树,该节点包含一个'self('
令牌,一个{{1 }}节点(您可能希望分配一个名称以便于访问)和一个guid
令牌。 )
节点又将包含guid
和GUIDBLOCK
令牌的序列。您还可以在每次使用'-'
之前添加blocks+=
,以获得仅包含GUIDBLOCK
标记而不包含破折号的列表。
将GUIDBLOCK
转换为两个令牌(即'self('
)也很有意义-特别是如果您想添加规则以忽略空白的情况下。