为什么这是左递归的,我该如何解决?
Why is this left-recursive and how do I fix it?
我正在学习 ANTLR4,我一度感到困惑。对于类似 Java 的语言,我正在尝试为成员链等结构添加规则,类似的东西:
expr1.MethodCall(expr2).MethodCall(expr3);
我收到一个错误,说我的两个规则是相互左递归的:
expression
: literal
| variableReference
| LPAREN expression RPAREN
| statementExpression
| memberAccess
;
memberAccess: expression DOT (methodCall | fieldReference);
我想我理解了为什么上面的规则组合被认为是左递归的:因为 memberAccess
是 expression
的候选者并且 memberAccess
以 expression
开头。
然而,当我看到(通过查看 the Java example)如果我只是将 memberAccess
的内容移动到 expression
时,我的理解就崩溃了,我没有从 ANTLR4 中得到任何错误(即使它仍然没有解析我想要的,似乎陷入了循环):
expression
: literal
| variableReference
| LPAREN expression RPAREN
| statementExpression
| expression DOT (methodCall | fieldReference)
;
- 为什么第一个示例是左递归的而第二个不是?
- 我需要做什么才能真正解析初始行?
第二个是左递归但不是互左递归。 ANTLR4 可以使用内置算法消除左递归规则。它不能消除互左递归规则。可能存在一种算法,但这很难保留动作和语义谓词。
出于某种原因,当我的语法有左递归时 ANTLRWorks 2 没有响应,导致我(错误地)认为我的语法是错误的。
从命令行编译和测试表明,具有直接左递归的版本实际上可以正确编译和解析。
(我把它留在这里以防其他人对 IDE 的行为感到困惑。)
我正在学习 ANTLR4,我一度感到困惑。对于类似 Java 的语言,我正在尝试为成员链等结构添加规则,类似的东西:
expr1.MethodCall(expr2).MethodCall(expr3);
我收到一个错误,说我的两个规则是相互左递归的:
expression
: literal
| variableReference
| LPAREN expression RPAREN
| statementExpression
| memberAccess
;
memberAccess: expression DOT (methodCall | fieldReference);
我想我理解了为什么上面的规则组合被认为是左递归的:因为 memberAccess
是 expression
的候选者并且 memberAccess
以 expression
开头。
然而,当我看到(通过查看 the Java example)如果我只是将 memberAccess
的内容移动到 expression
时,我的理解就崩溃了,我没有从 ANTLR4 中得到任何错误(即使它仍然没有解析我想要的,似乎陷入了循环):
expression
: literal
| variableReference
| LPAREN expression RPAREN
| statementExpression
| expression DOT (methodCall | fieldReference)
;
- 为什么第一个示例是左递归的而第二个不是?
- 我需要做什么才能真正解析初始行?
第二个是左递归但不是互左递归。 ANTLR4 可以使用内置算法消除左递归规则。它不能消除互左递归规则。可能存在一种算法,但这很难保留动作和语义谓词。
出于某种原因,当我的语法有左递归时 ANTLRWorks 2 没有响应,导致我(错误地)认为我的语法是错误的。
从命令行编译和测试表明,具有直接左递归的版本实际上可以正确编译和解析。
(我把它留在这里以防其他人对 IDE 的行为感到困惑。)