How to get ANTLR 3.2 to exit upon first error?

前端 未结 1 1964
我在风中等你
我在风中等你 2021-01-02 16:24

In section 10.4, The Definitive ANTLR reference tells you to override mismatch() & recoverFromMismatchedSet() if you want to exit upon the first parsing error. But, at l

1条回答
  •  别那么骄傲
    2021-01-02 17:05

    I posted this question to anltr-interest, and Andrew Haritonkin answered. Bart K is half right; you need to override recoverFromMismatchedSet(), but also recoverFromMismatchedToken().

    If you also want the lexer to exit upon the first error, there is a wiki page that explains what to do:

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

    Briefly, it states that:

    1. If you want to throw RecognitionException (or anything inheriting from Exception) then you have to do sneaky java tricks, because the relevant methods don't declare any exceptions
    2. If it's OK to throw RuntimeException or Error, then you can either override nextToken() to throw an exception instead of calling recoverError(), or you can override recoverError(). to throw the exception.

    Here is an example grammar that exits upon the first lexer or parser error:

    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 words]
        @init{$words = new ArrayList();}
      :  w=Atom {$words.add($w.text);} (',' w=Atom {$words.add($w.text);} )* EOF
      ;
    
    
    Atom: '0' | '1';
    
    WS  :  ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
    

    Sample output:

    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              
    

    0 讨论(0)
提交回复
热议问题