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 + "]!");
}
}
库版本:
- ANTLR4: 4.7.2
- JUnit: 5.5.0-m1
感谢所有帮助^^
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 解析器可以从一些语法错误中恢复,跳过一些标记并继续解析。
每次遇到语法错误时,都会调用 TestErrorListener
的 syntaxError()
方法。
根据您的示例代码,每次发生错误时,您都将 hadError
标志设置为 true,这意味着,在解析完成后,您可以根据您的输入测试该标志是真还是假令牌。
此外,您可以通过提供错误处理程序使 ANTLR 立即抛出异常并在发生错误时停止解析,即:
pars.setErrorHandler(new BailErrorStrategy());
从现在开始,您的解析器将抛出 ParseCancellationException
。捕获它并使用 getCause()
方法,您可以获得使解析器停止的真正原因,包括 NoViableAltException
。
在后一种情况下,您所要做的就是 运行 您的 pars.stmt_block();
与 assertThrows()
结合并检查 ParseCancellationException
是否被抛出。
我正在研究 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 + "]!");
}
}
库版本:
- ANTLR4: 4.7.2
- JUnit: 5.5.0-m1
感谢所有帮助^^
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 解析器可以从一些语法错误中恢复,跳过一些标记并继续解析。
每次遇到语法错误时,都会调用 TestErrorListener
的 syntaxError()
方法。
根据您的示例代码,每次发生错误时,您都将 hadError
标志设置为 true,这意味着,在解析完成后,您可以根据您的输入测试该标志是真还是假令牌。
此外,您可以通过提供错误处理程序使 ANTLR 立即抛出异常并在发生错误时停止解析,即:
pars.setErrorHandler(new BailErrorStrategy());
从现在开始,您的解析器将抛出 ParseCancellationException
。捕获它并使用 getCause()
方法,您可以获得使解析器停止的真正原因,包括 NoViableAltException
。
在后一种情况下,您所要做的就是 运行 您的 pars.stmt_block();
与 assertThrows()
结合并检查 ParseCancellationException
是否被抛出。