ANTLR报错疑问:为何‘mismatched input’未包含!和^预期令牌?
ANTLR解析错误中预期令牌未包含'!'和'^'的疑问
语法定义
grammar Playground; stmtList: (expr EOS)+; expr: IDENTIFIER ('!' | '^') IDENTIFIER | expr ('*' | '/') expr | expr ('+' | '-') expr | INT | IDENTIFIER; MAKE: 'make'; INT: '0' | [1-9] [0-9]*; IDENTIFIER: [a-zA-Z0-9]+; EQUAL: '='; // Dummy token that can be recognised EOS: '\r'? '\n'; WS: [ \t\n\r]+ -> skip;
测试输入
blah=blah
实际报错信息
line 1:4 mismatched input '=' expecting {'*', '/', '+', '-', EOS}
用户预期的报错形式:
line 1:4 mismatched input '=' expecting {'!', '^', '*', '/', '+', '-', EOS}
令牌生成结果
执行命令 grun Playground stmtList -tokens 后输出:
[@0,0:3='blah',<IDENTIFIER>,1:0] [@1,4:4='=',<'='>,1:4] [@2,5:8='blah',<IDENTIFIER>,1:5] [@3,9:9='\n',<EOS>,1:9] [@4,10:9='<EOF>',<EOF>,2:0]
ANTLR版本:4.11.1
疑问
为何ANTLR给出的预期令牌集中未包含expr规则第一个分支定义的'!'和'^'令牌?
原因分析
这核心是ANTLR解析器的状态问题:当它把第一个blah识别成独立的IDENTIFIER(匹配了expr规则的最后一个分支)后,就判定当前表达式已经完成。
此时解析器处于「表达式结束后」的状态,接下来只接受两种情况:要么是*/+这类二元操作符(用来扩展现有表达式,比如blah + 1这种嵌套结构),要么是EOS语句结束符。
而expr的第一个分支IDENTIFIER ('!' | '^') IDENTIFIER是个完整的表达式结构——它要求第一个IDENTIFIER后面必须立刻跟!或^,再衔接另一个IDENTIFIER,整个构成一个完整expr。但解析器已经把blah当成独立完成的expr,自然不会再考虑“在它后面加!或^拼成另一种expr”的情况,所以这两个符号不会出现在预期令牌列表里。
内容的提问来源于stack exchange,提问作者Tobi
相关产品推荐
相关产品推荐

