解决相互左递归语法

时间:2015-07-12 00:34:11

标签: vba parsing grammar antlr4

问题

我正在使用Antlr4基于grammar为VBA语言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;

然后找到一种方法来禁用lExpressioncallStatementMe中的dictionaryAccessExpression

创意2

像这样写callStatement

callStatement               
    :   Call? (simpleNameExpression | lExpression '.' unrestrictedName | lExpression '(' argumentList ')' | withExpression);

但我不确定Antlr是否会喜欢这样。

思想

我或许可以使用语义谓词和/或重写来改善这一点,但我在这方面非常环保。

任何想法都会非常感激。

1 个答案:

答案 0 :(得分:1)

你能不能保持indexExpressiondictionaryAccessExpressioncallStatement不变,以便lExpression可以使用它们,最后在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) ; 内扩展这些规则:

lExpression
    :   simpleNameExpression               #SimpleNameExpressionAlt
    |   Me                                 #MeExpressionAlt
    |   lExpression '.' unrestrictedName   #MemberAccessExpressionAlt
    |   lExpression '(' argumentList ')'   #IndexExpressionAlt
    |   lExpression '!' unrestrictedName   #DictionaryAccessExpressionAlt
    |   withExpression                     #WithExpressionAlt
    ;
  

[...]是否可以在lExpression中使用重写规则将memberAccessExpression等节点添加到解析树?

唉,v4不支持重写规则。但是,您可以使用rule labels,以便在您的听众或访问者中明确您的选择:

enterMemberAccessExpressionAlt

然后在监听器中,您将覆盖public class YourListener extends YourBaseListener { @Override public void enterMemberAccessExpressionAlt(YourParser.MemberAccessExpressionAltContext ctx) { // ... } }

sharedInstance