为什么在解析器规则中使用 EOF 会影响 ANTLR4 中的词法分析器?

Why does having EOF in parser rules influence the lexer in ANTLR4?

提问人:raffian 提问时间:10/27/2023 更新时间:10/27/2023 访问量:26

问:

从简单的语法开始:

grammar Simple;

file  : lines ;
lines : (ID | INT | STRING)+ '\r'? '\n';

ID       : [a-zA-Z_]*;
INT      : [0-9]*;
STRING   : '"' ~["\r\n]* '"';
COMMA    : ',';
WS       : [ \t\f]+ -> skip ;

示例#1 |有效输入

aaa
999

[@0,0:2='aaa',<3>,1:0]
[@1,3:3='\n',<2>,1:3]
[@2,4:6='999',<4>,2:0]

示例#2 |无效输入

在不更改解析器规则的情况下向输入添加了一些逗号,但令人惊讶的是,这不会引发任何错误,也不明白为什么词法分析器停止标记化而不是读取到文件末尾。999

   aaa
   999
   777,rrr
   fff,456,iom

   [@0,0:2='aaa',<3>,1:0]
   [@1,3:3='\n',<2>,1:3]
   [@2,4:6='999',<4>,2:0]

示例#3 |解析器调整

将“EOF”添加到起始规则中:

file  : lines EOF ;

现在词法分析器读到最后,解析器会引发预期的错误:

   aaa
   999
   777,rrr
   fff,456,iom

   [@0,0:2='aaa',<3>,1:0]
   [@1,3:3='\n',<2>,1:3]
   [@2,4:6='999',<4>,2:0]
   [@3,7:7='\n',<2>,2:3]
   [@4,8:10='777',<4>,3:0]
   [@5,11:11=',',<6>,3:3]
   [@6,12:14='rrr',<3>,3:4]
   [@7,15:15='\n',<2>,3:7]
   [@8,16:18='fff',<3>,4:0]
   [@9,19:19=',',<6>,4:3]
   [@10,20:22='456',<4>,4:4]
   [@11,23:23=',',<6>,4:7]
   [@12,24:26='iom',<3>,4:8]
   [@13,27:27='\n',<2>,4:11]
   [@14,28:27='<EOF>',<-1>,5:0]

   [2:0 | [@2,4:6='999',<4>,2:0] | why? mismatched input '999' expecting <EOF>]

问题

关于示例#2...

  1. 为什么解析器没有引发任何错误?
  2. 为什么词法分析器停止标记化而不是读取到文件末尾?999
  3. 我的理解是词法分析器和解析器是独立的,在 ANTLR4 中不通信,那么词法分析器如何知道在示例 #3 中解析器引发错误的同一位置停止读取?
ANTLR ANTLR4 语法 词法分析器

评论

2赞 kaby76 10/27/2023
(1 和 2):在通常的用例中,EOF 终止的启动规则强制解析器读取到输入的末尾并报告任何错误。否则,它会在错误点停止。这是一个“功能”,用于解析输入的隔离部分。(3):解析器通过“词法分析器”调用词法分析器。NextToken()”。解析器确实有一个“上下文状态”,当调用 NextToken() 时,词法分析器可以访问该状态。但解析器还会在 AdaptivePredict() 中计算一组可能的解析状态。NextToken() 中的词法分析器无法访问它。在这方面,词法分析器“独立”于解析器。
0赞 raffian 10/27/2023
如果您考虑发表您的评论作为答案,我会接受它,只是希望您能详细说明您的观点。

答: 暂无答案