Search code examples
javacc

Javacc grammar not working with optional tokens


I have a DFM (is a Delphi source file, like JSON, to define form component layouts) parser created with javaCC.

My grammar (.jj file) define this:

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; }
}

This is for parsing 2 types of object definitions:

object name: Type 
end

as so

object Type
end

So, the name : is optional.

But, when I try to parse this second DFM, I always get this error:

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

Was expecting:

":" ...

What I'm doing wrong?


Solution

  • A solution/workaround is, to make optional the : Type part and switch between the name and type values when the type == null.

    See the grammar implementation:

    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; 
        }
    }