Antlr ANTRL4-leaves环路的错误恢复

Antlr ANTRL4-leaves环路的错误恢复,antlr,antlr4,Antlr,Antlr4,我试图为ABAP语言的子集编写一个解析器。但当输入包含拼写错误/未知语句时,我会遇到一些问题 FUNCTION-POOL test. FUNCTION z_angebot_01. PERFORM x. LOOP AT mytable. PERFORM test. PERFOR test. PERFORM test. PERFORM test. ENDLOOP. ENDFUNCTION. 在本例中,其中一个PERFORM语句拼写为PER

我试图为ABAP语言的子集编写一个解析器。但当输入包含拼写错误/未知语句时,我会遇到一些问题

 FUNCTION-POOL test.

 FUNCTION z_angebot_01.

  PERFORM x.

  LOOP AT mytable.

    PERFORM test.

    PERFOR test.

    PERFORM test.
    PERFORM test.
  ENDLOOP.
ENDFUNCTION.
在本例中,其中一个PERFORM语句拼写为PERFORM。所以我希望解析器在重新同步之前吞下标记,并继续执行以下执行语句

 FUNCTION-POOL test.

 FUNCTION z_angebot_01.

  PERFORM x.

  LOOP AT mytable.

    PERFORM test.

    PERFOR test.

    PERFORM test.
    PERFORM test.
  ENDLOOP.
ENDFUNCTION.
与此相反,解析器似乎尝试插入令牌并离开循环。后来,它抱怨无关的ENDLOOP

输出消息: 第11行:4外部输入'perf'应为{ENDLOOP,LOOP_AT,PERFORM} 第15行:2外部输入'ENDLOOP'应为{ENDFUNCTION,LOOP_AT,PERFORM}

在调试生成的代码时,我注意到,PERFOR语句完全没有错误。只要找到loop_AT或PERFORM,解析器就留在循环中。其他任何东西都会退出循环。 但是,我如何将拼写错误/未知语句视为语法错误,直到下一个EOC标记时才将其忽略

我使用分离的lexer/parser,因此这是我当前的方法:

AbapLexer.g4:

lexer grammar AbapLexer;

@lexer::header {
package generated;
}

WS : [ \t\r\n] -> skip;
EOC     : '.' ;

ENDFUNCTION : [Ee][Nn][Dd][Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn];
ENDLOOP : [Ee][Nn][Dd][Ll][Oo][Oo][Pp];
FUNCTION : [Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn];
FUNCTION_POOL : [Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn] '-' [Pp][Oo][Oo][Ll];
LOOP_AT: [Ll][Oo][Oo][Pp] WHITESPACE [Aa][Tt];
PERFORM : [Pp][Ee][Rr][Ff][Oo][Rr][Mm];

IDENTIFIER: [_a-zA-Z] [_0-9a-zA-Z]* ;
fragment WHITESPACE: [ \t\r\n]+;
AbapParser.g4:

parser grammar AbapParser;
options { tokenVocab=AbapLexer; }

@parser::header {
package generated;
}

report: (FUNCTION_POOL) IDENTIFIER EOC
        (functionStatement)*
        ; 

block:
(
    loopStatement EOC
|   performStatement EOC
)+
;

loopStatement:
    loopStatementStart EOC  
        block?
    ENDLOOP
;

loopStatementStart:
    LOOP_AT IDENTIFIER
;


performStatement:
    PERFORM IDENTIFIER
;

functionStatement
:
    FUNCTION functionname = IDENTIFIER EOC
    block?
    ENDFUNCTION EOC
;
任何提示,谢谢

多谢各位


Peter

我猜它无法匹配
,并在
结束循环
处恢复。不确定它是否会更改任何内容,但您可以尝试以下操作:将
块?
的每个实例替换为
,并在
定义内,将
+
量词替换为
*
,或尝试
块:((performStatement | loopStatement)EOC)*。感谢您的回复!我试过你建议的改变。但是没有区别。在这两种情况下,我得到了相同的语法树(.I添加了以下规则…未知声明:~(ENDLOOP | ENDFUNCTION)~EOC*;…并添加到块规则中……因此拼写错误的命令不会导致错误,但我会在语法树中获得未知的安装节点。解析后,我可以使用侦听器检查这些节点。对我有效,但如果有人有更好的想法?