消除间接左递归

时间:2012-12-12 19:08:46

标签: compiler-construction grammar context-free-grammar javacc

我的大脑正在努力消除生产规则中的一些左递归。 我正在使用JavaCC构建编译器,我需要使用以下2个生产规则:

expression := fragment ( ( + | - | * | / )  fragment )*

fragment := identifier | number | ( + | - ) fragment | expression

但问题是片段与片段有关,与片段有关,即:间接左递归。

我环顾互联网,每个人似乎都使用这个算法here。该网站没有解释直接左递归消除,您可以找到here

我最终得到这样的规则:

void expression(): {}
{
  fragment()
  (
    (< PLUS >|< MINUS >|< DIVIDE >|< ASTERISKS >)
    fragment()
  )*
}

void k(): {}
{
  (
    ((< PLUS >|< MINUS >|< DIVIDE >|< ASTERISKS >)fragment())*k()
  | fragment()
  )
} 

void fragment(): {}
{
  (
    < ID >k()
  | number()k()
  | (< PLUS >|< MINUS >)fragment()k()
)
}

它们是用JavaCC编写的代码编写的,所以希望你能理解它们。基本上我引入了一个规则K来处理递归,除了问题仍然存在,因为K的第一部分可以减少为空,因为它是*(0次或更多次),它留给你K - &gt; k()更左递归!!

我不知道从哪里去,已经失去了很多头发。任何见解都将不胜感激!

1 个答案:

答案 0 :(得分:1)

我建议重写expression的规则,如下所示:

expression := ( identifier | number | ( + | - ) fragment ) ( ( + | - | * | / ) fragment )*

实际上,这只是原始定义中fragment的替换,Kleene算子可以方便地吸收一些术语。

当然,如果它应该反映原始规则,那么无论从解析中创建什么结构都需要适应它。