The Java 7 syntax specification specifies a QualifiedIdentifier
that consists of:
QualifiedIdentifier:
Identifier { . Identifier }
In later parts of the grammar though, this construct occurs again instead of the qualified identifier:
ImportDeclaration:
import [static] Identifier { . Identifier } [. *] ;
Primary:
Identifier { . Identifier } [IdentifierSuffix]
Why are these parts explicitly listed like this? Can't they simply be reduced to:
ImportDeclaration:
import [static] QualifiedIdentifier [. *] ;
Primary:
QualifiedIdentifier [IdentifierSuffix]
First, understand that the grammar you reference (JLS 7 Chapter 18) isn't actually "The Java 7 syntax specification" (e.g. The One True Grammar). It is a grammar that describes the Java 7 syntax. There are others, including the one in preceding chapters of the same JLS document. The JLS itself clarifies this in section 2.3, The Syntactic Grammar:
A syntactic grammar for the Java programming language is given in Chapters 4, 6-10, 14, and 15. This grammar has tokens defined by the lexical grammar as its terminal symbols. It defines a set of productions, starting from the goal symbol CompilationUnit (§7.3), that describe how sequences of tokens can form syntactically correct programs.
Chapter 18 also gives a syntactic grammar for the Java programming language, better suited to implementation than exposition. The same language is accepted by both syntactic grammars.
And the introduction to Chapter 18 explains that the grammar presented therein is specifically for use in the reference implementation:
The grammar presented piecemeal in the preceding chapters (§2.3) is much better for exposition, but it is not well suited as a basis for a parser. The grammar presented in this chapter is the basis for the reference implementation.
So there isn't a single canonical Java grammar. There is only the language syntax itself, which can be represented in multiple grammars.
OP asks whether
ImportDeclaration:
import [static] QualifiedIdentifier [. *] ;
Primary:
QualifiedIdentifier [IdentifierSuffix]
would be ok. Yes, sure, why not? It describes the same language, so it must be ok.
Recall that the purpose of the Chapter 18 grammar is to serve as the basis for a reference implementation. If you look closely, you'll see that QualifiedIdentifier
is used consistently where it fully describes the "Identifier-like construct" (my invented term) that it represents, but not where it would just be part of a larger "Identifier-like construct".
Looking at ImportDeclaration
, it is clear that the optional trailing .*
is part of the identifier of the thing(s) being imported. In an import like import java.util.*;
, the java.util
part, while dot separated, isn't really a Qualified Identifier. The identifier-like construct that represents the thing(s) being imported is the entire phrase java.util.*
. So thinking about it as a QualifiedIdentifier
plus optional .*
kind of clouds the mind.
A similar argument can be used for Primary
.
Further, use of QualifiedIdentifier
in an Import
or Primary
may make the parser more complicated. (I'd appreciate hearing from real language designers on this one.) In other words, since the Chapter 18 grammar is presented as being better suited for implementation, I have to think that this choice was deliberate and makes implementation easier.
Sure, the proposed use of QualifiedIdentifier
given above describes the same language in a strictly mechanical sense. But there are semantic reasons for preferring the grammar as written, and there may well be implementation reasons as well.