Как заставить ANTLR 3.2 выходить на первую ошибку?

В разделе 10.4, Категорическая ссылка ANTLR говорит Вам переопределять несоответствие () и recoverFromMismatchedSet (), если Вы хотите выйти на первую ошибку анализа. Но, по крайней мере, в ANTLR 3.2, кажется, что нет никакого несоответствия () метода и recoverFromMismatchedSet (), в документации говорится, что это "В настоящее время не Используется". Таким образом, кажется, что вещи изменились, так как книга была опубликована.

Что я, как предполагается, делаю вместо этого для выхода на первую ошибку анализа в ANTLR 3.2?

8
задан Dan Becker 15 March 2010 в 03:58
поделиться

1 ответ

Я разместил этот вопрос на anltr-interest, и Андрей Харитонкин ответил. Bart K прав наполовину; вам нужно переопределить recoverFromMismatchedSet(), а также recoverFromMismatchedToken().

Если вы также хотите, чтобы лексер завершал работу при первой ошибке, есть страница вики, которая объясняет, что делать:

http://www.antlr.org/wiki/pages/viewpage.action? pageId=5341217

Вкратце, там говорится, что:

  1. Если вы хотите бросать RecognitionException (или что-либо, наследующее от Exception), то вам придется прибегнуть к хитрым java-уловкам, потому что соответствующие методы не объявляют никаких исключений
  2. Если нормально бросать RuntimeException или Error, то вы можете либо переопределить nextToken(), чтобы бросать исключение вместо вызова recoverError(), либо вы можете переопределить recoverError(). чтобы бросать исключение.

Вот пример грамматики, которая завершается при первой ошибке лексера или парсера:

grammar Test;

@parser::members {

  public static void main(String[] args) throws Exception {
    String text = args[0];
    ANTLRStringStream in = new ANTLRStringStream(text);
    TestLexer lexer = new TestLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    System.out.println(new TestParser(tokens).mainRule());
  }

  @Override
  protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
    throw new MismatchedTokenException(ttype, input);
  }

  @Override
  public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
    throw e;
  }

}

@rulecatch {
    catch (RecognitionException e) {
        throw e;
    }
}

@lexer::members {
    @Override
    public void reportError(RecognitionException e) {
        throw new RuntimeException(e);
    }

}    

mainRule returns [List<String> words]
    @init{$words = new ArrayList<String>();}
  :  w=Atom {$words.add($w.text);} (',' w=Atom {$words.add($w.text);} )* EOF
  ;


Atom: '0' | '1';

WS  :  ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;

Пример вывода:

C:\Users\dan\workspace\antlrtest>java -cp .;antlr-3.2.jar TestParser "1,0" 
[1, 0]

C:\Users\dan\workspace\antlrtest>java -cp .;antlr-3.2.jar TestParser "1,,0"
Exception in thread "main" MismatchedTokenException(6!=4)
        at TestParser.recoverFromMismatchedToken(TestParser.java:45)
        at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:115)
        at TestParser.mainRule(TestParser.java:86)
        at TestParser.main(TestParser.java:40)

C:\Users\dan\workspace\antlrtest>java -cp .;antlr-3.2.jar TestParser "1,+0"   
Exception in thread "main" java.lang.RuntimeException: NoViableAltException('+@[])                                                                
        at TestLexer.reportError(TestLexer.java:16)                           
        at org.antlr.runtime.Lexer.nextToken(Lexer.java:94)                   
        at org.antlr.runtime.CommonTokenStream.fillBuffer(CommonTokenStream.java:119)                             at org.antlr.runtime.CommonTokenStream.LT(CommonTokenStream.java:238) 
        at org.antlr.runtime.Parser.getCurrentInputSymbol(Parser.java:54)     
        at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:104)    
        at TestParser.mainRule(TestParser.java:68)                            
        at TestParser.main(TestParser.java:40)                                
Caused by: NoViableAltException('+'@[])                                       
        at TestLexer.mTokens(TestLexer.java:165)                              
        at org.antlr.runtime.Lexer.nextToken(Lexer.java:84)
        ... 6 more              
13
ответ дан 5 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: