Javacc 语法不适用于可选标记

Javacc grammar not working with optional tokens

我有一个 DFM(是一个 Delphi 源文件,如 JSON,用于定义表单组件布局)用 javaCC 创建的解析器。

我的语法(.jj 文件)定义如下:

private DfmObject dfmObject():
{
    DfmObject res = new DfmObject();
    DfmProperty prop;
    DfmObject obj;
    Token tName;
    Token tType;
}
{
    <OBJECT>
    (tName = <IDENTIFIER>  { res.setName(tName.image); } <COLON>)?
    tType = <IDENTIFIER>  { res.setType(tType.image); } 
    <ENDLINE> 
    ( prop = property()    { res.addProperty(prop); } )*
    ( obj = dfmObject()   { res.addChild(obj);     } (<ENDLINE>)*)*
    <END>
    { return res; }
}

这用于解析 2 种类型的 object 定义:

object name: Type 
end

如此

object Type
end

因此,name : 是可选的。

但是,当我尝试解析第二个 DFM 时,我总是得到这个错误:

Exception in thread "main" eu.kaszkowiak.jdfm.parser.ParseException: Encountered " <ENDLINE> "\r\n"" at line 1, column 12.

Was expecting:

":" ...

我做错了什么?

A solution/workaround 是,使 : Type 部分可选,并在 type == null.[=15 时在 nametype 值之间切换=]

查看语法实现:

private DfmObject dfmObject():
{
    DfmObject res = new DfmObject();
    DfmProperty prop;
    DfmObject obj;
    Token tName;
    Token tType;
}
{
    (
        <OBJECT>
        (
            tName = <IDENTIFIER>  { res.setName(tName.image); } 
        )
        ( <COLON> tType = <IDENTIFIER>  { res.setType(tType.image); } )?
        <ENDLINE>
    )
    ( prop = property()    { res.addProperty(prop); } )*
    ( obj = dfmObject()   { res.addChild(obj);     } (<ENDLINE>)*)*
    <END>
    {
        if (res.getType() == null) {
            res.setType(res.getName());
            res.setName(null);
        } 
        return res; 
    }
}