首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >删除此语法中的间接左递归

删除此语法中的间接左递归
EN

Stack Overflow用户
提问于 2020-09-02 02:03:08
回答 2查看 95关注 0票数 1

我正在尝试弄清楚如何从Ruby解析器(https://github.com/kenaniah/ruby-parser/blob/master/ruby-parser/src/parsers/expression/logical.rs)的Rust端口中的逻辑关键字表达式中删除间接的左递归。语法看起来像这样:

代码语言:javascript
复制
E --> N | A | O | t
N --> n E
A --> E a E
O --> E o E
代码语言:javascript
复制
E = expression
A = keyword_and_expression
O = keyword_or_expression
N = keyword_not_expression

如何进行转换以删除AO中的递归

EN

回答 2

Stack Overflow用户

发布于 2020-09-02 03:41:04

我认为这里的问题不是间接递归,而是歧义。

如果只是间接递归,您可以简单地替换NAO的右侧,从而消除间接递归:

代码语言:javascript
复制
E → n E
  | E a E
  | E o E
  | t

为了摆脱直接的左递归,你可以使用左因子:

代码语言:javascript
复制
E → n E
  | E A'
  | t
A'→ a E
  | o E

然后删除剩余的左递归:

代码语言:javascript
复制
E → n E E'
  | t E'
E'→ ε
  | A' E'
A'→ a E
  | o E

它没有直接或间接的左递归,并且每个规则都以唯一的终结点开头。但是,它不是LL(1),因为存在first/follow冲突。

这并不奇怪,因为原始语法是高度歧义的,而且左递归消除不了歧义。只有在伴随operator precedence table的情况下,原始语法才有意义。

该表表明,ANDOR是具有相同优先级的左结合运算符(这是一个稍微不寻常的决定),而NOT是具有更高优先级的一元运算符。反过来,这意味着BNF应该是这样编写的:

代码语言:javascript
复制
N → n N
  | t
E → A
  | O
  | N
A → E a N
O → E o N
N → n N
  | t

与OP中的语法的唯一区别是消除了歧义,如优先表所示。

同样,第一步是替换非终结符AO,以使左递归更直接:

代码语言:javascript
复制
E → E a N
  | E o N
  | N
N → n N
  | t

这基本上与算术表达式的语法相同(忽略乘法,因为只有一个优先级),并且可以直接消除左递归:

代码语言:javascript
复制
E  → N E'
E' → a E
   | o E
   | ε
N  → n N
   | t
票数 0
EN

Stack Overflow用户

发布于 2020-09-02 03:52:02

根据此factorization tool,生成的语法将为:

代码语言:javascript
复制
E  -> N
    | A
    | O
    | t
N  -> n E
A  -> n E a E A'
    | O a E A'
    | t a E A'
O  -> n E o E O'
    | n E a E A' o E O'
    | t a E A' o E O'
    | t o E O'
A' -> a E A'
    | ϵ
O' -> a E A' o E O'
    | o E O'
    | ϵ

由于E的多个产品,看起来AO的分解最终变得相当复杂。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63693126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档