根据我的语法,当我分析如下条目时:
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 堆栈为:
我现在无法重构这个语法。所以我正在寻找一种通过超时停止解析器执行的方法。
我已经使用 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,工作线程和池线程也会继续运行。
所以,
有什么办法可以停止 .< startRule > 吗?
我想到了不时调用一些回调来看看我们是否应该停止。
我不想使用线程,并使用 .stop (),因为它已被弃用且不安全。
有什么想法吗?
最佳答案
我确实需要复习语法,但现在做不到。
我按照迈克的想法,得到了预期的行为。
我实现了扩展 ParserATNSimulator 类:
public class ParserATNSimulatorWithTimeOut extends ParserATNSimulator {
private Instant start = Instant.now();
public ParserATNSimulatorWithTimeOut(org.antlr.v4.runtime.Parser parser, ATN atn, DFA[] decisionToDFA,
PredictionContextCache sharedContextCache) {
super(parser, atn, decisionToDFA, sharedContextCache);
}
@Override
protected void closure(ATNConfig config,
ATNConfigSet configs,
Set<ATNConfig> closureBusy,
boolean collectPredicates,
boolean fullCtx,
boolean treatEofAsEpsilon)
{
Duration timeElapsed = Duration.between(start, Instant.now());
if (timeElapsed.toMinutes() >= 1 )
{
Exception e = new ParseCancellationException("Too long!!!");
throw new ParseCancellationException(e);
}
super.closure(config, configs, closureBusy,collectPredicates,fullCtx,treatEofAsEpsilon);
}
}
并在 MyParser 中更改它。
public MyParser(TokenStream input) {
super(input);
_interp = new ParserATNSimulatorWithTimeOut(this,_ATN,_decisionToDFA,_sharedContextCache);
}
关于java - Antlr4 - 如何在解析器花费太长时间时停止解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56761502/