【问题标题】:JavaCC get ParseException error when lookahead > 0JavaCC 在前瞻 > 0 时出现 ParseException 错误
【发布时间】:2017-01-08 00:34:26
【问题描述】:

当我尝试制作一个简单的解析器时,我遇到了这个错误。解析器应该接受 (01|10|00|11)*(00|11)。当我使用前瞻 = 0 时,00100100 将触发错误,即使它是正确的输入。因为 JavaCC 将其读取为 00 1 00 1 00,而不是 00 10 01 00。但是当我添加前瞻来修复它时,我得到了

Exception in thread "main" ParseException: Encountered "" at line 1, column 6.
Was expecting one of:

    at GS.generateParseException(GS.java:453)
    at GS.jj_consume_token(GS.java:337)
    at GS.q3(GS.java:50)
    at GS.q0(GS.java:17)
    at GS.q1(GS.java:32)
    at GS.q0(GS.java:14)
    at GS.q3(GS.java:43)
    at GS.q0(GS.java:17)
    at GS.main(GS.java:8)

谁能帮我找出原因? 任何帮助将非常感激。谢谢

options{
    LOOKAHEAD = 4;
}

PARSER_BEGIN(GS)
public class GS {
    public static void main(String args[]) throws ParseException {
        GS parser = new GS(System.in);
        parser.q0();
    }
}
PARSER_END(GS)

TOKEN:
{
    <END : (["\n", "\r", "\t"])+>
}


void q0():{}
{
    "1" q1() | "0" q2() | "00" q3() | "11" q3()
}

void q1():{}
{
    "0" q0()
}

void q2():{}
{
    "1" q0()
}

void q3():{}
{
    q0() | <END>
}

【问题讨论】:

  • 我建议将 DEBUG_PARSER 设置为 true。
  • 也可能是DEBUG_TOKEN_MANGER。在我看来,它没有找到END 令牌。您确定在您输入的最后一位数字之后有一个换行符、回车符或制表符吗?
  • 显然,当给定 0011 时,解析器读取 00 并调用 q3() 后,而不是选择 q0() 然后读取 11,在 q3 上它选择 ,即使仍有输入。当仍有输入时,有什么方法可以强制解析器选择 q0()?
  • 我的错,前面的例子是错误的,因为数字后面没有换行符、回车符或制表符,并且在给出 0011“/n”时会给出正确答案。但是即使我添加了换行符或返回,当给定一个更长的字符串时它仍然有同样的问题。
  • 我建议删除问题或重写它以包含解析器失败的实际示例输入。就目前而言,这个问题没有提供任何证据表明有问题需要解决或有问题需要回答。

标签: javacc lookahead parseexception


【解决方案1】:

我认为写作

void q3():{}
{
    <END> |q0()
}

而不是

void q3():{}
{
    q0() | <END>
}

可能会解决问题:如果您内联 q3,您可以看到 q0 是左递归的,因此您需要无限前瞻来选择替代生产。将 END 放在首位将赋予它更高的优先级,并且产生式将变为右递归。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多