Antlr ANTRL4-leaves环路的错误恢复
我试图为ABAP语言的子集编写一个解析器。但当输入包含拼写错误/未知语句时,我会遇到一些问题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
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*;…并添加到块规则中……因此拼写错误的命令不会导致错误,但我会在语法树中获得未知的安装节点。解析后,我可以使用侦听器检查这些节点。对我有效,但如果有人有更好的想法?