【问题标题】:Consuming Error tokens in antlr4在 antlr4 中使用错误令牌
【发布时间】:2017-10-11 15:09:57
【问题描述】:

这是我的语法,我想输入为

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 策略,但它仍然没有工作

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

}

}

我的输出:

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 antlr3 antlr2


    【解决方案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 : . ;
    

    【讨论】:

    • 嗨@GRosenberg 感谢您的回复,我使用了 DefaultErrorStrategy 但我仍然无法得到正确的结果,我使用错误策略类请帮助编辑。
    • 感谢@GRosenberg,我已经按照您所说的添加了代码,但是控件没有在恢复方法中进行,我将输入作为“altasdfer table ;alter table ;”但输出为第 1:0 行令牌识别错误:'alta' 第 1:4 行令牌识别错误:'s' 第 1:5 行令牌识别错误:'d' 第 1:6 行令牌识别错误:' f' 行 1:7 令牌识别错误:'e' 行 1:8 令牌识别错误:'r' 行 1:9 令牌识别错误:''(开始编译)请帮助我卡在它上面。
    • @GRosenberg 使用恢复方法进行查询时:altasder 表;更改表;它消耗令牌直到第一个分号(;)。它不处理正确的第二个语句。你能请指导
    • @GRosenberg 在处理错误语句直到分号后,它应该再次从第一条规则开始。如何实现
    猜你喜欢
    • 2023-01-08
    • 2021-12-22
    • 1970-01-01
    • 2015-03-23
    • 1970-01-01
    • 2022-12-09
    • 2023-02-05
    • 2013-08-12
    • 2017-03-12
    相关资源
    最近更新 更多