我需要获取每条规则的开始和结束索引。即,开始索引是属于规则的第一个标记的第一个字符的字符位置,而结束索引是属于该规则的最后一个标记的最后一个字符位置。使用这些数字,我可以精确地从输入文件中裁剪出规则的结果。
这种直截了当的方式应该是使用$start
和$stop
令牌,即$start.getStartIndex()
和$stop.getStopIndex()
。但是,即使在$stop
操作中使用,我也遇到null
令牌通常为@after
。
根据确定的Antlr4引用,$stop
令牌定义为:“要匹配的最后一个非隐藏通道令牌
按照规则。在提到当前规则时,
此属性仅适用于after和
最后的动作。“听起来好像这样的标记应该存在(至少对于任何匹配至少一个标记的规则而言)。因此,很多情况下,为什么这个标记是null
是很奇怪的(即使对于那些规则来说也是如此)一个简单的标记 - 不是一个子标记 - 作为它们的最后一个标记。在这种情况下,停止标记如何成为null
?
现在,我正在使用一种解决方法,只需询问有关其当前令牌的输入,移回一个令牌并将此令牌用作stop
令牌。然而,这看起来很糟糕:
@after {
int start = $start.getStartIndex();
int stop = _input.get(_input.index()-1).getStopIndex();
// do something with start and stop
}
更干净的解决方案(如果stop
不为null)应如下所示:
@after {
int start = $start.getStartIndex();
int stop = $stop.getStopIndex();
}
答案 0 :(得分:3)
在执行任何用户定义的finally
操作后,在生成的代码中的@finally{}
块中设置停止标记。 @after{}
代码在try
块中执行,该代码也在设置停止令牌之前发生。
stop
属性仅适用于限定引用。例如,您可以执行以下操作:
foo : bar {assert $bar.stop != null};
另请注意,ANTLR 4旨在鼓励将操作代码从嵌入操作重定位到解析完成后在解析树上操作的侦听器和/或访问者接口。以这种方式使用时,将为树中的所有上下文设置停止令牌。几乎在所有情况下,使用@after
或@finally
块都是ANTLR 4中的代码气味,应该避免使用。