Antlr4 Antlr深层规则集性能问题

Antlr4 Antlr深层规则集性能问题,antlr4,context-free-grammar,Antlr4,Context Free Grammar,我已经尝试过制作一个语法来理解类C语言的表达式优先级: var a = expression0.expression1(expression2 + expression3() * expression4) 当正确排列优先级时,将变为: var a = (expression0.expression1)(expression2 + ((expression3()) * expression4)) 为了实现这一点,我将表达式按优先级排序为规则。以下是我语法中的相关摘录: expression:

我已经尝试过制作一个语法来理解类C语言的表达式优先级:

var a = expression0.expression1(expression2 + expression3() * expression4)
当正确排列优先级时,将变为:

var a = (expression0.expression1)(expression2 + ((expression3()) * expression4))
为了实现这一点,我将表达式按优先级排序为规则。以下是我语法中的相关摘录:

expression: assignmentExpression;
assignmentExpression
    : equalityExpression ASSIGNMENT assignmentExpression
    | equalityExpression
    ;
equalityExpression
    : logicalExpression equals equalityExpression
    | logicalExpression notEquals equalityExpression
    | logicalExpression
    ;
logicalExpression
    : relationalExpression and logicalExpression
    | relationalExpression or logicalExpression
    | relationalExpression
    ;
relationalExpression
    : addExpression greaterThan relationalExpression
    | addExpression lessThan relationalExpression
    | addExpression greaterOrEquals relationalExpression
    | addExpression lessOrEquals relationalExpression
    | addExpression
    ;
addExpression
    : multiplyExpression add addExpression
    | multiplyExpression subtract addExpression
    | multiplyExpression
    ;
multiplyExpression
    : conversionExpression multiply multiplyExpression
    | conversionExpression divide multiplyExpression
    | conversionExpression
    ;
conversionExpression
    : unaryExpression AS conversionExpression
    | unaryExpression
    ;
unaryExpression
    : subtract unaryExpression
    | add unaryExpression
    | ifExpression
    ;
ifExpression
    : IF PAREN expression ENDPAREN expression (ELSE expression)?
    | instantiationExpression
    ;
instantiationExpression
    : NEW invocationExpression
    | invocationExpression
    ;
invocationExpression
    : reachExpression PAREN arguments? ENDPAREN
    | reachExpression
    ;
reachExpression
    : primeExpression DOT primeExpression
    | primeExpression
    ;
在以下代码中使用它:

{ int a = 7 }
生成以下输出:

expression
 assignmentExpression
  equalityExpression
   logicalExpression
    relationalExpression
     addExpression
      multiplyExpression
       conversionExpression
        unaryExpression
         ifExpression
          instantiationExpression
           invocationExpression
            reachExpression
             primeExpression
              blockExpression
               "{"
               statement
                variableDeclaration
                 variableType
                  type
                   identifier
                    "int"
                 identifier
                  "a"
                 variableInitialization
                  "="
                  expression
                   assignmentExpression
                    equalityExpression
                     logicalExpression
                      relationalExpression
                       addExpression
                        multiplyExpression
                         conversionExpression
                          unaryExpression
                           ifExpression
                            instantiationExpression
                             invocationExpression
                              reachExpression
                               primeExpression
                                literal
                                 integer
                                  "7"
               "}"
它可能有问题,但我不能真正测试它,因为这种语法会导致疯狂的性能损失。我以前的语法从左到右解析表达式需要几毫秒的时间,而这一次需要整整2分钟

我已经追踪到了
parsertansimulator.AdaptivePredict
,在更深层次上,这个问题是一堆疯狂的

ParserATNSimulator.Closure
ParserATNSimulator.ClosureCheckingStopState
ParserATNSimulator.Closure_
它似乎不是为了得到正确的表达式(number-literal:7),而是为了每个规则级别向下一次。所以这不是O(n),而是O(n^n)才得到那该死的“7”

这是Antlr的问题,还是我的语法问题,还是它的现状


编辑: 好的,我已经设法通过以下方式重写语法来消除性能问题:

assignmentExpression: equalityExpression (ASSIGNMENT assignmentExpression)?;

但是我仍然不明白为什么会发生这种情况,以及这种变化是如何解决这个问题的。

您不需要像ANTLR4那样使用多个表达式规则来编码优先级。您可以只使用一个左递归表达式规则,并按优先级降序列出备选方案,以及假定为右关联的规则的注释。您确定这是真的吗?然后,我将如何将应该具有相同优先级(从左到右求值)的规则编码为
expression op=(“+”|“-”)expression
expression additiveOp expression
,其中
additiveOp
定义为
“+”|“-”。请看一看,以了解这一点在实际语言语法中的作用。好的,谢谢,我要尝试一下。另外,不要测量给定输入的第一次解析运行。ANTLR4有一个重要的预热阶段(为特定输入的路径构建内部结构)。完成此操作后,进一步的解析运行会快得多。