JavaCC lookahead选项不起作用

时间:2014-07-17 10:59:36

标签: parsing javacc lookahead

我正在使用JavaCC 6.0,因为以下选择冲突,我需要将前瞻选项设置为2:

double Func() :
{}
{
    <STRING> "(" ( (<STRING> | Expression() ) "," )*  ")"
}

存在冲突是因为Expression()可以以<STRING>开头而且我得到&#34;考虑使用2的前瞻来进行早期扩展。&#34;

所以我将前瞻选项改为了 options { LOOKAHEAD = 2; FORCE_LA_CHECK = true; ...}

但我仍然得到相同的警告,并且解析器在需要检测表达式而不是字符串时失败。

我做错了什么或者前瞻选项是不起作用的?

1 个答案:

答案 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() | ")" )
}

递归版本还具有重复次数少于迭代版本的好处。