19.1.2 Problem #2: Modifiers Too Specific

Consider the two groups of productions:

FieldDeclaration:
Field
Modifiersopt Type VariableDeclarators ;
FieldModifiers:
FieldModifier
FieldModifiers FieldModifier
FieldModifier: one of
public protected private
final static transient volatile

and:

MethodHeader:
MethodModifiersopt ResultType MethodDeclarator Throwsopt
MethodModifiers:
MethodModifier
MethodModifiers MethodModifier
MethodModifier: one of
public protected private
static
abstract final native synchronized

Now consider the partial input:

class Problem2 { public static int

When the parser is considering the token static, with one-token lookahead to symbol int-or, worse yet, considering the token public with lookahead to static-it cannot yet tell whether this will be a field declaration such as:

public static int maddie = 0;

or a method declaration such as:

public static int maddie(String art) { return art.length(); }

Therefore, the parser cannot tell with only one-token lookahead whether static (or, similarly, public) should be reduced to FieldModifier or MethodModifier. Therefore, the productions shown above result in a grammar that is not LALR(1). There are also other problems with drawing distinctions among different kinds of modifiers in the grammar.

While not all contexts provoke the problem, the simplest solution is to combine all contexts in which such modifiers are used, eliminating all six of the nonterminals ClassModifiers (§8.1.2), FieldModifiers (§8.3.1), MethodModifiers (§8.4.3), ConstructorModifiers (§8.6.3), InterfaceModifiers (§9.1.2), and ConstantModifiers (§9.3) from the grammar, replacing them all with a single nonterminal Modifiers:

Modifiers:
Modifier
Modifiers
Modifier
Modifier: one of
public protected private
static
abstract final native synchronized transient volatile

A later stage of compiler analysis then sorts out the precise role of each modifier and whether it is permitted in a given context.