如何解决ANTLR:过于贪婪的规则
看起来我在理解过于贪婪的规则匹配时遇到了问题。我正在尝试对 .g4
文件进行语法着色。以下是使此问题可重现的最小(简化)摘录:
lexer grammar ANTLRv4Lexer;
Range
: '[' RangeChar+ ']'
;
fragment EscapedChar
: '\\' ~[u]
| '\\u' EscapedCharHex EscapedCharHex EscapedCharHex EscapedCharHex
;
fragment EscapedCharHex
: [0-9A-Fa-f]
;
fragment RangeChar
: ~']'
| EscapedChar
;
Punctuation
: [:;()+\->*[\]~|]
;
Identifier
: [a-zA-Z0-9]+
;
Whitespace
: [ \t]+
-> skip
;
Newline
: ( '\r' '\n'?
| '\n'
)
-> skip
;
LineComment
: '//' ~[\r\n]*
;
(不完整的)测试文件如下:
: (~ [\]\\] | EscAny)+ -> more
;
// ------
fragment Id
: NameStartChar NameChar*
;
String2Part
: ( ~['\\]
| EscapeSequence
)+
;
我不明白为什么它如此贪婪地匹配 Range
:
[@0,3:3=':',<Punctuation>,1:3]
[@1,5:5='(',1:5]
[@2,6:6='~',1:6]
[@3,8:135='[\]\\] | EscAny)+ -> more\r\n ;\r\n\r\n // ------\r\n\r\nfragment Id\r\n : NameStartChar NameChar*\r\n ;\r\n\r\n\r\nString2Part\r\n\t: ( ~['\\]',<Range>,1:8]
[@4,141:141='|',13:3]
[@5,143:156='EscapeSequence',<Identifier>,13:5]
[@6,162:162=')',14:3]
[@7,163:163='+',14:4]
[@8,167:167=';',15:1]
[@9,170:169='<EOF>',<EOF>,16:0]
我明白为什么在第一行它匹配 [
、\]
和 \\
,但为什么它显然将 ]
视为 RangeChar
?
解决方法
您的词法分析器使用 stackblitz
替代项匹配 \
中的第一个 \\]
,然后将剩余的 ~']'
作为 \]
匹配。这样做的原因是这种解释会导致比 EscapedChar
是 \\
和 EscapedChar
是范围的结尾的匹配更长的匹配,并且当有多种有效方法可以匹配一个词法规则,ANTLR 总是选择最长的(除非涉及到 ]
)。
要解决此问题,您应该更改 *?
,以便只允许将反斜杠作为转义序列的一部分,即将 RangeChar
替换为 ~']'
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。