用我的语法,当我分析像这样的条目时:

ZZ9->ZZ9_LINHA  :=  &(_cAlias+"->(CONTAEBTA)"   )+& (_cAlias+"->(REGISTRO)"     )+& (_cAlias+"->(TRANSACAO)"    )+& (_cAlias+"->(REFERENCIA)"   )+;
                    &(_cAlias+"->(REFPAGTO)"    )+& (_cAlias+"->(STATTRANSA)"   )+& (_cAlias+"->(NAOUSADO1)"    )+& (_cAlias+"->(NAOUSADO2)"    )+;
                    &(_cAlias+"->(NUMFATURA)"   )+& (_cAlias+"->(INDDISPUTA)"   )+& (_cAlias+"->(DATFATURAM)"   )+& (_cAlias+"->(DATPARTIDA)"   )+;
                    &(_cAlias+"->(NOMVIAJANT)"  )+& (_cAlias+"->(INIVIAJANT)"   )+& (_cAlias+"->(ROTA)"         )+& (_cAlias+"->(NAOUSADO3)"    )+;
                    &(_cAlias+"->(CENTROCUST)"  )+& (_cAlias+"->(STATUSPGTO)"   )+& (_cAlias+"->(VALORPAGTO)"   )+& (_cAlias+"->(SINALPAGTO)"   )+;
                    &(_cAlias+"->(VALORTRANS)"  )+& (_cAlias+"->(SINALTRANS)"   )+& (_cAlias+"->(NAOUSADO4)"    )+& (_cAlias+"->(NAOUSADO5)"    )+;
                    &(_cAlias+"->(NAOUSADO6)"   )+& (_cAlias+"->(NAOUSADO7)"    )+& (_cAlias+"->(NUMBILHETE)"   )+& (_cAlias+"->(CIAAEREA)"     )+;
                    &(_cAlias+"->(DATEMISSAO)"  )+& (_cAlias+"->(TAXAEMBARQ)"   )+& (_cAlias+"->(SINALTXEMB)"   )+& (_cAlias+"->(VLRBILHET)"    )+;
                    &(_cAlias+"->(SINBILHET)"   )+& (_cAlias+"->(NAOUSADO8)"    )+& (_cAlias+"->(NAOUSADO9)"    )+& (_cAlias+"->(TIPDESPESA)"   )+;
                    &(_cAlias+"->(DATDESPESA)"  )+& (_cAlias+"->(DEPTO)"        )+& (_cAlias+"->(MATRICULA)"    )+& (_cAlias+"->(CODIATA)"      )+;
                    &(_cAlias+"->(NAOUSADOA)"   )+& (_cAlias+"->(REQVIAGEM)"    )+& (_cAlias+"->(NAOUSADOB)"    )+& (_cAlias+"->(CLASSEVOO)"    )


解析器变得越来越慢,并且使用越来越多的内存。

如果工作线程已暂停,则ANTLR4堆栈为:

java - Antlr4-如何在花费太长时间时停止解析器-LMLPHP

我现在无法对此语法进行重构。因此,我正在寻找一种通过超时停止执行解析器的方法。

我已经使用ExecutorService和Future尝试了以下方法:

public class MyParserIsolateThread implements Callable<ParseTree> {

    public String ppo;
    public MyParserIsolateThread(String ppoInfo)
    {
        this.ppo = ppoInfo;
    }

    @Override
    public ParseTree call() throws Exception {

        NoCaseANTLRStringStream input = new NoCaseANTLRStringStream(this.ppo);
        MyLexer lexer = new MyLexer(input);
        CommonTokenStream token = new CommonTokenStream(lexer);
        MyParser parser = new MyParser(token);
        AntlrToSonarErrorListener error = new AntlrToSonarErrorListener(null,null,ppo);
        parser.addErrorListener(error);
        long startTime = System.currentTimeMillis();
        System.out.println("Starting parsing...");
        ParseTree tree = parser.program();
        long estimatedTime = System.currentTimeMillis() - startTime;
        System.out.println("Parse Finished. Elapsed time:" + estimatedTime);
        return tree;
    }

}


    MyParserIsolateThread threadParser = new MyParserIsolateThread(ppo);
    ExecutorService executorService = Executors.newFixedThreadPool(1);

    Future<ParseTree> result = executorService.submit(threadParser);
    try {
        ParseTree tree = result.get(60, TimeUnit.SECONDS);
        System.out.println("Parser OK ");
    } catch (Exception e) {
        // interrupts if there is any possible error
        System.out.println("too long parsing...");
        result.cancel(true);

    }
    executorService.shutdownNow();
    try {
        executorService.awaitTermination(1, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("end.");


如果我使用一个耗时超过60秒的条目,则会正确显示该消息,但是即使使用shutdownNow,工作线程和池线程也会继续运行。

所以,

有什么方法可以停止。吗?

我想到了不时调用的回调函数,以查看是否应该停止。

我不想使用Thread,而使用.stop(),因为它已被弃用且不安全。

任何想法?

最佳答案

您可以使用与BailOutErrorStrategy相同的方法:万一发生错误,它会引发异常,解析机制无法捕获该异常。

在运行解析器之前,将它添加到解析器中。覆盖enterEveryRule方法,并在调用该方法时检查解析器到目前为止运行的时间。如果超时,则抛出您的停止异常,该异常将立即停止解析运行。您可以在代码中捕获此异常,以查看是否已达到超时。

10-07 15:49
查看更多