语法中的间接递归

时间:2015-11-04 13:03:15

标签: parsing recursion compiler-construction grammar

我试图从以下语法中删除间接递归:

F -> P X
X -> R C
R -> C R | I R | epsilon

所有大写字母都是非终端的,我刚刚停止了制作,因为它们并不重要。

在此之后,您可以看到我会得到一些看起来像F - > P(C | I)* C导致我的递归下降解析器出现问题。

任何有效的表达式必须以C结尾,但最终的C总是通过重复使用R生产来消耗,不留下任何代币留给X的最终C - > R C生产。

以下面的代币表达式为例:" P C I C"

  • 我们使用F - > P X生产去除第一个P离开" C I C"
  • 然后X - > R C - > C R C所以我们可以消耗C离开" I C"
  • 然后R C - >我R C所以我们可以消耗我离开" C"

现在我们遇到了问题。一个递归的正确解析器将简单地选择像这样继续扩展R:

  • R C - > C R C所以我们消耗最后一个字符C而不留下剩余的代币!

此时,尽管输入有效,我的程序仍会出错,因为最终的R C - > C(使用epsilon生产)并且没有剩余的C匹配!

我认为我需要做的就是以某种方式巧妙地重新排列语法以消除这种模糊性。非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

您可以将P (C | I)* C重写为P I* C+ (I+ C+)*,这可以直接实现为递归下降解析器。如果你把它写成右递归的BNF语法,你最终会得到不正确的关联性,但通常你会用循环编写递归下降解析器,使用如上所述的扩展BNF。 [注1]

实际上,一旦你解析了P,就会得到类似的结果:

do {
  while (try_parse(I)) {}
  parse(C);
  while (try_parse(C)) {}
} while (try_parse(I));

注释

  1. 或者,至少,我会,如果我再写下递归下降解析器了。这作为左递归语法和它的LALR(1)更直接,所以你可以生成一个带有野牛的解析器。