CHAPTER 19
The grammar for Java presented piecemeal in the preceding chapters is much better for exposition, but it cannot be parsed left-to-right with one token of lookahead because of certain syntactic peculiarities, some of them inherited from C and C++. These problems and the solutions adopted for the LALR(1) grammar are presented below, followed by the grammar itself.
PackageName:and:
Identifier
PackageName.Identifier TypeName:
Identifier
PackageName.Identifier
MethodName:Now consider the partial input:
Identifier
AmbiguousName.Identifier AmbiguousName:
Identifier
AmbiguousName.Identifier
class Problem1 { int m() { hayden.
When the parser is considering the token hayden, with one-token lookahead to
symbol ".", it cannot yet tell whether hayden should be a PackageName that
qualifies a type name, as in:
hayden.Dinosaur rex = new hayden.Dinosaur(2);or an AmbiguousName that qualifies a method name, as in:
hayden.print("Dinosaur Rex!");
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
names in the grammar.
The solution is to eliminate the nonterminals PackageName, TypeName, ExpressionName, MethodName, and AmbiguousName, replacing them all with a single nonterminal Name:
Name:A later stage of compiler analysis then sorts out the precise role of each name or name qualifier.
SimpleName
QualifiedName SimpleName:
Identifier QualifiedName:
Name.Identifier
For related reasons, these productions in §4.3:
ClassOrInterfaceType:were changed to:
ClassType
InterfaceType ClassType:
TypeName InterfaceType:
TypeName
ClassOrInterfaceType:
Name ClassType:
ClassOrInterfaceType InterfaceType:
ClassOrInterfaceType
FieldDeclaration:and:
FieldModifiersoptTypeVariableDeclarators;FieldModifiers:
FieldModifier
FieldModifiersFieldModifier FieldModifier: one of
publicprotectedprivate
final static transient volatile
MethodHeader:Now consider the partial input:
MethodModifiersoptResultTypeMethodDeclaratorThrowsopt MethodModifiers:
MethodModifier
MethodModifiersMethodModifier MethodModifier: one of
publicprotectedprivate
static
abstract final native synchronized
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:A later stage of compiler analysis then sorts out the precise role of each modifier and whether it is permitted in a given context.
Modifier
ModifiersModifier Modifier: one of
public protected private
static
abstract final native synchronized transient volatile
FieldDeclaration:and:
ModifiersoptTypeVariableDeclarators;
MethodHeader:where ResultType is defined as:
ModifiersoptResultTypeMethodDeclaratorThrowsopt
ResultType:Now consider the partial input:
Type
void
class Problem3 { int julie
Note that, in this simple example, no Modifiers are present. When the parser is
considering the token int, with one-token lookahead to symbol julie, it cannot
yet tell whether this will be a field declaration such as:
int julie = 14;or a method declaration such as:
int julie(String art) { return art.length(); }
Therefore, after the parser reduces int to the nonterminal Type, it cannot tell with
only one-token lookahead whether Type should be further reduced to ResultType
(for a method declaration) or left alone (for a field declaration). Therefore, the
productions shown above result in a grammar that is not LALR(1).
The solution is to eliminate the ResultType production and to have separate alternatives for MethodHeader:
MethodHeader:This allows the parser to reduce
ModifiersoptTypeMethodDeclaratorThrowsopt
ModifiersoptvoidMethodDeclaratorThrowsopt
int to Type and then leave it as is, delaying the decision as to whether a field declaration or method declaration is in progress.ArrayType:and:
Type[ ]
ArrayAccess:Now consider the partial input:
Name[Expression]PrimaryNoNewArray
[Expression]
class Problem4 { Problem4() { peter[
When the parser is considering the token peter, with one-token lookahead to
symbol [, it cannot yet tell whether peter will be part of a type name, as in:
peter[] team;or part of an array access, as in:
peter[3] = 12;Therefore, after the parser reduces
peter to the nonterminal Name, it cannot tell
with only one-token lookahead whether Name should be reduced ultimately to
Type (for an array type) or left alone (for an array access). Therefore, the productions shown above result in a grammar that is not LALR(1).
The solution is to have separate alternatives for ArrayType:
ArrayType:This allows the parser to reduce
PrimitiveType[ ]Name
[ ]ArrayType
[ ]
peter to Name and then leave it as is, delaying
the decision as to whether an array type or array access is in progress.
CastExpression:Now consider the partial input:
(PrimitiveType)UnaryExpression
(ReferenceType)UnaryExpressionNotPlusMinus
class Problem5 { Problem5() { super((matthew)
When the parser is considering the token matthew, with one-token lookahead to
symbol ), it cannot yet tell whether (matthew) will be a parenthesized expression, as in:
super((matthew), 9);or a cast, as in:
super((matthew)baz, 9);Therefore, after the parser reduces
matthew to the nonterminal Name, it cannot
tell with only one-token lookahead whether Name should be further reduced to
PostfixExpression and ultimately to Expression (for a parenthesized expression) or
to ClassOrInterfaceType and then to ReferenceType (for a cast). Therefore, the
productions shown above result in a grammar that is not LALR(1).
The solution is to eliminate the use of the nonterminal ReferenceType in the definition of CastExpression, which requires some reworking of both alternatives to avoid other ambiguities:
CastExpression:This allows the parser to reduce
(PrimitiveTypeDimsopt)UnaryExpression
(Expression)UnaryExpressionNotPlusMinus
(NameDims)UnaryExpressionNotPlusMinus
matthew to Expression and then leave it there,
delaying the decision as to whether a parenthesized expression or a cast is in
progress. Inappropriate variants such as:
(int[])+3and:
(matthew+1)bazmust then be weeded out and rejected by a later stage of compiler analysis.
The remaining sections of this chapter constitute a LALR(1) grammar for Java syntax, in which the five problems described above have been solved.
Goal:
CompilationUnit
Literal:
IntegerLiteral
FloatingPointLiteral
BooleanLiteral
CharacterLiteral
StringLiteral
NullLiteral
Type:
PrimitiveType
ReferenceType PrimitiveType:
NumericType
booleanNumericType:
IntegralType
FloatingPointType IntegralType: one of
byte short int long charFloatingPointType: one of
float doubleReferenceType:
ClassOrInterfaceType
ArrayType ClassOrInterfaceType:
Name ClassType:
ClassOrInterfaceType InterfaceType:
ClassOrInterfaceType ArrayType:
PrimitiveType[ ]Name
[ ]ArrayType
[ ]
Name:
SimpleName
QualifiedName SimpleName:
Identifier QualifiedName:
Name.Identifier
CompilationUnit:
PackageDeclarationoptImportDeclarationsoptTypeDeclarationsopt ImportDeclarations:
ImportDeclaration
ImportDeclarationsImportDeclaration TypeDeclarations:
TypeDeclaration
TypeDeclarationsTypeDeclaration PackageDeclaration:
packageName;ImportDeclaration:
SingleTypeImportDeclaration
TypeImportOnDemandDeclaration SingleTypeImportDeclaration:
importName;TypeImportOnDemandDeclaration:
importName. * ;TypeDeclaration:
ClassDeclaration
InterfaceDeclaration
;
Modifiers:
Modifier
ModifiersModifier Modifier: one of
public protected private
static
abstract final native synchronized transient volatile
ClassDeclaration:
ModifiersoptclassIdentifierSuperoptInterfacesoptClassBody Super:
extendsClassType Interfaces:
implementsInterfaceTypeList InterfaceTypeList:
InterfaceType
InterfaceTypeList,InterfaceType ClassBody:
{ClassBodyDeclarationsopt}ClassBodyDeclarations:
ClassBodyDeclaration
ClassBodyDeclarationsClassBodyDeclaration ClassBodyDeclaration:
ClassMemberDeclaration
StaticInitializer
ConstructorDeclaration ClassMemberDeclaration:
FieldDeclaration
MethodDeclaration
FieldDeclaration:
ModifiersoptTypeVariableDeclarators;VariableDeclarators:
VariableDeclarator
VariableDeclarators,VariableDeclarator VariableDeclarator:
VariableDeclaratorId
VariableDeclaratorId=VariableInitializer VariableDeclaratorId:
Identifier
VariableDeclaratorId[ ]VariableInitializer:
Expression
ArrayInitializer
MethodDeclaration:
MethodHeaderMethodBody MethodHeader:
ModifiersoptTypeMethodDeclaratorThrowsopt
ModifiersoptvoidMethodDeclaratorThrowsopt MethodDeclarator:
Identifier(FormalParameterListopt)MethodDeclarator
[ ]FormalParameterList:
FormalParameter
FormalParameterList,FormalParameter FormalParameter:
TypeVariableDeclaratorId Throws:
throwsClassTypeList ClassTypeList:
ClassType
ClassTypeList,ClassType MethodBody:
Block
;
StaticInitializer:
staticBlock
ConstructorDeclaration:
ModifiersoptConstructorDeclaratorThrowsoptConstructorBody ConstructorDeclarator:
SimpleName(FormalParameterListopt)ConstructorBody:
{ExplicitConstructorInvocationoptBlockStatementsopt}ExplicitConstructorInvocation:
this (ArgumentListopt) ;
super (ArgumentListopt) ;
InterfaceDeclaration:
ModifiersoptinterfaceIdentifierExtendsInterfacesoptInterfaceBody ExtendsInterfaces:
extendsInterfaceType
ExtendsInterfaces,InterfaceType InterfaceBody:
{InterfaceMemberDeclarationsopt}InterfaceMemberDeclarations:
InterfaceMemberDeclaration
InterfaceMemberDeclarationsInterfaceMemberDeclaration InterfaceMemberDeclaration:
ConstantDeclaration
AbstractMethodDeclaration ConstantDeclaration:
FieldDeclaration AbstractMethodDeclaration:
MethodHeader;
ArrayInitializer:
{VariableInitializersopt,opt}VariableInitializers:
VariableInitializer
VariableInitializers,VariableInitializer
Block:
{BlockStatementsopt}BlockStatements:
BlockStatement
BlockStatementsBlockStatement BlockStatement:
LocalVariableDeclarationStatement
Statement LocalVariableDeclarationStatement:
LocalVariableDeclaration;LocalVariableDeclaration:
TypeVariableDeclarators Statement:
StatementWithoutTrailingSubstatement
LabeledStatement
IfThenStatement
IfThenElseStatement
WhileStatement
ForStatement StatementNoShortIf:
StatementWithoutTrailingSubstatement
LabeledStatementNoShortIf
IfThenElseStatementNoShortIf
WhileStatementNoShortIf
ForStatementNoShortIf StatementWithoutTrailingSubstatement:
Block
EmptyStatement
ExpressionStatement
SwitchStatement
DoStatement
BreakStatement
ContinueStatement
ReturnStatement
SynchronizedStatement
ThrowStatement
TryStatement EmptyStatement:
;LabeledStatement:
Identifier:Statement LabeledStatementNoShortIf:
Identifier:StatementNoShortIf ExpressionStatement:
StatementExpression;StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
IfThenStatement:
if (Expression)Statement IfThenElseStatement:
if (Expression)StatementNoShortIfelseStatement IfThenElseStatementNoShortIf:
if (Expression)StatementNoShortIfelseStatementNoShortIf SwitchStatement:
switch (Expression)SwitchBlock SwitchBlock:
{SwitchBlockStatementGroupsoptSwitchLabelsopt}SwitchBlockStatementGroups:
SwitchBlockStatementGroup
SwitchBlockStatementGroupsSwitchBlockStatementGroup SwitchBlockStatementGroup:
SwitchLabelsBlockStatements SwitchLabels:
SwitchLabel
SwitchLabelsSwitchLabel SwitchLabel:
caseConstantExpression:WhileStatement:
default :
while (Expression)Statement WhileStatementNoShortIf:
while (Expression)StatementNoShortIf DoStatement:
doStatementwhile (Expression) ;
ForStatement:
for (ForInitopt;Expressionopt;ForUpdateopt)Statement ForStatementNoShortIf:
for (ForInitopt;Expressionopt;ForUpdateopt)StatementNoShortIf ForInit:
StatementExpressionList
LocalVariableDeclaration ForUpdate:
StatementExpressionList StatementExpressionList:
StatementExpression
StatementExpressionList,StatementExpression BreakStatement:
breakIdentifieropt;ContinueStatement:
continue Identifieropt;ReturnStatement:
returnExpressionopt;ThrowStatement:
throwExpression;SynchronizedStatement:
synchronized (Expression)Block TryStatement:
tryBlockCatches
tryBlockCatchesoptFinally Catches:
CatchClause
CatchesCatchClause CatchClause:
catch (FormalParameter)Block Finally:
finallyBlock
Primary:
PrimaryNoNewArray
ArrayCreationExpression PrimaryNoNewArray:
Literal
this
(Expression)ClassInstanceCreationExpression
FieldAccess
MethodInvocation
ArrayAccess ClassInstanceCreationExpression:
newClassType(ArgumentListopt)ArgumentList:
Expression
ArgumentList,Expression ArrayCreationExpression:
newPrimitiveTypeDimExprsDimsopt
newClassOrInterfaceTypeDimExprsDimsopt DimExprs:
DimExpr
DimExprsDimExpr DimExpr:
[Expression]Dims:
[ ]Dims
[ ]FieldAccess:
Primary.Identifier
super .Identifier MethodInvocation:
Name(ArgumentListopt)Primary
.Identifier(ArgumentListopt)Identifier
super .(ArgumentListopt)ArrayAccess:
Name[Expression]PrimaryNoNewArray
[Expression]PostfixExpression:
Primary
Name
PostIncrementExpression
PostDecrementExpression PostIncrementExpression:
PostfixExpression++PostDecrementExpression:
PostfixExpression--UnaryExpression:
PreIncrementExpression
PreDecrementExpression
+UnaryExpression
-UnaryExpression
UnaryExpressionNotPlusMinus PreIncrementExpression:
++UnaryExpression PreDecrementExpression:
--UnaryExpression UnaryExpressionNotPlusMinus:
PostfixExpression
~UnaryExpression
!UnaryExpression
CastExpression CastExpression:
(PrimitiveTypeDimsopt)UnaryExpression
(Expression)UnaryExpressionNotPlusMinus
(NameDims)UnaryExpressionNotPlusMinus MultiplicativeExpression:
UnaryExpression
MultiplicativeExpression*UnaryExpression
MultiplicativeExpression/UnaryExpression
MultiplicativeExpression%UnaryExpression AdditiveExpression:
MultiplicativeExpression
AdditiveExpression+MultiplicativeExpression
AdditiveExpression-MultiplicativeExpression ShiftExpression:
AdditiveExpression
ShiftExpression<<AdditiveExpression
ShiftExpression>>AdditiveExpression
ShiftExpression>>>AdditiveExpression RelationalExpression:
ShiftExpression
RelationalExpression<ShiftExpression
RelationalExpression>ShiftExpression
RelationalExpression<=ShiftExpression
RelationalExpression>=ShiftExpression
RelationalExpressioninstanceofReferenceType EqualityExpression:
RelationalExpression
EqualityExpression==RelationalExpression
EqualityExpression!=RelationalExpression AndExpression:
EqualityExpression
AndExpression&EqualityExpression ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression^AndExpression InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression|ExclusiveOrExpression ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression&&InclusiveOrExpression ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression||ConditionalAndExpression ConditionalExpression:
ConditionalOrExpression
ConditionalOrExpression?Expression:ConditionalExpression AssignmentExpression:
ConditionalExpression
Assignment Assignment:
LeftHandSideAssignmentOperatorAssignmentExpression LeftHandSide:
Name
FieldAccess
ArrayAccess AssignmentOperator: one of
= *= /= %= += -= <<= >>= >>>= &= ^= |=Expression:
AssignmentExpression ConstantExpression:
Expression
Contents | Prev | Next | Index
Java Language Specification (HTML generated by dkramer on August 01, 1996)
Copyright © 1996 Sun Microsystems, Inc.
All rights reserved
Please send any comments or corrections to doug.kramer@sun.com