我正在阅读明确的ANTLR4引用,并且对其中一个示例有疑问(p。76):
STRING: '"' (ESC|.)*? '"';
fragment
ESC: '\\"' | '\\\\' ;
该规则与典型的C++字符串匹配-
""
中包含的char序列,也可以包含\"
。在我的期望中,由于非贪心的构造,规则
STRING
应该匹配最小的字符串。因此,如果看到\"
,它将在规则末尾将\
映射到.
,将"
映射到"
,因为这将导致尽可能小的字符串。取而代之的是,将\"
映射到ESC
。我有一个理解上的问题,因为这不是我所期望的。这里到底发生了什么?就是这样吗,一个单独的DFA首先匹配
(ESC|.)
,另一个DFA使用已经匹配的STRING
构造字符串匹配(ESC|.)
?我不得不承认我还没有读完这本书。 最佳答案
ANTLR 4词法分析器通常以最长匹配获胜的方式运行,而不考虑语法中替代项出现的顺序。如果两个词法分析器规则匹配相同的最长输入序列,则只有将这些规则的相对顺序进行比较,才能确定 token 类型的分配方式。
一旦词法分析器到达非贪婪的可选内容或闭包,规则内的行为就会发生变化。从那一刻到规则结束,该规则内的所有替代项将被视作有序处理,并且具有最低替代项的路径将获胜。由于the way we order alternatives in the underlying ATN representation,这种看似奇怪的行为实际上是造成非贪婪处理的原因。当词法分析器处于此模式下并到达块(ESC|.)
时,排序约束要求它在可能的情况下使用ESC
。
关于antlr - ANTLRv4 : non-greedy rules,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18787242/