ANTLR4性能问题

ANTLR4性能问题,antlr4,Antlr4,对ANTL4解析的性能进行了一些讨论,例如: 还有一个公开的bug报告: 这就需要使用两阶段策略来提高ANTLR4的性能。为此,首先在SLL模式下调用解析器,只有在出现故障时才使用较慢的LL模式 这对于小型语法非常有效,如994版中使用的语法: grammar expr; expr: ID | 'not' expr | expr 'and' expr | expr 'or' expr | expr 'between' expr 'and' expr

对ANTL4解析的性能进行了一些讨论,例如:

还有一个公开的bug报告:

这就需要使用两阶段策略来提高ANTLR4的性能。为此,首先在SLL模式下调用解析器,只有在出现故障时才使用较慢的LL模式

这对于小型语法非常有效,如994版中使用的语法:

grammar expr;

expr: ID
    | 'not' expr
    | expr 'and' expr
    | expr 'or' expr
    | expr 'between' expr 'and' expr
    ;

ID: [a-zA-Z_][a-zA-Z_0-9]*;
WS: [ \t\n\r\f]+ -> skip;
ERROR: .;
但如果语法变得稍微复杂和模糊:

/**
 * see https://github.com/antlr/antlr4/issues/994
 */
grammar numexpr;

numexpr: if_statement EOF;

if_statement:
  if_part ( else_part ) ? 'endif';

if_part:
  'if' expr statement_list|
  'if' expr;

else_part:
  'else' statement_list |
  'else';

statement_list:
  statement +;  


statement: if_statement; 

expr: ID
    | VALUE
    | 'not' expr
    | expr '=' expr
    | expr 'and' expr
    | expr 'or' expr
    | expr 'between' expr 'and' expr
    ;

VALUE: [0-9]+;
ID: [a-zA-Z_][a-zA-Z_0-9]*;
WS: [ \t\n\r\f]+ -> skip;
ERROR: .;
使用两阶段策略不再有效。 计时结果是:

  2    27 msecs   0,2
  3    95 msecs   3,5
  4    99 msecs   1,0
  5    64 msecs   0,6
  6    87 msecs   1,4
  7   181 msecs   2,1
  8   350 msecs   1,9
  9   822 msecs   2,3
 10  2912 msecs   3,5
 11  7134 msecs   2,4
 12 21420 msecs   3,0
ratio: 2,01
从输入开始添加每个“and valuex=x”表达式部分所需的时间是原来的两倍多

if Value=0  and not Value0=0 and not Value1=1 endif. 
需要对语法进行一些修改,使其适合SLL

这将如何实现?

询问相关问题。如果我加上

if(mode.equals(PredictionMode.LL\u EXACT\u AMBIG\u DETECTION)){
parserHolder.parser.addErrorListener(新的DiagnosticeErrorListener());
}
并将doTestParser行更改为:

doTestParser(parserHolder,PredictionMode.LL_-EXACT\u-AMBIG\u-DETECTION,PredictionMode.LL);
我也没有得到任何歧义行,但只得到:

if Value=0  and not Value0=0 and not Value1=1 endif
line 1:20 reportAttemptingFullContext d=6 (expr), input='andnotValue0'
line 1:12 reportContextSensitivity d=6 (expr), input='and'
line 1:37 reportAttemptingFullContext d=6 (expr), input='andnotValue1'
line 1:29 reportContextSensitivity d=6 (expr), input='and'
请在下面找到显示问题的JUnit测试。它由两个类组成——一个抽象基类和一个测试类,该类显示了

JUnit测试用例

package com.bitplan.ruleparser;
导入java.io.IOException;
导入org.antlr.v4.runtime.antlInputStream;
导入org.antlr.v4.runtime.CommonTokenStream;
导入org.antlr.v4.runtime.Lexer;
导入org.antlr.v4.runtime.ParserRuleContext;
导入org.junit.Test;
导入com.bitplan.expr.exprLexer;
导入com.bitplan.expr.exprParser;
导入com.bitplan.numexpr.numexprLexer;
导入com.bitplan.numexpr.numexprParser;
/**
*测试问题994的性能
* 
*@author wf
*
*/
公共类TestIssue994扩展了TestTwoPhaseParser{
公共静态类ExprParserHolderFactory扩展ParserHolderFactory{
@凌驾
ParserHolder getParserHolder(int索引)引发异常{
返回新的ExprParserHolder(索引);
}
}
/**
* 
*@author wf
*
*/
公共静态类ExprParserHolder扩展了ParserHolder{
public ExprParserHolder(int索引)引发IOException{
超级(指数);
}
私人快递公司;
@凌驾
受保护的org.antlr.v4.runtime.Parser getParser(CommonTokenStream令牌){
mParser=新的exprParser(令牌);
返回mParser;
}
@凌驾
受保护的Lexer getLexer(AntlInputStream-in){
返回新的exprLexer(in);
}
@凌驾
受保护的ParserRuleContext parse(){
返回mParser.expr();
}
@凌驾
受保护的字符串getInput(int索引){
字符串ANDCLASSION=“非X0”;

对于(int i=0;i您应该按描述拆分左递归
expr
非递归或基本递归规则。

这是@kvantt建议拆分后语法的处理方式

/**
 * see https://github.com/antlr/antlr4/issues/994
 */
grammar primrecexpr;

primrecexpr: if_statement EOF;

if_statement:
  if_part ( else_part ) ? 'endif';

if_part:
  'if' expr statement_list|
  'if' expr;

else_part:
  'else' statement_list |
  'else';

statement_list:
  statement +;  

statement: if_statement; 


expr:
    notexpr
    | expr 'and' expr
    | expr 'or' expr
    ;    

notexpr: 
    'not' notexpr
    | equalexpr;

equalexpr: 
    atomexpr |   
    equalexpr '=' equalexpr
    ;

atomexpr:
   ID
    | VALUE;

VALUE: [0-9]+;
ID: [a-zA-Z_][a-zA-Z_0-9]*;
WS: [ \t\n\r\f]+ -> skip;
ERROR: .;

使用修改后的Grammarth查看计时结果会很好。结果是对性能没有任何可测量的影响,这取决于表达式的长度。基本上,解析时间总是相同的,并且取决于计算机的速度。
/**
 * see https://github.com/antlr/antlr4/issues/994
 */
grammar primrecexpr;

primrecexpr: if_statement EOF;

if_statement:
  if_part ( else_part ) ? 'endif';

if_part:
  'if' expr statement_list|
  'if' expr;

else_part:
  'else' statement_list |
  'else';

statement_list:
  statement +;  

statement: if_statement; 


expr:
    notexpr
    | expr 'and' expr
    | expr 'or' expr
    ;    

notexpr: 
    'not' notexpr
    | equalexpr;

equalexpr: 
    atomexpr |   
    equalexpr '=' equalexpr
    ;

atomexpr:
   ID
    | VALUE;

VALUE: [0-9]+;
ID: [a-zA-Z_][a-zA-Z_0-9]*;
WS: [ \t\n\r\f]+ -> skip;
ERROR: .;