【问题标题】:Eliminating Left Recursion from this weird Expression Grammar从这个奇怪的表达式语法中消除左递归
【发布时间】:2017-07-01 01:17:57
【问题描述】:

我正在尝试编写一个表达式语法,其中有 3 个运算符“+”、“-”和“/”。乘法运算符通过并置隐含,如下所示:

(1+2)(3+4 5)

语法如下:

S -> A ('+' A)*

A -> B ('-' B)*

B -> C ('/' C)*

C -> D ( D )*

D ->ID
    |Num
    |'(' S ')'

我正在使用使用 ANTLR 解析器的 Xtext,它说这在规则 C 上是递归的。如果我要将规则 4 更改为

C -> D ('\*' D)*

然后消除错误。我很困惑。需要帮助!

【问题讨论】:

  • 什么是非终结符E?
  • 对不起。那是一个错字。已编辑。
  • 我不认为这是问题所在,但您的规则是多余的。例如。 S->A('+' A)* 已经允许派生单个 A,因此 S->A 是不必要的。其他所有人都一样。
  • 好的。我删除了那些。我对解析很陌生。请多多包涵。

标签: parsing grammar left-recursion


【解决方案1】:

我对Xtext一无所知,但是Antlr 4对这个语法没有问题:

grammar Expr; 
s: a ('+' a)* ;
a: b ('-' b)* ;
b: c ('/' c)* ;
c: d ( d )* ;
d: ID | NUM |'(' s ')' ;
ID: [a-z][a-z0-9]* ;
NUM: [0-9]+ ;
WS: [ \t\r\n]+ -> skip ;

当我编译并运行您的示例 (1+2)(3+4 5) 时,我得到了这个解析树:

可能是 Xtext 使用的是旧版本的 Antlr。这是一个很棒的软件,但在旧版本中,尤其是它并不完美。根据标准定义,该文法不是左递归的。 Antlr 有可能将其转换为 左递归的更简单语法,但这显然是一个已修复的错误。

因此,如果我的猜测是正确的,那么您将成功使用以下明确的“简化”语法:

grammar Expr; 
s: a ap ;
ap: '+' a ap | /* eps */ ;
a: b bp ;
bp: '-' b bp | /* eps */ ;
b: c cp ;
cp: '/' c cp | /* eps */ ;
c: d dp ;
dp: d dp | ;
d: ID | NUM |'(' s ')' ;
ID: [a-z][a-z0-9]* ;
NUM: [0-9]+ ;
WS: [ \t\r\n]+ -> skip ;

新的解析树:

【讨论】:

  • 这正是我想要生成的解析树。但是,我似乎坚持使用使用 ANTLR 3.2 的 Xtext。我只想知道如何留下这个语法。
  • 我想我必须说服我的团队切换到 ANTLR 4。未来会有很多这样的左递归。谢谢!
  • 你不能排除左递归,因为语法不是左递归的。 ANTLR 3 中一定有一个错误导致它重写为左递归的东西。最好的猜测是将 Kleene 星运算重写为语法规则。
  • @KartikSayani 谢谢。我添加了一个潜在的解决方法。我对它是否适用于您的环境感兴趣。
  • 非常感谢。 Xtext 仍然提示对规则 C 和 DP 进行左递归。我认为问题出在括号上。 C 和 DP 都调用 D 调用 '(' S ')' 并且它递归?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多