我的大脑正在努力消除生产规则中的一些左递归。 我正在使用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()更左递归!!
我不知道从哪里去,已经失去了很多头发。任何见解都将不胜感激!
答案 0 :(得分:1)
我建议重写expression
的规则,如下所示:
expression := ( identifier | number | ( + | - ) fragment ) ( ( + | - | * | / ) fragment )*
实际上,这只是原始定义中fragment
的替换,Kleene算子可以方便地吸收一些术语。
当然,如果它应该反映原始规则,那么无论从解析中创建什么结构都需要适应它。