【问题标题】:ANTLR: VERY slow parsingANTLR:解析非常慢
【发布时间】:2016-08-12 22:17:34
【问题描述】:

我已经成功地将我的表达式拆分为算术和布尔表达式,如下所示:

/* entry point */
parse: formula EOF;


formula : (expr|boolExpr);

/* boolean expressions : take math expr and use boolean operators on them */

boolExpr
  : bool                                            
  | l=expr operator=(GT|LT|GEQ|LEQ) r=expr          
  | l=boolExpr operator=(OR|AND) r=boolExpr         
  | l=expr (not='!')? EQUALS r=expr                 
  | l=expr BETWEEN low=expr AND high=expr           
  | l=expr IS (NOT)? NULL                           
  | l=atom LIKE regexp=string                       
  | l=atom ('IN'|'in') '(' string (',' string)* ')' 
  | '(' boolExpr ')'                                
  ;

/* arithmetic expressions */
expr
    : atom                                                 
    | (PLUS|MINUS) expr                                    
    | l=expr operator=(MULT|DIV) r=expr                    
    | l=expr operator=(PLUS|MINUS) r=expr                  
    | function=IDENTIFIER '(' (expr ( ','  expr )* ) ? ')' 
    | '(' expr ')'                                         
    ;

atom
    : number
    | variable
    | string
    ;

但现在我遇到了巨大的性能问题。我尝试解析的一些公式非常慢,以至于它变得难以忍受:一个多小时(我在那一刻停下来)来解析这个:

-4.77+[V1]*-0.0071+[V1]*[V1]*0+[V2]*-0.0194+[V2]*[V2]*0+[V3]*-0.00447932+[V3]*[V3]*-0.0017+[V4]*-0.00003298+[V4]*[V4]*0.0017+[V5]*-0.0035+[V5]*[V5]*0+[V6]*-4.19793004+[V6]*[V6]*1.5962+[V7]*12.51966636+[V7]*[V7]*-5.7058+[V8]*-19.06596752+[V8]*[V8]*28.6281+[V9]*9.47136506+[V9]*[V9]*-33.0993+[V10]*0.001+[V10]*[V10]*0+[V11]*-0.15397774+[V11]*[V11]*-0.0021+[V12]*-0.027+[V12]*[V12]*0+[V13]*-2.02963068+[V13]*[V13]*0.1683+[V14]*24.6268688+[V14]*[V14]*-5.1685+[V15]*-6.17590512+[V15]*[V15]*1.2936+[V16]*2.03846688+[V16]*[V16]*-0.1427+[V17]*9.02302288+[V17]*[V17]*-1.8223+[V18]*1.7471106+[V18]*[V18]*-0.1255+[V19]*-30.00770912+[V19]*[V19]*6.7738

你知道问题是什么吗?

当解析器进入formula语法规则时,解析停止。

编辑这里的原始问题:

我的语法允许这样做:

// ( 1 LESS_EQUALS 2 )
1 <= 2  

但我在 G4 文件中表达它的方式使它也接受了这一点:

// ( ( 1 LESS_EQUALS 2 ) LESS_EQUALS 3 )
1 <= 2 <= 3

我不想要的。

我的语法包含这个:

expr
    : atom                                                 # atomArithmeticExpr
    | (PLUS|MINUS) expr                                    # plusMinusExpr
    | l=expr operator=('*'|'/') r=expr                     # multdivArithmeticExpr
    | l=expr operator=('+'|'-') r=expr                     # addsubtArithmeticExpr
    | l=expr operator=('>'|'<'|'>='|'<=') r=expr           # comparisonExpr
[...]

我如何告诉 Antlr 这是不可接受的?

【问题讨论】:

  • 你有没有解决过速度问题?我也遇到了。

标签: antlr4 operator-precedence


【解决方案1】:

只需将根分成两部分。将根“expr”重命名为“rootexpr”,反之亦然。

rootExpr
    : atom                                                 # atomArithmeticExpr
    | (PLUS|MINUS) expr                                    # plusMinusExpr
    | l=expr operator=('*'|'/') r=expr                     # multdivArithmeticExpr
    | l=expr operator=('+'|'-') r=expr                     # addsubtArithmeticExpr
    | l=expr operator=('>'|'<'|'>='|'<=') r=expr           # comparisonExpr

编辑:你不能在 expr 规则中有循环引用 => expr 节点。

【讨论】:

  • 呃?但是,expr 的定义是什么?
  • 你的问题是,如何告诉 Antlr,这是不可接受的。因此,如果您确实只想允许一个运算符表达式,我告诉您不要使用循环引用。当然,这不是完整的语法,只是重点。 expr 规则可以定义为不同的规则,或者如果适用,您可以使用“原子”规则。
猜你喜欢
  • 2011-12-18
  • 2013-09-03
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-18
  • 2014-05-04
相关资源
最近更新 更多