Antlr 太贪婪的规则
看起来我在理解过于贪婪的规则匹配时遇到了问题。我正在尝试将一个Antlr 太贪婪的规则,antlr,antlr4,Antlr,Antlr4,看起来我在理解过于贪婪的规则匹配时遇到了问题。我正在尝试将一个.g4文件用于语法着色。以下是使该问题重现的最小(简化)摘录: lexer grammar ANTLRv4Lexer; Range : '[' RangeChar+ ']' ; fragment EscapedChar : '\\' ~[u] | '\\u' EscapedCharHex EscapedCharHex EscapedCharHex EscapedCharHex ; fr
.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
)+
;
我不明白为什么它与范围
匹配得如此贪婪:
[@0,3:3=':',<Punctuation>,1:3]
[@1,5:5='(',<Punctuation>,1:5]
[@2,6:6='~',<Punctuation>,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='|',<Punctuation>,13:3]
[@5,143:156='EscapeSequence',<Identifier>,13:5]
[@6,162:162=')',<Punctuation>,14:3]
[@7,163:163='+',<Punctuation>,14:4]
[@8,167:167=';',<Punctuation>,15:1]
[@9,170:169='<EOF>',<EOF>,16:0]
[@0,3:3=':',1:3]
[@1,5:5='(',,1:5]
[@2,6:6='~',,1:6]
[@3,8:135='[\]\\]\124; EscAny)+->更多\r\n\r\n\r\n/----\r\n\r\n片段Id\r\n:NameStartChar NameChar*\r\n\r\n\r\n\r\nString2Part\r\n\t:(~['\\]',1:8]
[@4,141:141='|',,13:3]
[@5143:156='EscapeSequence',13:5]
[@6,162:162=')',,14:3]
[@7,163:163='+',,14:4]
[@8,167:167=';',,15:1]
[@9,170:169='',,16:0]
我理解为什么在第一行中它与
[
,\]
和\\
匹配,但是为什么它显然将]
视为RangeChar
?您的lexer使用~']
替代项匹配\\\]
中的第一个\
,然后将剩余的\]
作为转义字符匹配。它这样做的原因是,这种解释导致的匹配比\\
是转义字符
和]
是范围结束的情况更长,并且当有多种有效方法匹配词法规则时,ANTLR总是选择最长的一种(除非涉及*?
)
要解决此问题,您应该更改RangeChar
,以便反斜杠只允许作为转义序列的一部分,即将~']'
替换为~[\]\\]
您的lexer使用~']
选项匹配\\]
中的第一个\
,然后将剩余的\]
作为转义字符进行匹配。它这样做的原因是,这种解释导致的匹配比\\
是转义字符
和]
是范围结束的情况更长,并且当有多种有效方法匹配词法规则时,ANTLR总是选择最长的一种(除非涉及*?
)
要解决这个问题,您应该更改RangeChar
,这样反斜杠只允许作为转义序列的一部分,即用~[\]\]
替换~[\]\]非常感谢。我假设如果出现反斜杠,它会跳过~']
,因为转义字符
匹配会更长。@ThomasS。是的,但是最大咀嚼原则适用于lexer规则,而不是片段。也就是说,它使用的路径为Range
生成尽可能长的匹配,而不是RangeChar
。非常感谢。我假设如果出现反斜杠,它会跳过~']
,因为转义字符
匹配会更长。@ThomasS。是的,但是最大咀嚼原则适用于lexer规则,而不是片段。也就是说,它与为Range
而不是RangeChar
生成最长可能匹配的路径相匹配。