Antlr4 语义词缀谓词性能

Antlr4 语义词缀谓词性能,antlr4,Antlr4,我有一个lexer为传递给lexer的宏字符串的动态列表创建宏标记。我在顶级词法规则中使用了语义谓词来实现此功能: MACRO: { macros != null && tryMacro() }? .; 其中tryMacro()只检查是否有宏字符串与输入序列匹配 这种方法的性能非常差,经过一些研究后,我尝试将lexer规则更改为以下内容: MACRO: . { macros != null && tryMacro() }?; 这大大提高了性能,但我真的不明白为

我有一个lexer为传递给lexer的宏字符串的动态列表创建宏标记。我在顶级词法规则中使用了语义谓词来实现此功能:

MACRO: { macros != null && tryMacro() }? .;
其中
tryMacro()
只检查是否有宏字符串与输入序列匹配

这种方法的性能非常差,经过一些研究后,我尝试将lexer规则更改为以下内容:

MACRO: . { macros != null && tryMacro() }?;

这大大提高了性能,但我真的不明白为什么。:)因为“.”匹配任何字符,语义谓词规则的调用次数应该和以前一样多,不是吗?有人能为这种行为提供解释吗?

原因很简单:如果您将谓词放在开头,词法分析器将对其进行计算,以决定是否应应用
规则。如果将其放在末尾,它将仅在与
规则可能匹配时执行检查

由于
非常通用,我想您应该将它放在规则的末尾,并且由于规则的限制,它肯定会在最后尝试。它只能匹配单字符标记,因此更精确的规则将是优先考虑的


如果
规则被更优先的规则取代,则不会考虑它,也不会调用您的谓词。

我对此进行了进一步调试,结果发现规则的重新排序改变了lexer的行为,导致宏在解析期间不被接受。感知性能提高的原因是,在词法分析器在进行预测时放弃规则之前,语义谓词只被评估了几次。因此,规则的更改实际上是无效的,并不是性能的改进


通过将宏处理移到解析器,我最终解决了性能问题

这个问题是众所周知的。我在我的ANLTR4C++目标博客中描述了:规则左侧的谓词阻止为其生成的DFA不被缓存,而是导致它们被反复计算。如果你有很多alt,例如很多关键字(lexer规则有点像隐藏根上下文的alt)。@MikeLischke你的链接断了:(我移动了网站。链接已更改为: