在嵌套条件下使用 LOOKAHEAD

Using LOOKAHEAD in nested conditions

我正在维护使用 JavaCC 来解析语法的旧代码。

我的 .jjt 文件大致如下所示:

void Top() {}
{
    Bazz() OpenParenthesis() Foo() CloseParenthesis()
}
void Foo() {}
{
    Bar() Blah() A()
}

void A() {}
{
    Z() (B() Z())*
}
void Z() {}
{
    (OpenParenthesis())? X() Y() (CloseParenthesis())?
}

图例:

我的问题是 "simple" 输入如下:

bazz ( bar blah x y )

...右括号作为 Z 条件(0 or 1? 量词)的一部分使用,因此 [=13= 中的强制性右括号] 会产生语法错误,其中解析器会期望 B<EOF>.

JavaCC 正则表达式不像 Java 正则表达式那样具有细粒度量词,因此我不能在 Z 的右括号中使用不情愿的量词。

我已经阅读了 LOOKAHEAD 结构(一些 tutorial/docs here)并且认为我可以使用一个来推断结束右括号是否不应该被 [=21 使用=],因此将 Z 重写为:

void Z() {}
{
    (OpenParenthesis())? X() Y() (LOOKAHEAD(1) CloseParenthesis())?
}

我还研究过前瞻的大小。

不幸的是,要么我不了解该功能,要么前瞻功能不适用于如上图所示的分层语法。

到目前为止,我发现的一些糟糕的解决方法包括:

显然两者都不让我满意。

我是不是忽略了什么?

也许我没有理解您代码的意图,但是规则

void Z() {}
{
    (OpenParenthesis())? X() Y() (CloseParenthesis())?
}

我觉得很奇怪。您真的希望以下所有序列都可以解析为 Z 吗?

( x y )
x y
( x y
x y )

如果您认为最后两个不应该被解析为Z,那么将规则更改为

void Z() {}
{
    OpenParenthesis() X() Y() CloseParenthesis()
|
    X() Y()
}

如果你真的真的真的希望 Z 成为现在的样子,请发表评论,我会提交一个可行的解决方案,至少对于上面的例子是这样