如何解决存在相似模式时,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,它与上面的字符串匹配。
这是添加了 '
[@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 举报,一经查实,本站将立刻删除。