【背景】
折腾:
【记录】用antlr的preprocess去预处理一个新的eddl文件去除eddl中不支持的元素对应的文件内容
期间,希望实现:
对于当前预处理的新的hart的eddl文件
第一次出错,即那个MismatchedTokenException,就退出。
以此希望实现后续的,方便调试而找到具体错误的根本原因,并希望最终解决此问题。
【解决过程】
1.经过参考之前自己的:
中的:
去给preprocess.g添加对应的代码,变为:
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.其中,由于
public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException {
中的BitSet找不到,所以无法编译,需要添加对应的:
import org.antlr.runtime.BitSet;
后,才可以正常编译和调试。
3.后来去原先的代码,才看出问题:
之前不小心把
recoverFromMismatchedToken
和
recoverFromMismatchedSet
都加到了:
@members
中,其对应着实际上是Parser的member,
所以应该去改为,加到:
@lexer::members
中去,才是加到Lexer的member中。
3.所以去试试,改为:
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); } }
最后,终于实现希望了,当第一个错误时,可以直接退出:
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的。
其中:
加到:
@members { ...... }
是默认加给Parser的;
加到:
@lexer::members { ...... }
是加给Lexer的。