【问题标题】:How to remove indirect left-recursion from grammar如何从语法中删除间接左递归
【发布时间】:2013-11-01 13:13:04
【问题描述】:

我有一些相互左递归的 ANTLR 代码:

expr: int_liter
| bool_liter
| char_liter
| str_liter
| pair_liter
| ident
| array_elem
| unary_oper expr
| expr binary_oper expr
| OPEN_PARENTHESES expr CLOSE_PARENTHESES
;

array_elem:  expr  OPEN_BRACKET expr CLOSE_BRACKET ;

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: parsing recursion antlr grammar left-recursion


    【解决方案1】:

    ANTLR 4 只能处理直接左递归,但您的语法包含来自规则 exprarray_elemexpr 的间接左递归。在您的特定语法中解决此问题的最简单方法是将array_elem 规则内联到expr 规则中,并使用标记的外部替代项为expr 中的每个替代项分配有意义的名称。

    expr
      : int_liter                                # someLabel
      | bool_liter                               # someLabel               
      | char_liter                               # someLabel
      | str_liter                                # someLabel
      | pair_liter                               # someLabel
      | ident                                    # someLabel
      | expr OPEN_BRACKET expr CLOSE_BRACKET     # array_elem
      | unary_oper expr                          # someLabel
      | expr binary_oper expr                    # someLabel
      | OPEN_PARENTHESES expr CLOSE_PARENTHESES  # someLabel
      ;
    

    注意以下关于使用标记的外部替代品的限制:

    1. 没有两个外部替代项可以共享一个标签,并且标签不能匹配任何规则名称;标签在整个语法中必须是唯一的。
    2. 如果标记了规则的一个外部替代项(例如 array_elem 替代项),则必须标记该规则的所有外部替代项。

    【讨论】:

    • 我很震惊地得知,像 ANTLR 这样的现代工具无法做到 yacc 自 70 年代以来所能做到的事情。
    • @Ingo:ANTLR 是一个 LL 解析器生成器; YACC 是一个 LALR 解析器生成器。你把苹果比作大米。
    • 这对我来说是个新闻。我一直认为ANTLR中的LR承诺了LALR。无论如何,我很高兴我从来没有努力学习 ANTLR 并坚持使用 yacc(或者,pbyacc -j,如果你需要一些 java-ish)
    • @280Z28 嘿,谢谢你的回答!另一个问题,我试图做标签,现在当从像这样assign_lhs: ident | array_elem | pair_elem ; 的其他规则调用时,array_elem 规则说是未定义的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    相关资源
    最近更新 更多