【背景】
折腾:
【记录】用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的。