ANTLR 4 (Java) 捕获解析器 errors/expections 用于测试目的

ANLTR 4 (Java) catch parser errors/expections for test purposes

我正在研究 ANTLR-Parser,现在正在为解析器编写测试。

我已经找到了 "positive"- 测试解析器的方法,但现在还想测试解析器在提供错误输入时是否也会失败(否定测试?)。

我想要的 是一种使用 JUnits Assertions.assertThrows() 的方法,例如 NoViableAltException 或解析器抛出的任何其他异常。

我已经看过 ANTLRErrorListener 及其实现,但还没有找到解决方案。

到目前为止,这是我的测试用例:

@Test
    public void test_short_negative() {

        String[] string_values = new String[]{"{", "<EOF>"};
        int[] id_values = new int[]{MyLexer.CBRACKET_OPEN, MyLexer.EOF};

        ArrayList<TestToken> tokens = new ArrayList<>();

        for (int i = 0; i < id_values.length; i++) tokens.add(new TestToken(string_values[i], id_values[i]));

        ListTokenSource source = new ListTokenSource(tokens);
        for(TestToken t: tokens) t.setTokenSource(source);

        TestErrorListener errorListener = new TestErrorListener(true);
        MyParser pars = createParser(new ListTokenSource(tokens), errorListener);
        pars.stmt_block();
    }

public class TestErrorListener extends BaseErrorListener {
    private boolean hadError = false;
    private TestToken lastOffendingSymbol;

    private boolean doPrint;

    public TestErrorListener(boolean doPrint){
        this.doPrint = doPrint;
    }

    public boolean hadError() {
        return hadError;
    }

    public TestToken getLastOffendingSymbol() {
        return lastOffendingSymbol;
    }

    @Override
    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
        if(doPrint) System.out.println("Syntax error at " + line + ":" + charPositionInLine + ". Symbol: '" + ((TestToken) offendingSymbol).getText() + "' could not be parsed.");
        hadError = true;
        lastOffendingSymbol = (TestToken) offendingSymbol;
    }

    @Override
    public void reportAmbiguity(Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) {
        if(doPrint) System.out.println("Ambiguity found at [" + startIndex + ":" + stopIndex + "]!");
    }


}

库版本:


感谢所有帮助^^

also want to test that the parser also fails when supplied with a bad input

在这种情况下,您所说的 "fails" 的意思不太清楚,但我认为您的意思是 "how do I know a syntax error has occured?"。因为 ANTLR 解析器可以从一些语法错误中恢复,跳过一些标记并继续解析。

每次遇到语法错误时,都会调用 TestErrorListenersyntaxError() 方法。

根据您的示例代码,每次发生错误时,您都将 hadError 标志设置为 true,这意味着,在解析完成后,您可以根据您的输入测试该标志是真还是假令牌。

此外,您可以通过提供错误处理程序使 ANTLR 立即抛出异常并在发生错误时停止解析,即:

pars.setErrorHandler(new BailErrorStrategy());

从现在开始,您的解析器将抛出 ParseCancellationException。捕获它并使用 getCause() 方法,您可以获得使解析器停止的真正原因,包括 NoViableAltException

在后一种情况下,您所要做的就是 运行 您的 pars.stmt_block();assertThrows() 结合并检查 ParseCancellationException 是否被抛出。