自定义错误处理程序方法无法处理令牌识别错误

问题描述 投票:1回答:1

这是我的.g4文件:

grammar Hello;

start : compilation;
compilation : sql*;
sql : altercommand;
altercommand : ALTER TABLE SEMICOLON;
ALTER: 'alter';
TABLE: 'table';
SEMICOLON : ';';

我的主班:

public class Main {
    public static void main(String[] args) throws IOException {
        ANTLRInputStream ip = new ANTLRInputStream("altasdere table ; alter table ;");
        HelloLexer lex = new HelloLexer(ip);
        CommonTokenStream token = new CommonTokenStream(lex);
        HelloParser parser = new HelloParser(token);

        parser.setErrorHandler(new CustomeErrorHandler());

        System.out.println(parser.start().toStringTree(parser));            
    }    
}

我的CutomErrorHandler类:

public class CustomeErrorHandler extends DefaultErrorStrategy {

    @Override
    public void recover(Parser recognizer, RecognitionException e) {
        super.recover(recognizer, e);
        TokenStream tokenStream = (TokenStream) recognizer.getInputStream();

        if (tokenStream.LA(1) == HelloParser.SEMICOLON) {
            IntervalSet intervalSet = getErrorRecoverySet(recognizer);
            tokenStream.consume();
            consumeUntil(recognizer, intervalSet);
        }
     }
 }

当我输入altasdere table ; alter table ;时,它不会解析第二个命令,因为它在第一个命令中发现了错误。我主类的输出是

line 1:0 token recognition error at: 'alta'
line 1:4 token recognition error at: 's'
line 1:5 token recognition error at: 'd'
line 1:6 token recognition error at: 'e'
line 1:7 token recognition error at: 'r'
line 1:8 token recognition error at: 'e'
line 1:9 token recognition error at: ' '
(start compilation)
antlr antlr4 antlrworks antlr2
1个回答
1
投票

The Definitive ANTLR 4 Reference中的9.5节,更改ANTLR的错误处理策略,我可以阅读:

默认错误处理机制效果很好,但是有一个一些非典型的情况下,我们可能想要更改它。

您的语法是否非典型,您需要处理令牌识别错误?我个人将编写一个语法,该语法在Lexer级别上没有错误,如下所示。

文件Question.g4:

grammar Question;

question
@init {System.out.println("Question last update 0712");}
    :   sql+ EOF
    ;

sql
    :   alter_command
    |   erroneous_command
    ;

alter_command
    :   ALTER TABLE SEMICOLON
        {System.out.println("Alter command found : " + $text);}
    ;

erroneous_command
    :   WORD TABLE? SEMICOLON
        {System.out.println("Erroneous command found : " + $text);}
    ;

ALTER     : 'alter' ;
TABLE     : 'table' ;
WORD      : [a-z]+ ;
SEMICOLON : ';' ;
WS        : [ \t\r\n]+ -> channel(HIDDEN) ;

请注意,WORD规则必须位于ALTER之后,请参阅disambiguatehere

文件t.text:

altasdere table ; alter table ;

执行:

$ grun Question question -tokens -diagnostics t.text
[@0,0:8='altasdere',<WORD>,1:0]
[@1,9:9=' ',<WS>,channel=1,1:9]
[@2,10:14='table',<'table'>,1:10]
[@3,15:15=' ',<WS>,channel=1,1:15]
[@4,16:16=';',<';'>,1:16]
[@5,17:17=' ',<WS>,channel=1,1:17]
[@6,18:22='alter',<'alter'>,1:18]
[@7,23:23=' ',<WS>,channel=1,1:23]
[@8,24:28='table',<'table'>,1:24]
[@9,29:29=' ',<WS>,channel=1,1:29]
[@10,30:30=';',<';'>,1:30]
[@11,31:31='\n',<WS>,channel=1,1:31]
[@12,32:31='<EOF>',<EOF>,2:0]
Question last update 0712
Erroneous command found : altasdere table ;
Alter command found : alter table ;

您可以看到,错误的输入已被WORD令牌吸收。现在,应该可以轻松地处理或忽略侦听器/访问者中的错误命令。

© www.soinside.com 2019 - 2024. All rights reserved.