这个问题参考了书中的Cymbol代码(~第143页):
int t = ctx.type().start.getType(); // in DefPhase.enterFunctionDecl()
Symbol.Type type = CheckSymbols.getType(t);
每个组件返回什么:"ctx.type()"、"start"、"getType()"?这本书对这些名字没有任何解释。
我可以"有点"理解"ctx.type()"指的是"type"规则,而"getType()"返回与之相关的数字。但"start"到底做什么?
此外,为了概括这个问题:获取规则返回的值/结构的机制是什么——尤其是在侦听器中使用的情况下?
我可以看到,对于ID,它是:
String name = ctx.ID().getText();
如上所述,对于关键字的枚举,它是通过"start.getType()"实现的。我应该知道还有其他特殊类型的访问吗?
让我们逐步分解问题。显然,ctx
是CymbolParser.FunctionDeclContext
的实例。在第98-99页上,您可以看到语法和ParseTree是如何实现的(至少感觉是这样的——对于真正的实现,请参阅.g4
文件)。
看看第99页AST的图,您可以看到节点FunctionDeclContext
有几个子节点,其中一个标记为type
。直观地看,它在某种程度上与函数返回类型相对应。这是您在调用CymbolParser.FunctionDeclContext::type
时检索到的节点。返回类型可能类似于TypeContext
。
请注意,开头没有"get"的方法通常是子getter,例如,您可以通过调用CymbolParser.FunctionDeclContext::block
来访问块。
因此,您获得了所传递方法的类型上下文。您可以在任何上下文上调用begin
或end
,以获取定义上下文的最后一个Token
中的第一个。只需start
即可获得"第一个单词"。在这种情况下,第一个Token
当然是函数返回类型itsef,例如int
。
最后一个调用Token::getType
返回Token
的积分表示。
您可以在API参考网页上找到更多信息-上下文,令牌。但理解行为的最好方法是阅读生成的ANTLR类,如<GrammarName>Parser
等。为了完整起见,我在书中附上了一个链接。