微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ANTLR:过于贪婪的规则

如何解决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 举报,一经查实,本站将立刻删除。