Antlr4 Antlr深层规则集性能问题
我已经尝试过制作一个语法来理解类C语言的表达式优先级: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:
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有一个重要的预热阶段(为特定输入的路径构建内部结构)。完成此操作后,进一步的解析运行会快得多。