ANTLR не выдает ошибки при неверном вводе
Я использую ANTLR для разбора логических выражений в пишущем Java-инструменте, и у меня возникают проблемы, потому что передача неверных строк ввода в сгенерированный лексер и анализатор ANTLR не вызывает никаких исключений. Вместо того, чтобы генерировать RecognitionException, как я и ожидал, сгенерированные файлы просто выводят сообщение об ошибке на консоль и возвращают, как будто ошибок не было, что приводит к аварийному завершению моей программы, когда она сталкивается с пустыми данными позже.
Я использовал ANTLRWorks версии 1.4.3 для генерации файлов, и, похоже, должна быть какая-то опция, чтобы он действительно выдавал ошибки, а не печатал на консоль, но я ничего не нашел. Кто-нибудь знает, как заставить ANTLR фактически выдавать сообщения об ошибках? Я видел, что эта же проблема в C# была решена с помощью более старой версии ANTLR, это то, что мне нужно сделать?
РЕДАКТИРОВАТЬ: После того, как Барт указал мне в направлении того, что я искал, я нашел эту страницу
https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Migrating+from+ANTLR+2+to+ANTLR+3
у чьей секции "Обработка ошибок" был код, который делал то, что я хочу, более точно. Чтобы изменить способ ANTLR перехватывать исключения, вы можете сказать это в файле грамматики:
@rulecatch {
catch (RecognitionException e) {
throw e;
}
}
Это заставляет ANTLR выдавать исключение вместо того, чтобы обрабатывать его и восстанавливать. В этом разделе также есть кое-что о переопределении функций несоответствия и восстановления, чтобы убедиться, что выбрасываются все возможные исключения.
2 ответа
Легким решением было бы переопределить ваш лексер и парсер reportError(...)
и выдать собственное исключение вместо того, чтобы позволить ANTLR попытаться восстановиться с неверным синтаксисом / вводом:
grammar YourGrammar;
// options/header/tokens
@parser::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException("I quit!\n" + e.getMessage());
}
}
@lexer::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException("I quit!\n" + e.getMessage());
}
}
// lexer & parser rules
Подробнее о сообщениях об ошибках (и восстановлении): https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Error+reporting+and+recovery
Вы должны использовать прослушиватель ошибок, как предлагается в этом ответе
Однако для быстрого перехода с antlr3 на antlr4 / antlr v4 вы можете использовать это в качестве грамматики:
@parser::members
{
private final Logger log = LogManager.getLogger(this.getClass().getName());
public java.util.HashMap<String, Double> memory = new java.util.HashMap<String, Double>();
@Override
public void notifyErrorListeners(Token offendingToken, String msg, RecognitionException ex)
{
throw new RuntimeException(msg);
}
}
@lexer::members
{
@Override
public void recover(RecognitionException ex)
{
throw new RuntimeException(ex.getMessage());
}
}