我在消除JavaCC中的左递归时遇到问题。我找到了Epsilon tokens的解决方案,但似乎JavaCC无法与Epsilon令牌(如TOKEN : <eps : "">
)很好地协作。下面我准备一个我的问题的例子:
void prod1() :
{}
{
<beta1>
| prod2() <alpha1>
}
void prod2() :
{}
{
<beta2>
| [prod2()] <alpha2>
| prod1() <alpha3>
}
这里我们看到直接和非直接左递归。它是我真正语法的简化示例(我的JavaCC语法基于现有的BNF语法,因此我不得不以这种形式使用它。)
答案 0 :(得分:1)
我找到了一个解决方案,它似乎适合我。
void prod1() :
{}
{
<beta1>
| prod2() <alpha1>
}
void prod2() :
{}
{
<beta2>
| [prod2()] <alpha2> // (1)
| prod1() <alpha3>
}
步骤1.展开(1)
void prod1() :
{}
{
<beta1>
| prod2() <alpha1>
}
void prod2() :
{}
{
<beta2>
| <alpha2>
| prod2() <alpha2>
| prod1() <alpha3>
}
步骤2.将prod1插入prod2
内void prod1() :
{}
{
<beta1>
| prod2() <alpha1>
}
void prod2() :
{}
{
<beta2>
| <alpha2>
| prod2() <alpha2>
| <beta1> <alpha3>
| prod2() <alpha1> <alpha3>
}
步骤3.使用epsilon产生消除prod2中的左递归(在此处描述https://en.wikipedia.org/wiki/Left_recursion)
void prod1() :
{}
{
<beta1>
| prod2() <alpha1>
}
void prod2() :
{}
{
<beta2> prod2_()
| <alpha2> prod2_()
| <beta1> <alpha3> prod2_()
}
void prod2_() :
{}
{
prod2() <alpha2> prod2_()
| prod2() <alpha1> <alpha3> prod2_()
| <epsilon>
}
步骤4.从prod2_()中消除epsilon产生(此处描述http://www.d.umn.edu/~hudson/5641/l11m.pdf)
void prod1() :
{}
{
<beta1>
| prod2() <alpha1>
}
void prod2() :
{}
{
<beta2> [prod2_()]
| <alpha2> [prod2_()]
| <beta1> <alpha3> [prod2_()]
}
void prod2_() :
{}
{
prod2() <alpha2> [prod2_()]
| prod2() <alpha1> <alpha3> [prod2_()]
}
答案 1 :(得分:0)
prod1 --> beta1 | prod2 alpha1
prod2 --> beta2 | [prod2] alpha2 | prod1 alpha3
展开选项
prod1 --> beta1 | prod2 alpha1
prod2 --> beta2 | alpha2 | prod2 alpha2 | prod1 alpha3
替换prod2中的prod1
prod1 --> beta1 | prod2 alpha1
prod2 --> beta2 | alpha2 | prod2 alpha2 | (beta1 | prod2 alpha1) alpha3
分发
prod1 --> beta1 | prod2 alpha1
prod2 --> beta2 | alpha2 | prod2 alpha2 | beta1 alpha3 | prod2 alpha1 alpha3
重新排列和因子
prod1 --> beta1 | prod2 alpha1
prod2 --> (beta2 | alpha2 | beta1 alpha3) | prod2 (alpha2 | alpha1 alpha3)
消除左递归
prod1 --> beta1 | prod2 alpha1
prod2 --> (beta2 | alpha2 | beta1 alpha3) (alpha2 | alpha1 alpha3)*