2010-03-15 15 views
8

W sekcji 10.4, Ostateczne odwołanie ANTLR mówi, aby zastąpić niedopasowanie() & recoverFromMismatchedSet(), jeśli chcesz zakończyć po pierwszym błędzie analizowania. Ale przynajmniej w ANTLR 3.2 okazuje się, że nie ma żadnej metody niedopasowania(), a instrukcja recoverFromMismatchedSet() mówi, że jest "Nie jest obecnie używana". Wygląda więc na to, że zmieniło się od czasu wydania książki.Jak uzyskać ANTLR 3.2, aby wyjść po pierwszym błędzie?

Co mam zamiast tego zrobić, aby wyjść z pierwszego błędu analizy ANTLR 3.2?

Odpowiedz

13

Wysłałem to pytanie do anltr-interest, a Andrew Haritonkin odpowiedział. Bart K ma połowę rację; musisz zastąpić metodę recoverFromMismatchedSet(), ale także recoverFromMismatchedToken().

Jeśli też chcesz lexer, aby wyjść na pierwszym błędem, istnieje strona wiki, który wyjaśnia, co należy zrobić:

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

Pokrótce, stwierdza, że:

  1. Jeśli chcesz rzucić RecognitionException (lub coś dziedziczącego z Exception), musisz zrobić podstępne sztuczki Java, ponieważ odpowiednie metody nie zadeklarują żadnych wyjątków
  2. Jeśli jest to w porządku, aby rzucić RuntimeEx ception lub Error, możesz albo nadpisać nextToken(), aby rzucić wyjątek, zamiast wywoływać metodę recoverError(), albo możesz zastąpić metodę recoverError(). rzucić wyjątek.

Oto przykład gramatyki że wychodzi po pierwszym Lexer lub parsera błędu: wyjście

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; } ; 

Próbka:

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('[email protected][])                 
     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    
+0

Dzięki za follow up Dan! –

Powiązane problemy