I'm using JavaCC to make a specification to recognize a language. The problem I have is that JavaCC gives me a warning because public is a common prefix of Member() declaration. Member() can has Attributes() and/or Method() but must have at least one Method, the order does not matter.
The warning JavaCC gives me is:
Choice conflict in (...)+ construct at line 66, column 23. Expansion nested within construct and expansion following construct have common prefixes, one of which is: "public". Consider using a lookahead of 2 or more for nested expansion.
The line 66 is the only line of Member(). Also I need to do this without change lookahead value.
Here is the code:
void Member() : {}
{
(Attribute())* (Method())+ (Attribute() | Method())*
}
void Attribute() : {}
{
"private" Type() <Id> [":=" Expr()]";"
}
void Method() : {}
{
MethodHead() MethodBody()
}
void MethodHead() : {}
{
("public")? (<Id> | Type() | "void") <Id> "(" Parameter() ")"
}
Thanks.
The problem is that this regular expression
is ambiguous. Let's abbreviate methods by M and attributes by A. If the input is MAM, there no problem. The
(Method())+
matches the first M and the(Attribute() | Method())*
matches the remaining AM. But if the input is MMA, where should the divide be? Either(Method())+
matches M and(Attribute() | Method())*
matches MA or(Method())+
matches MM and(Attribute() | Method())*
matches A. Both parses are possible. JavaCC doesn't know which parse you want, so it complains.What you can do:
(Method())+
and only methods after the first attribute will be recognized by(Attribute() | Method())*
.(Method())+
to(LOOKAHEAD(1) Method())+
. That won't change the behaviour of the parser, but it will suppress the warning.The offending line could be rewritten as either
or as