Search code examples
javacc

Transform grammar to avoid common prefixes


I have this grammar with common prefixes (<id>) and I want to transform it to avoid them.

void Components() : {}
{
    (Read() | Write())* (<id>Assignment())* <id>Declaration() (Read() | Write() | <id>(Assignment() | Declaration()))*
}

The problem is (<id>Assignment())* <id>Declaration(). The grammar can have 0 or more Assignments/Read/Write statments but at least 1 Declaration and then any statment/declaration in any order.


Solution

  • Refactoring this is easy, but I probably wouldn't do it. I'd probably look ahead a little further. Here are two solutions


    Factor out the <id>

    void Components() : {}
    {
        (Read() | Write())*
        <id>
        (Assignment() <id>)*
        Declaration()
        ( Read()
        | Write()
        | <id> (Assignment() | Declaration())
        )*
    }
    

    Use longer lookahead

    void Components() : {}
    {
        (Read() | Write())*
        (LOOKAHEAD( 2 ) <id> Assignment())*
        <id> Declaration()
        ( Read()
        | Write()
        | LOOKAHEAD( 2 ) <id> Assignment()
        | <id> Declaration())
        )*
    }