2010-03-15 10 views
8

En la sección 10.4, la referencia ANTLR definitiva le indica que anule la discrepancia() & recoverFromMismatchedSet() si desea salir del primer error de análisis. Pero, al menos en ANTLR 3.2, parece que no hay ningún método de desajuste(), y la documentación de recoverFromMismatchedSet() dice que es "No se usa actualmente". Entonces parece que las cosas han cambiado desde que el libro fue publicado.¿Cómo obtener ANTLR 3.2 para salir del primer error?

¿Qué se supone que debo hacer para salir del primer error de análisis en ANTLR 3.2?

Respuesta

13

Publiqué esta pregunta a anltr-interest, y Andrew Haritonkin respondió. Bart K tiene la mitad de la razón; necesita anular recoverFromMismatchedSet(), pero también recoverFromMismatchedToken().

Si también desea que el analizador léxico para salir en el primer error, hay una página wiki que explica qué hacer:

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

En pocas palabras, se establece que:

  1. Si desea lanzar RecognitionException (o cualquier cosa que herede de Exception), entonces tiene que hacer trucos java astuto, porque los métodos pertinentes no declaran ninguna excepción
  2. Si está bien lanzar RuntimeEx A continuación, puede anular nextToken() para lanzar una excepción en lugar de llamar a recoverError(), o puede anular recoverError(). lanzar la excepción.

Aquí es un ejemplo de gramática que sale en el primer error léxico o analizador: salida

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

muestra:

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

Gracias por el seguimiento de Dan! –