ANTLR не бросает ошибки при неправильном вводе
Я использую ANTLR для анализа логических выражений в инструменте Java, который я пишу, и у меня возникают проблемы, потому что передача недопустимых входных строк в сгенерированный лексер и парсер ANTLR не вызывает никаких исключений. Вместо того, чтобы бросать RecognitionException, как и следовало ожидать, сгенерированные файлы просто печатают сообщение об ошибке в консоли и возвращаются, как если бы не возникало ошибок, из-за чего моя программа вылетала, когда она запускалась в пустые данные позже.
Я использовал ANTLRWorks версии 1.4.3 для генерации файлов, и кажется, что должна быть какая-то опция, чтобы на самом деле выкладывать ошибки, а не печатать на консоль, но я ничего не нашел. Кто-нибудь знает, как заставить ANTLR фактически выкидывать сообщения об ошибках? Я видел, что эта же проблема на С# была решена с использованием более старой версии ANTLR, это то, что мне нужно сделать?
EDIT: После того, как Барт указал мне в направлении того, что я искал, я нашел эту страницу
https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Migrating+from+ANTLR+2+to+ANTLR+3
чей раздел "Обработка ошибок" имел код, который делал то, что я хочу более точно. Чтобы изменить способ использования исключений ANTLR, вы можете сказать это в файле грамматики:
@rulecatch {
catch (RecognitionException e) {
throw e;
}
}
Это заставляет ANTLR исключать исключение вместо обработки и восстановления. В этом разделе также есть некоторые сведения о переопределении функций рассогласования и восстановления, чтобы исключить все возможные исключения.
Ответы
Ответ 1
Простое исправление будет состоять в том, чтобы переопределить ваш лексер и парсер 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
Ответ 2
Вы должны использовать прослушиватель ошибок, как предложено в этом ответе
Однако для быстрой миграции из 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());
}
}