我正在研究ANTLR解析器,现在正在为解析器编写测试。
我已经找到了一种“正向”测试解析器的方法,但是现在还想测试在输入错误的情况下解析器也会失败(负测试?)。
我想要的是一种使用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 + "]!");
}
}
库版本:
感谢所有帮助^^
答案 0 :(得分:1)
还希望测试在提供错误输入时解析器是否也会失败
在这种情况下,“失败”的含义还不清楚,但是我认为您的意思是“我怎么知道语法错误发生了?”。由于ANTLR解析器可以从某些语法错误中恢复,因此跳过一些标记并继续进行解析。
每次遇到语法错误时,您的syntaxError()
的{{1}}方法都会被调用。
根据示例代码,每次发生错误时,都将TestErrorListener
标志设置为true,这意味着在解析之后,您可以针对输入令牌测试此标志为true还是false。
此外,您可以通过提供错误处理程序,使ANTLR立即引发异常并在发生错误时停止解析,即:
hadError
从现在开始,您的解析器将抛出pars.setErrorHandler(new BailErrorStrategy());
。捕获并使用ParseCancellationException
方法,您可以获得导致解析器停止的真正原因,包括getCause()
。
在后一种情况下,您要做的就是将NoViableAltException
与pars.stmt_block();
一起运行,并检查是否抛出assertThrows()
。