解决相互左递归文法
Resolve mutual left recursive grammar
问题
我正在使用 Antlr4 开发 grammar for the VBA language based on the Microsoft specification。我试图严格遵守语法规范,但由于这一原因,有一个相互左递归错误需要解决。这是显示问题的完整语法的一个子集:
lExpression
: simpleNameExpression
| Me //instanceExpression 5.6.11
| memberAccessExpression
| indexExpression
| dictionaryAccessExpression
| withExpression
;
memberAccessExpression : lExpression '.' unrestrictedName;
indexExpression : lExpression '(' argumentList ')';
dictionaryAccessExpression : lExpression '!' unrestrictedName;
我可以将子表达式移动到主 lExpression
规则中以克服最初的问题,但我会在其他规则中引起问题,例如:
callStatement
: Call? (simpleNameExpression | memberAccessExpression | indexExpression | withExpression);
它标识规则中允许的特定子表达式。还有其他地方也会出现这种情况,我就举这家为例。
想法 1
这样写callStatement
:
callStatement
: Call? lExpression;
然后找到一种方法来禁用 callStatement
中的 lExpression
成为 Me
或 dictionaryAccessExpression
。
想法 2
这样写callStatement
:
callStatement
: Call? (simpleNameExpression | lExpression '.' unrestrictedName | lExpression '(' argumentList ')' | withExpression);
但我不确定 Antlr 是否会喜欢它。
想法
我也许可以使用语义谓词 and/or 重写来改进这一点,但我在这方面还很新手。
如有任何想法,我们将不胜感激。
你能不能不让memberAccessExpression
、indexExpression
和dictionaryAccessExpression
保持原样,这样callStatement
就可以使用它们,结束在[=17里面扩展这些规则=]:
lExpression
: simpleNameExpression
| Me //instanceExpression 5.6.11
| lExpression '.' unrestrictedName
| lExpression '(' argumentList ')'
| lExpression '!' unrestrictedName
| withExpression
;
memberAccessExpression : lExpression '.' unrestrictedName;
indexExpression : lExpression '(' argumentList ')';
dictionaryAccessExpression : lExpression '!' unrestrictedName;
callStatement
: Call? (simpleNameExpression | memberAccessExpression | indexExpression | withExpression)
;
[...] Is it possible to use a rewrite rule in lExpression to add the memberAccessExpression etc nodes to the parse tree?
唉,v4 不支持重写规则。但是,您可以使用 rule labels 以便在您的听众或访问者内部很清楚您是哪种选择:
lExpression
: simpleNameExpression #SimpleNameExpressionAlt
| Me #MeExpressionAlt
| lExpression '.' unrestrictedName #MemberAccessExpressionAlt
| lExpression '(' argumentList ')' #IndexExpressionAlt
| lExpression '!' unrestrictedName #DictionaryAccessExpressionAlt
| withExpression #WithExpressionAlt
;
然后在侦听器中覆盖 enterMemberAccessExpressionAlt
:
public class YourListener extends YourBaseListener {
@Override
public void enterMemberAccessExpressionAlt(YourParser.MemberAccessExpressionAltContext ctx) {
// ...
}
}
问题
我正在使用 Antlr4 开发 grammar for the VBA language based on the Microsoft specification。我试图严格遵守语法规范,但由于这一原因,有一个相互左递归错误需要解决。这是显示问题的完整语法的一个子集:
lExpression
: simpleNameExpression
| Me //instanceExpression 5.6.11
| memberAccessExpression
| indexExpression
| dictionaryAccessExpression
| withExpression
;
memberAccessExpression : lExpression '.' unrestrictedName;
indexExpression : lExpression '(' argumentList ')';
dictionaryAccessExpression : lExpression '!' unrestrictedName;
我可以将子表达式移动到主 lExpression
规则中以克服最初的问题,但我会在其他规则中引起问题,例如:
callStatement
: Call? (simpleNameExpression | memberAccessExpression | indexExpression | withExpression);
它标识规则中允许的特定子表达式。还有其他地方也会出现这种情况,我就举这家为例。
想法 1
这样写callStatement
:
callStatement
: Call? lExpression;
然后找到一种方法来禁用 callStatement
中的 lExpression
成为 Me
或 dictionaryAccessExpression
。
想法 2
这样写callStatement
:
callStatement
: Call? (simpleNameExpression | lExpression '.' unrestrictedName | lExpression '(' argumentList ')' | withExpression);
但我不确定 Antlr 是否会喜欢它。
想法
我也许可以使用语义谓词 and/or 重写来改进这一点,但我在这方面还很新手。
如有任何想法,我们将不胜感激。
你能不能不让memberAccessExpression
、indexExpression
和dictionaryAccessExpression
保持原样,这样callStatement
就可以使用它们,结束在[=17里面扩展这些规则=]:
lExpression
: simpleNameExpression
| Me //instanceExpression 5.6.11
| lExpression '.' unrestrictedName
| lExpression '(' argumentList ')'
| lExpression '!' unrestrictedName
| withExpression
;
memberAccessExpression : lExpression '.' unrestrictedName;
indexExpression : lExpression '(' argumentList ')';
dictionaryAccessExpression : lExpression '!' unrestrictedName;
callStatement
: Call? (simpleNameExpression | memberAccessExpression | indexExpression | withExpression)
;
[...] Is it possible to use a rewrite rule in lExpression to add the memberAccessExpression etc nodes to the parse tree?
唉,v4 不支持重写规则。但是,您可以使用 rule labels 以便在您的听众或访问者内部很清楚您是哪种选择:
lExpression
: simpleNameExpression #SimpleNameExpressionAlt
| Me #MeExpressionAlt
| lExpression '.' unrestrictedName #MemberAccessExpressionAlt
| lExpression '(' argumentList ')' #IndexExpressionAlt
| lExpression '!' unrestrictedName #DictionaryAccessExpressionAlt
| withExpression #WithExpressionAlt
;
然后在侦听器中覆盖 enterMemberAccessExpressionAlt
:
public class YourListener extends YourBaseListener {
@Override
public void enterMemberAccessExpressionAlt(YourParser.MemberAccessExpressionAltContext ctx) {
// ...
}
}