Parsing 在ANTLR4中使用什么来解决更复杂情况下的歧义(而不是语法谓词)?

Parsing 在ANTLR4中使用什么来解决更复杂情况下的歧义(而不是语法谓词)?,parsing,antlr,antlr4,Parsing,Antlr,Antlr4,在ANTLRv3中,可以使用语法谓词来解决歧义,即显式地告诉ANTLR应该选择哪个替代方案。ANTLR4似乎只是接受具有类似歧义的语法,但在解析过程中它会报告这些歧义。它产生了一个解析树,尽管存在这些歧义(根据文档,通过选择第一个备选方案)。但如果我想让它选择其他的选择,我能做什么呢?换句话说,我如何明确地解决歧义 (有关悬挂else问题的简单情况,请参见:) 一个更复杂的例子: 如果我有这样的规则: expr : expr '[' expr? ']' | ID expr

在ANTLRv3中,可以使用语法谓词来解决歧义,即显式地告诉ANTLR应该选择哪个替代方案。ANTLR4似乎只是接受具有类似歧义的语法,但在解析过程中它会报告这些歧义。它产生了一个解析树,尽管存在这些歧义(根据文档,通过选择第一个备选方案)。但如果我想让它选择其他的选择,我能做什么呢?换句话说,我如何明确地解决歧义

(有关悬挂else问题的简单情况,请参见:)

一个更复杂的例子:

如果我有这样的规则:

expr
    :   expr '[' expr? ']'
    |   ID expr
    |   '[' expr ']'
    |   ID
    |   INT
    ;
这将把
foo[4]
解析为
(expr foo(expr[(expr 4)])
。但我可能想将其解析为
(expr(expr foo)[(expr 4)])
。(也就是说,如果可能的话,总是选择第一个备选方案。它是第一个备选方案,因此根据文档,它应该具有更高的优先级。那么它为什么要构建这棵树呢?)

如果我理解正确,我有两种解决方案:

  • 基本上用语义谓词实现语法谓词(但是,在这种情况下,我不确定如何实现)

  • 重新构造语法

  • 例如,将
    expr
    替换为
    e

    e   :   expr | pe
        ;
    
    expr
        :   expr '[' expr? ']'
        |   ID expr
        |   ID
        |   INT
        ;
    
    pe  :   '[' expr ']'
        ;
    
    尽管语法变得更加复杂,但这似乎奏效了


    我可能误解了一些事情,但这两种解决方案似乎都不如语法谓词那么优雅和复杂。尽管如此,我还是喜欢使用
    ??
    操作符解决悬空else问题。但我不知道在这种情况下如何使用。有可能吗?

    您可以通过将
    ID
    选项置于
    ID expr
    上方来解决此问题。当消除左递归时,所有非左递归的备选方案都会在左递归的备选方案之前进行解析

    对于您的示例,第一个非左递归替代项
    ID expr
    与整个表达式匹配,因此之后没有任何内容可供解析。

    要获取此表达式(expr(expr foo)[(expr 4)],可以使用

    顶部:expr-EOF

    expr:expr'['expr?']| ID | INT


    我更新了您的示例,使用运算符
    [
    ]
    而不是
    ,以使读者清楚地了解以LISP语法打印示例时的格式。我尝试将ID置于ID expr之上。不幸的是,这并不能解决问题,我仍然得到相同的树。