【背景】
折腾:
【记录】用antlr的preprocess去预处理一个新的eddl文件去除eddl中不支持的元素对应的文件内容
期间,希望实现:
对于当前预处理的新的hart的eddl文件
第一次出错,即那个MismatchedTokenException,就退出。
以此希望实现后续的,方便调试而找到具体错误的根本原因,并希望最终解决此问题。
【解决过程】
1.经过参考之前自己的:
中的:
去给preprocess.g添加对应的代码,变为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | grammar preprocess; //lexer grammar preprocess; options{ language=Java; output = AST; } @lexer ::header { //package com.mm.antlrv3demo; import java.io.*; import java.util.*; } @parser ::header { //package com.mm.antlrv3demo; } @members { @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; } } // Alter code generation so catch-clauses get replace with this action. @rulecatch { catch (RecognitionException e) { throw e; } } @lexer ::members { ...... @Override public void reportError(RecognitionException e) { throw new RuntimeException(e); } } |
然后调试了半天,发现:
生成的:
preprocessLexer.java
中没有所希望的:
recoverFromMismatchedToken
而
preprocessParser.java
中才有那个recoverFromMismatchedToken
而且关键问题是:
最后当调试出错时,根本没有停止,却继续执行了。
2.其中,由于
1 | public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException { |
中的BitSet找不到,所以无法编译,需要添加对应的:
1 | import org.antlr.runtime.BitSet; |
后,才可以正常编译和调试。
3.后来去原先的代码,才看出问题:
之前不小心把
recoverFromMismatchedToken
和
recoverFromMismatchedSet
都加到了:
1 | @members |
中,其对应着实际上是Parser的member,
所以应该去改为,加到:
1 | @lexer ::members |
中去,才是加到Lexer的member中。
3.所以去试试,改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | grammar preprocess; //lexer grammar preprocess; options{ language=Java; output = AST; } @lexer ::header { //package com.mm.antlrv3demo; import java.io.*; import java.util.*; } @parser ::header { //package com.mm.antlrv3demo; } // Alter code generation so catch-clauses get replace with this action. @rulecatch { catch (RecognitionException e) { throw e; } } @lexer ::members { ...... //for debug: exit for first error/exception @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; } @Override public void reportError(RecognitionException e) { throw new RuntimeException(e); } } |
最后,终于实现希望了,当第一个错误时,可以直接退出:
1 2 3 4 5 6 7 8 9 10 11 12 | Exception in thread "main" java.lang.RuntimeException: MismatchedTokenException(32!=41) at preprocessLexer.reportError(preprocessLexer.java:136) at org.antlr.runtime.Lexer.nextToken(Lexer.java:99) at preprocessLexer.nextToken(preprocessLexer.java:79) at antlrPreprecessTest.preprcessTest(antlrPreprecessTest.java:61) at antlrPreprecessTest.main(antlrPreprecessTest.java:33) Caused by: MismatchedTokenException(32!=41) at org.antlr.runtime.Lexer.match(Lexer.java:206) at preprocessLexer.mIDENTIFIER(preprocessLexer.java:1102) at preprocessLexer.mTokens(preprocessLexer.java:2377) at org.antlr.runtime.Lexer.nextToken(Lexer.java:85) ... 3 more |
了
如图:
【总结】
在给antlr的语法文件中加代码时,要搞清楚是加给Lexer还是Parser的。
其中:
加到:
1 2 3 | @members { ...... } |
是默认加给Parser的;
加到:
1 2 3 | @lexer ::members { ...... } |
是加给Lexer的。