我正在使用JavaCC 6.0,因为以下选择冲突,我需要将前瞻选项设置为2:
double Func() :
{}
{
<STRING> "(" ( (<STRING> | Expression() ) "," )* ")"
}
存在冲突是因为Expression()
可以以<STRING>
开头而且我得到&#34;考虑使用2的前瞻来进行早期扩展。&#34;
所以我将前瞻选项改为了
options {
LOOKAHEAD = 2;
FORCE_LA_CHECK = true;
...}
但我仍然得到相同的警告,并且解析器在需要检测表达式而不是字符串时失败。
我做错了什么或者前瞻选项是不起作用的?
答案 0 :(得分:3)
我从不使用LOOKAHEAD的全局设置而不是1.相反,我会在需要的地方使用本地预测。在你的情况下,我会做以下
double Func() :
{}
{
<STRING>
"("
(
( LOOKAHEAD( <STRING> "," )
<STRING>
| Expression()
)
","
)*
")"
}
在最后一个参数之后你需要一个逗号是相当奇怪的。如果你不想要,你可以这样做
double Func() :
{}
{
<STRING>
"("
(
( LOOKAHEAD( <STRING> ("," | ")") ) <STRING> | Expression() )
( ","
( LOOKAHEAD( <STRING> ("," | ")") ) <STRING> | Expression() )
)*
)?
")"
}
但是,在上面的两个片段中,这些前瞻性规范违反了FAQ 4.8中的建议,即语法前瞻规范扫描的令牌应该全部由选择使用。如果您在预见规范中使用func()
本身,则可能会出现问题。对于第一种语法,这很容易处理:像这样分发逗号
double Func() :
{}
{
<STRING>
"("
(
( LOOKAHEAD(<STRING> "," )
<STRING> ","
| Expression() ","
)
)*
")"
}
对于第二种语法(在最后一个参数之后没有逗号的语法),您可以使用这样的递归:
double Func() :
{}
{
<STRING> "(" ( ")" | Args() )
}
void Args() :
{}
LOOKAHEAD(<STRING> ("," | ")" )
<STRING>
("," Args() | ")" )
|
Expression()
("," Args() | ")" )
}
递归版本还具有重复次数少于迭代版本的好处。