2010-03-15 10 views
8

Nella sezione 10.4, il riferimento ANTLR definitivo indica di ignorare la mancata corrispondenza() & recoverFromMismatchedSet() se si desidera uscire al primo errore di analisi. Ma, almeno in ANTLR 3.2, sembra che non esista un metodo mismatch(), e la documentazione recoverFromMismatchedSet() dice che è "Not Used Used". Quindi sembra che le cose siano cambiate da quando il libro è stato pubblicato.Come ottenere ANTLR 3.2 per uscire al primo errore?

Cosa dovrei fare invece di uscire dal primo errore di analisi in ANTLR 3.2?

risposta

13

Ho inviato questa domanda a un altro interesse e Andrew Haritonkin ha risposto. Bart K ha metà a destra; è necessario eseguire l'override di recoverFromMismatchedSet(), ma anche recoverFromMismatchedToken().

Se si desidera anche il lexer per uscire sul primo errore, c'è una pagina wiki che spiega cosa fare:

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

In breve, si afferma che:

  1. Se vuoi lanciare RecognitionException (o qualsiasi cosa erediti da Exception) allora devi fare trucchi java, perché i metodi rilevanti non dichiarano alcuna eccezione
  2. Se è OK lanciare RuntimeEx ception o Error, quindi è possibile ignorare nextToken() per generare un'eccezione invece di chiamare recoverError(), oppure è possibile eseguire l'override di recoverError(). gettare l'eccezione.

Ecco una grammatica di esempio che esce sul primo errore lexer o parser: uscita

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

Esempio:

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

Grazie per il follow-up Dan! –