Primary expressions include most of the simplest kinds of expressions, from which all others are constructed: literals, field accesses, method invocations, and array accesses. A parenthesized expression is also treated syntactically as a primary expression.
Primary:
PrimaryNoNewArray
ArrayCreationExpression PrimaryNoNewArray:
Literal
this
(
Expression)
ClassInstanceCreationExpression
FieldAccess
MethodInvocation
ArrayAccess
As programming language grammars go, this part of the Java grammar is unusual, in two ways. First, one might expect simple names, such as names of local variables and method parameters, to be primary expressions. For technical reasons, names are lumped together with primary expressions a little later when postfix expressions are introduced (§15.13).
The technical reasons have to do with allowing left-to-right parsing of Java programs with only one-token lookahead. Consider the expressions (z[3])
and (z[])
. The first is a parenthesized array access (§15.12) and the second is the start of a cast (§15.15). At the point that the look-ahead symbol is [
, a left-to-right parse will have reduced the z
to the nonterminal Name. In the context of a cast we prefer not to have to reduce the name to a Primary, but if Name were one of the alternatives for Primary, then we could not tell whether to do the reduction (that is, we could not determine whether the current situation would turn out to be a parenthesized array access or a cast) without looking ahead two tokens, to the token following the [
. The Java grammar presented here avoids the problem by keeping Name and Primary separate and allowing either in certain other syntax rules (those for MethodInvocation, ArrayAccess, PostfixExpression, but not for FieldAccess, because this is covered by Name). This strategy effectively defers the question of whether a Name should be treated as a Primary until more context can be examined. (Other problems remain with cast expressions; see §19.1.5.)
The second unusual feature avoids a potential grammatical ambiguity in the expression:
new int[3][3]
which in Java always means a single creation of a multidimensional array, but which, without appropriate grammatical finesse, might also be interpreted as meaning the same as:
(new int[3])[3]
This ambiguity is eliminated by splitting the expected definition of Primary into
Primary and PrimaryNoNewArray. (This may be compared to the splitting of
Statement into Statement and StatementNoShortIf (§14.4) to avoid the "dangling
else
" problem.)