【发布时间】:2018-01-06 11:49:18
【问题描述】:
我想得到 ANTLR4 解析器的具体错误信息。 而且我发现有两种处理错误的方法:errorListener和errorHandler。
// set error handler
parser.removeErrorListeners();
parser.addErrorListener(new QueryErrorListener());
parser.setErrorHandler(new BailErrorStrategy());
但我对它们之间的区别感到困惑。
我发现,errorListener 可以得到具体的错误信息,但是只能打印或者记录,不能抛出异常。
errorListener的实现如下:
public class QueryErrorListener extends BaseErrorListener {
private static final Logger LOGGER = LoggerFactory.getLogger(QueryDispatcher.class);
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
int line, int charPositionInLine, String msg,
RecognitionException e)
{
List<String> stack = ((Parser)recognizer).getRuleInvocationStack(); Collections.reverse(stack);
String errorMessage = "line "+line+":"+charPositionInLine+" at "+
offendingSymbol+": "+msg;
LOGGER.error("rule stack: "+stack);
LOGGER.error(errorMessage);
QueryParseErrorStrategy queryParseErrorStrategy = new QueryParseErrorStrategy();
}
}
同时errorHandler只能抛出异常ParseCancellationException,没有任何具体信息。
public class BailErrorStrategy extends DefaultErrorStrategy {
/** Instead of recovering from exception {@code e}, re-throw it wrapped
* in a {@link ParseCancellationException} so it is not caught by the
* rule function catches. Use {@link Exception#getCause()} to get the
* original {@link RecognitionException}.
*/
@Override
public void recover(Parser recognizer, RecognitionException e) {
for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) {
context.exception = e;
}
throw new ParseCancellationException(e);
}
/** Make sure we don't attempt to recover inline; if the parser
* successfully recovers, it won't throw an exception.
*/
@Override
public Token recoverInline(Parser recognizer)
throws RecognitionException
{
InputMismatchException e = new InputMismatchException(recognizer);
for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) {
context.exception = e;
}
throw new ParseCancellationException(e);
}
/** Make sure we don't attempt to recover from problems in subrules. */
@Override
public void sync(Parser recognizer) { }
}
我正在尝试寻找解决方案,添加一个传输方法以从 ParseCancellationException 获取详细消息,如下所示。
我发现我可以从 RecognitionException 的 Token 对象中得到一些消息,但是我只能找到 line/charPositionInLine/offendingSymbol 消息,我不知道详细消息在哪里,比如“缺少'xxx',期望'yyy'"
public class ANTLRExceptionTransfer {
public static SemanticException transfer(RecognitionException re) {
String errorMsg = "";
Recognizer<?, ?> recognizer = re.getRecognizer();
Token offendingSymbol = re.getOffendingToken();
int line = offendingSymbol.getLine();
int charPositionInLine = offendingSymbol.getCharPositionInLine();
// ????????
String msg = "";
List<String> stack = ((Parser)recognizer).getRuleInvocationStack();
Collections.reverse(stack);
String errorMessage = "rule stack: "+stack;
errorMessage = "\nline "+line+":"+charPositionInLine+" at "+
offendingSymbol+": "+msg;
return new SemanticException(errorMessage);
}
}
errorHandler的使用方法正确吗? 如何获得带有特定错误消息的异常?
【问题讨论】:
-
我现在可以从 RecognitionException 获取基本信息,但仍然不知道如何构建像 errorListener 那样的可读消息 [@1289,4632:4632='}' 的第 1:4632 行, ,1:4632]: 外部输入 '}' 期待 ','] 。 ANTLR4有没有提供可用的方法?
标签: antlr4