【问题标题】:How to avoid mutual left-recursion in ANTLR 4如何避免ANTLR 4中的相互左递归
【发布时间】:2014-01-14 12:20:27
【问题描述】:

我正在编写一个语法来处理标量和向量表达式。下面的语法被简化以显示我遇到的问题,标量表达式可以从向量派生,向量可以从标量派生。例如,向量可以是文字 [1, 2, 3] 或标量与向量 2 * [1, 2, 3] 的乘积(等效于 [2, 4, 6])。标量可以是文字2 或向量[1, 2, 3][1] 的索引(相当于2)。

grammar LeftRecursion;

Integer
    : [0-9]+
    ;

WhiteSpace
    : [ \t\r\n]+ -> skip
    ;

input
    : expression EOF;

expression
    : scalar
    | vector
    ;

scalar
    : Integer
    | vector '[' Integer ']'
    ;

vector
    : '[' Integer ',' Integer ',' Integer ']'
    | scalar '*' vector
    ;

ANTLR4 给了我错误:The following sets of rules are mutually left-recursive [scalar, vector]。这是有道理的,因为scalar 引用了vector,反之亦然,但同时它应该是确定性的。

我将如何重构此语法以避免相互(间接)左递归?我可以expand one of the terms inplace,但这会在完整的语法中引入很多重复,其中向量和标量有更多的替代方案。我也可以refactor the grammar to have a primary expression,但我不想让scalar '*' scalar 作为有效的vector 替代方案。还有其他选择吗?

【问题讨论】:

    标签: antlr4 left-recursion


    【解决方案1】:

    AFAIK,除了扩展以消除间接递归规则之外别无他法:

    expression
        : scalar
        | vector
        ;
    
    scalar
        : '[' Integer ',' Integer ',' Integer ']' '[' Integer ']'
        | scalar '*' vector '[' Integer ']'
        | Integer
        ;
    
    vector
        : '[' Integer ',' Integer ',' Integer ']'
        | scalar '*' vector
        ;
    

    【讨论】:

    • 您不能通过添加额外的规则来避免重复吗? IE。 vector_literal: '['Integer, Integer, Integer ']' 并在 scalarvector 中使用它? scalar: vector_literal '[' Integer ']'
    【解决方案2】:
    scalar
        : Integer
        | vector '[' Integer ']'
        ;
    
    vector
        : '[' Integer ',' Integer ',' Integer ']'
        | scalar '*' vector
        ;
    

    让你可以写一个表达式

    [i,i,i][i] * [i,i,i][i] * ... * [i,i,i]
    

    这将导致 java 和其他堆栈深度有限的语言的解析器堆栈溢出。

    我认为你应该为向量查找创建一个不同的语法规则,它不是一个标量,它只是 results 一个标量,但这应该在解析器树处理中处理,而不是在 ANTLR .

    【讨论】:

    • 几乎任何语法都可能导致无限的表达深度。以自引用规则scalar : Integer | scalar '*' scalar; 为例。这也可以扩展到任何长度1 * 2 * 3 * 4 * ... * n.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多