Java 7 语法中的分隔标识符可以简化为限定标识符吗?

Can separated identifiers in the Java 7 grammar be reduced to qualified identifiers?

Java 7 syntax specification 指定一个 QualifiedIdentifier,其中包含:

QualifiedIdentifier:
    Identifier { . Identifier }

虽然在语法的后面部分,这个结构再次出现而不是限定标识符:

ImportDeclaration: 
    import [static] Identifier { . Identifier } [. *] ;
Primary:
    Identifier { . Identifier } [IdentifierSuffix]

为什么要这样明确列出这些部分?不能简单地简化为:

ImportDeclaration: 
    import [static] QualifiedIdentifier [. *] ;
Primary:
    QualifiedIdentifier [IdentifierSuffix]

唯一正确的语法

首先,请了解您引用的语法(JLS 7 第 18 章)实际上并不是 "The Java 7 syntax specification"(例如唯一正确的语法)。它是描述 Java 7 语法的 语法 。还有其他的,包括同一 JLS 文档前几章中的那个。 JLS 本身在 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.

并且Chapter 18的介绍解释了其中介绍的语法专门用于参考实现:

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.

所以没有单一规范Java语法。只有语言语法本身,可以用多种语法来表示。

建议的替代方案是否可以接受?

OP 询问是否

ImportDeclaration: 
    import [static] QualifiedIdentifier [. *] ;
Primary:
    QualifiedIdentifier [IdentifierSuffix]

没问题。是的,当然,为什么不呢?描述的是同一种语言,肯定没问题。

那么他们为什么要这样做呢?

回想一下,第 18 章语法的目的是作为参考实现的基础。如果你仔细观察,你会发现 QualifiedIdentifier 在完全描述它所代表的 "Identifier-like construct"(我发明的术语)的地方一直被使用,而不是在它只是更大的 [=] 的一部分的地方67=].

查看 ImportDeclaration,很明显可选的尾随 .* 是所导入事物的标识符 的一部分。在像 import java.util.*; 这样的导入中,java.util 部分虽然以点分隔,但并不是真正的限定标识符。表示正在导入的事物的类似标识符的结构是整个短语 java.util.*。所以 认为 将其作为 QualifiedIdentifier 加上可选的 .* 有点让人头疼。

类似的论点可用于 Primary

此外,在 ImportPrimary 中使用 QualifiedIdentifier 可能 会使解析器更加复杂。 (我很高兴听到真正的语言设计者对这个问题的看法。)换句话说,由于第 18 章的语法更适合实现,我不得不认为这个选择是经过深思熟虑的,并且使实现更容易。

底线

当然,上面给出的 QualifiedIdentifier 的建议用法在严格机械意义上描述了相同的语言。但是更喜欢书面语法有语义上的原因,也可能有实现上的原因。