ANTLR не выдает ошибки при неверном вводе - PullRequest
14 голосов
/ 28 декабря 2011

Я использую 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 ]

17 голосов
/ 28 декабря 2011

Легким решением было бы переопределить 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

1 голос
/ 30 января 2015

Вы должны использовать прослушиватель ошибок, как предложено в этом ответе

Однако, для быстрого перехода с 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()); 
  }
}
...