我该如何告诉ANTLR更喜欢另一种替代方案?

问题描述:

我有以下产品:我该如何告诉ANTLR更喜欢另一种替代方案?

expression 
    : primary # stubLabel 
    | expression '.' Identifier # stubLabel 
    | expression '.' 'this' # stubLabel 
    | expression '.' 'new' nonWildcardTypeArguments? innerCreator # stubLabel 
    | expression '.' 'super' superSuffix # stubLabel 
    | expression '.' explicitGenericInvocation # stubLabel 
    | expression '[' expression ']' # stubLabel 
    | Identifier arguments # namedMethodInvocation 
    | expression '.' Identifier arguments # namedMethodInvocation 
    | expression arguments # unnamedMethodInvocation 
    | // Lots of other patterns... 
    ; 

我愿解析器首先尝试unnamedMethodInvocation之前尝试namedMethodInvocation模式。这不会自动发生,因为ANTLR会尝试选择最长匹配的备选项,而不是使用第一个匹配策略。我如何强迫它做到这一点?

编辑:对不起,我忽略发布链接到上面的语法文件。 Here是。

+0

请发布'主要'生产规则。 – saka1029

+0

@ saka1029我很抱歉,我忽略了链接到我的文章中的完整语法文件!语法文件可以在这里找到(https://github.com/antlr/grammars-v4/blob/master/java/Java.g4#L540)。 “主要”生产规则是[here](https://github.com/antlr/grammars-v4/blob/master/java/Java.g4#L540)。 –

+0

在语法分析器规则中,从一个接一个,从上到下地排列(如语法中所写)并且第一个匹配的成功。订单本身就是一个问题,因为它决定了很多事情(例如优先级)。 –

尝试移动namedMethodInvocationprimary生产规则(之前Identifier)这样。

primary 
    : '(' expression ')' 
    | 'this' 
    | 'super' 
    | literal 
    | Identifier arguments // namedMethodInvocation 
    | Identifier 
    | typeType '.' 'class' 
    | 'void' '.' 'class' 
    | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) 
    ; 

或者在expression移动primary到最后。或者插入新规则primaryOrNamedMethodInvocation

expression 
    : primaryOrNamedMethodInvocation 
    | expression '.' Identifier 
    ..... 
    ; 

primaryOrNamedMethodInvocation 
    : Identifier arguments // namedMethodInvocation 
    | primary 
    ; 
+0

saka1029,我不想这样做,因为'namedMethodInvocation'是没有意义的。 ''nameMethodInvocation'应该匹配一个像'foo.bar()'这样的表达式,这太复杂了,无法成为主要的。 –

+0

增加了另一种解决方案。 – saka1029

+0

saka1029,我不认为这会影响结果,因为ANTLR根据它的时间长度来选择替代方案,而不是它在生产中的顺序。 –