在antlr4中使用错误令牌

时间:2017-10-11 15:09:58

标签: antlr antlr4 antlr3 antlr2

这是我的语法,我试图将输入作为

alter table ;

一切正常,但是当我付出

altasder table; alter table ;

它在第一个字符串上给出了一个错误,但是我希望解析第二个命令忽略第一个'altasder table;'

grammar Hello;

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

我怎样才能实现呢???

我使用了DefualtError状态,但仍然不是wotking

import org.antlr.v4.runtime.DefaultErrorStrategy;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.misc.IntervalSet;

public class CustomeErrorHandler extends DefaultErrorStrategy {


        @Override
        public void recover(Parser recognizer, RecognitionException e) {
        // TODO Auto-generated method stub
        super.recover(recognizer, e);


            TokenStream tokenStream = (TokenStream)recognizer.getInputStream();


            if (tokenStream.LA(1) == HelloParser.SEMICOLON  )
            {

                IntervalSet intervalSet = getErrorRecoverySet(recognizer);

                tokenStream.consume();

                consumeUntil(recognizer, intervalSet);
            }
        }
    }

主要课程: 公共课主要{

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));

}

}

myoutput:

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)

为什么它没有转向第二个命令?

1 个答案:

答案 0 :(得分:1)

需要使用DefaultErrorStrategy来控制解析器响应识别错误的行为方式。根据需要进行扩展,修改#recover方法,使用令牌直到令牌流中所需的解析重启点。

#recover的简单实现是:

@Override
public void recover(Parser recognizer, RecognitionException e) {
    if (e instanceof InputMismatchException) {
        int ttype = recognizer.getInputStream().LA(1);
        while (ttype != Token.EOF && ttype != HelloParser.SEMICOLON) {
            recognizer.consume();
            ttype = recognizer.getInputStream().LA(1);
        }
    } else {
        super.recover(recognizer, e);
    }
}

根据需要调整while条件以识别下一个有效点以恢复识别。

注意,错误消息是由于词法分析器无法匹配无关的输入字符。要删除错误消息,请添加为最后一个词法分析器规则:

ERR_TOKEN : . ;