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

存在相似模式时,ANTLR 无法正确匹配模式

如何解决存在相似模式时,ANTLR 无法正确匹配模式

我正在使用 ANTLR 来解析一些查询

这是我的 ANTLR g4:

 'serviceAccounts': [
 {
   'email': 'default'
   'scopes':[
    'https://www.googleapis.com/auth/compute','https://www.googleapis.com/auth/servicecontrol','https://www.googleapis.com/auth/service.management.readonly','https://www.googleapis.com/auth/logging.write','https://www.googleapis.com/auth/monitoring.write','https://www.googleapis.com/auth/trace.append','https://www.googleapis.com/auth/devstorage.read_write']}]

我喂它时的问题:

propTest
  : objectPath NOT? (EQ|NEQ) primitiveLiteral    # propTestEqual
  | objectPath NOT? (EQ|NEQ) 'wwww'              # propTestThlEqual
  ;

primitiveLiteral
  : orderableLiteral
  | BoolLiteral
  ;

primitiveLiteral
  : orderableLiteral
  ;

orderableLiteral
  : StringLiteral
  ;

StringLiteral
  : QUOTE ( ~['\\] | '\\\'' | '\\\\' )* QUOTE
  ;

我希望比赛发生在

[network-traffic:src_port = '123]

但它不匹配任何东西,但一旦我删除

: objectPath NOT? (EQ|NEQ) primitiveLiteral       # propTestEqual

然后匹配发生在

| objectPath NOT? (EQ|NEQ) 'wwww'   # propTestThlEqual

知道发生了什么吗?

** 更新

: objectPath NOT? (EQ|NEQ) primitiveLiteral       # propTestEqual

解决方法

您不匹配,因为您在 ' 上没有结束 '123

这是您的令牌流(对于您的示例)(我还包含了错误消息)

[@0,0:0='[',<'['>,1:0]
[@1,1:15='network-traffic',<IdentifierWithHyphen>,1:1]
[@2,16:16=':',<':'>,1:16]
[@3,17:24='src_port',<IdentifierWithoutHyphen>,1:17]
[@4,26:26='=',<EQ>,1:26]
[@5,28:28=''',<'''>,1:28]
[@6,29:31='123',<IntPosLiteral>,1:29]
[@7,32:32=']',<']'>,1:32]
[@8,33:32='<EOF>',<EOF>,1:33]
line 1:28 no viable alternative at input 'network-traffic:src_port=''

它与输入 [network-traffic:src_port = '123'] 匹配良好

(我添加了您的 | objectPath NOT? (EQ | NEQ) 'wwww' # propTestThlEqual1 替代 popTest,它与上面的字符串匹配。

这是添加了 '

的 tokenStream
[@0,28:32=''123'',<StringLiteral>,33:33=']',1:33]
[@7,34:33='<EOF>',1:34]

令牌规则将选择最长的匹配。

对你的语法的评论...

您可能想让 QUOTE 成为一个片段,这样它就不能被识别为它自己的标记(但只能在您引用它的 Lexer 规则中)(任何以大写开头的规则都是一个 Lexer 规则(它是习惯上使 Lexer Rules 全部大写,但它是“重要”的第一个字母)

如果我将 QUOTE 规则更改为 fragment QUOTE: '\'';

那么tokenStream就是:(再次包含错误信息)

[@0,<InvalidCharacter>,1:33]
line 1:28 no viable alternative at input 'network-traffic:src_port=''

您会收到相同的“没有可行的替代方案”错误,但您还会收到有助于提示问题的 InvalidCharacter: .; 令牌。


至于在 propTest 规则上只有一个选项时为什么会得到不同结果的问题……这很有趣。当有单一规则时,我会在您的示例中收到 extraneous input ''' expecting { 警告,并在您的评论中针对第二个示例收到 mismatched input ']' expecting { 警告。

这两者都是 ANTLR 尝试更好的错误恢复的结果。 (请参阅 Pragmatic Programmers 的“The Definitve ANTLR 4 Refenence”中的“Recovering from Errors in SubRules”和“A Parade of Errors”部分(如果您打算使用 ANTLR 做很多事情,这几乎是一本“必备”书))。现在很明显,当 ANTLR 有多个规则替代方案时,它无法真正参与这些恢复尝试。 (我确实看过 ATN 图,但它们并没有真正涵盖这些错误恢复路径,因此差异“无趣”)

由于您只会在 propTest 解析器规则的单一替代版本中看到这些警告,因此处理它们实际上可能“无关紧要”。只需处理您会因输入错误而得到的 no viable alternative 错误,然后继续。

仅供参考...如果您想寻求一个可以使用这些错误恢复策略的选项,但要注意这些警告,您可以实现自己的 ErrorListener 类。

我几乎总是这样做,所以我可以更好地控制捕获所有错误和警告并决定如何在 UI 中管理它们。默认的 ErrorHandler 几乎只是将消息输出到控制台。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。