最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】在用antlr预处理一个新的hart的eddl文件时希望第一次出错就退出

ANTLR crifan 2614浏览 0评论

【背景】

折腾:

【记录】用antlr的preprocess去预处理一个新的eddl文件去除eddl中不支持的元素对应的文件内容

期间,希望实现:

对于当前预处理的新的hart的eddl文件

第一次出错,即那个MismatchedTokenException,就退出。

以此希望实现后续的,方便调试而找到具体错误的根本原因,并希望最终解决此问题。

【解决过程】

1.经过参考之前自己的:

【记录】antlr的异常处理:遇到第一个错误就停止和退出

中的:

【已解决】antlr中尝试出错就退出,结果编译parser出错:error: recoverFromMismatchedSet(IntStream,RecognitionException,BitSet) in xxxParser cannot override recoverFromMismatchedSet(IntStream,RecognitionException,BitSet) in BaseRecognizer,return type void is not compatible with Object

去给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

如图:

exception quit for first error while preprocessing

 

【总结】

在给antlr的语法文件中加代码时,要搞清楚是加给Lexer还是Parser的。

 

其中:

加到:

@members {
    ......
}

是默认加给Parser的;

加到:

@lexer::members {
    ......
}

是加给Lexer的。

转载请注明:在路上 » 【已解决】在用antlr预处理一个新的hart的eddl文件时希望第一次出错就退出

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.150 seconds, using 22.11MB memory