java - JavaCC 中的左递归(直接和间接)消除

标签 java parsing recursion grammar javacc

我在消除 JavaCC 中的左递归时遇到问题。我找到了一个解决方案 Epsilon tokens ,但 JavaCC 似乎无法与 Epsilon token 很好地配合(如 TOKEN : <eps : ""> )。下面我准备了一个我的问题的示例:

void prod1() : 
{}
{
    <beta1>
    | prod2() <alpha1>
}

void prod2() : 
{}
{
    <beta2>
    | [prod2()] <alpha2>
    | prod1() <alpha3>
}

这里我们看到直接左递归和非直接左递归。这是我的真实语法的简化示例(我的JavaCC语法是基于现有的BNF语法,因此我被迫以这种形式使用它)。

最佳答案

我找到了一个解决方案,它似乎适合我。

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_()]
}

关于java - JavaCC 中的左递归(直接和间接)消除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42834736/

相关文章:

java - Canoo WebFunctionalTest/Selenium,功能比较

java - 安卓 native : How to deallocate object after returning from native layer

json - 解析内容丰富的 Webhook(自定义 JSON 类型)

javascript parseInt 从字符串中删除空格

c - 更好的做法是 strcpy() 或指向另一个数据结构?

typescript - 确保对象列表在编译时在 TypeScript 中具有唯一的键

java - 在Java中递归打印字符串的反向

java - Jackson XML 反序列化 - 保存无法识别的字段

java - 在spring data jpa中获取非表实体的数据

c++ - 似乎很难找出这个简单程序的时间复杂度