Javaの文法を19.に示す。文法は,LALR(1) 文法であることが機械的に検査されている。
これまでに示したJavaの文法は,説明には適しているが,C及びC++から継承された一部の構文的特異性のために,1トークンの先読みではLR(left-to-right)技法で解析できない。次に,この問題及びLALR(1)文法で採用された解決を示し,その後の節で文法自体を規定する。
PackageName:
Identifier
PackageName . Identifier
TypeName:
Identifier
PackageName . Identifier
MethodName:
Identifier
AmbiguousName . Identifier
AmbiguousName:
Identifier
AmbiguousName . Identifier
class Problem1 { int m() { hayden.
パーサが記号 "." まで 1トークン先読みしてトークンhaydenを検討するとき,パーサは,haydenが次のとおり型名を限定するPackageNameでなければならないか
hayden.Dinosaur rex = new hayden.Dinosaur(2);
又は次のとおりメソッド名を限定するAmbiguousNameでなければならないか,まだ判定できない。
hayden.print("Dinosaur Rex!");
したがって,前述の生成規則は,LALR(1)の文法ではないことになる。この文法には,各種の名前の区別に関する別の問題も存在する。
これを解決するには,非終端記号のPackageName,TypeName,ExpressionName,MethodName,及びAmbiguousNameを削除し,これらを単一の非終端記号Nameで置き換える。
Name:
SimpleName
QualifiedName
SimpleName:
Identifier
QualifiedName:
Name . Identifier
コンパイラ解析の後の段階で,各名前又は名前限定子の正確な役割を分類する。
関連した理由により,4.3の次の生成規則
ClassOrInterfaceType:
ClassType
InterfaceType
ClassType:
TypeName
InterfaceType:
TypeName
ClassOrInterfaceType:
Name
ClassType:
ClassOrInterfaceType
InterfaceType:
ClassOrInterfaceType
次の二つの生成規則を考える。
FieldDeclaration:
FieldModifiers opt Type VariableDeclarators ;
FieldModifiers:
FieldModifier
FieldModifiers FieldModifier
FieldModifier: one of
public protected private
final static transient volatile
MethodHeader:
MethodModifiersopt ResultType MethodDeclarator Throwsopt
MethodModifiers:
MethodModifier
MethodModifiers MethodModifier
MethodModifier: one of
public protected private
static
abstract final native synchronized
class Problem2 { public static int
パーサが記号intまで 1トークン先読みしてトークンstaticを検討するとき,又はさらに悪い状況として,staticまで1トークン先読みしてトークンpublicを検討するとき,これが次のとおりフィールド宣言なのか
public static int maddie = 0;
public static int maddie(String art) { return art.length(); }
したがって,パーサは1トークンの先読みだけでは,static(又は同様にpublic)をFieldModifierとして還元すべきか,MethodModifierとして還元すべきか判定できない。したがって,前述の生成規則は,LALR(1)の文法ではないことになる。この文法には,各種の修飾子の区別に関する別の問題も存在する。
すべての文脈で問題が起きるわけではないが,最も簡単に解決するには,これらの修飾子が使用されているすべての文脈を統合し,非終端記号ClassModifiers(8.1.2),FieldModifiers(8.3.1),MethodModifiers(8.4.3),ConstructorModifiers(8.6.3),InterfaceModifiers(9.1.2),ConstantModifiers(9.3)の六つすべてを削除し,単一の非終端記号Modifiersで置き換える。
Modifiers:
Modifier
Modifiers Modifier
Modifier: one of
public protected private
static
abstract final native synchronized transient volatile
コンパイラ解析の後の段階で,各修飾子の正確な役割を分類し,及びそれが与えられた文脈で許されるかどうかを解析する。
次の二つの生成規則(問題点2の修正を施した生成規則)を考える。
FieldDeclaration:
Modifiersopt Type VariableDeclarators ;
MethodHeader:
Modifiersopt ResultType MethodDeclarator Throwsopt
ResultType:
Type
void
class Problem3 { int julie
この簡単な例は,Modifiersが存在しないことに注意すること。パーサが1トークン先読みして記号julieまで行き,トークンintを検討するとき,これが次のとおりフィールド宣言なのか
int julie = 14;
int julie(String art) { return art.length(); }
したがって,パーサは,intを非終端記号のTypeとして還元した後で,TypeをさらにResultTypeとして還元しなければならない(メソッド宣言の場合)か,そのままにしておく(フィールド宣言の場合)のか,1トークンの先読みだけでは判定できない。したがって,前述の生成規則は,LALR(1)の文法ではないことになる。
これを解決するには,ResultTypeの生成規則を削除して,MethodHeaderに別の選択肢を用意する。
MethodHeader:
Modifiersopt Type MethodDeclarator Throwsopt
Modifiersopt void MethodDeclarator Throwsopt
これで,パーサはintをTypeとして還元してそのままにしておき,フィールド宣言又はメソッド宣言の判定を遅らせることができる。
ArrayType:
Type [ ]
ArrayAccess:
Name [ Expression ]
PrimaryNoNewArray [ Expression ]
class Problem4 { Problem4() { peter[
パーサが記号 [ まで1トークン先読みしてトークンpeterを解析するとき,peterが次のとおり型名の一部なのか
peter[] team;
peter[3] = 12;
判定できない。したがって,パーサは,peterを非終端記号のNameとして還元した後で,Nameを最終的にTypeとして還元する(配列型の場合)のか,又はそのままにしておく(配列アクセスの場合)のか,1トークンの先読みでは判定できない。したがって,前述の生成規則は,LALR(1)の文法ではないことになる。
これを解決するには,ArrayTypeに別の選択肢を用意する。
ArrayType:
PrimitiveType [ ]
Name [ ]
ArrayType [ ]
これで,パーサは,peterをNameとして還元してそのままにしておき,配列型又は配列アクセスの判定を遅らせることができる。
CastExpression:
( PrimitiveType ) UnaryExpression
( ReferenceType ) UnaryExpressionNotPlusMinus
class Problem5 { Problem5() { super((matthew)
パーサが記号 ) まで1トークン先読みしてトークンmatthewを解析するとき,(matthew) が次のとおり括弧付き式なのか:
super((matthew), 9);
super((matthew)baz, 9);
判定できない。したがって,パーサは,matthewを非終端記号のNameとして還元した後で,NameをさらにPostfixExpressionとして還元し,最終的にExpressionとして還元する (括弧付きの式の場合)のか,ClassOrInterfaceTypeとして還元し,次にReferenceTypeとして還元する(キャストの場合)のか,1トークンの先読みでは判定できない。したがって,前述の生成規則は,LALR(1)の文法ではないことになる。
これを解決するには,CastExpressionの定義内の非終端記号ReferenceTypeを削除する。これは,別のあいまいさを回避するために,両選択肢の多少の変更が必要となる。
CastExpression:
( PrimitiveType Dimsopt ) UnaryExpression
( Expression ) UnaryExpressionNotPlusMinus
( Name Dims ) UnaryExpressionNotPlusMinus
これで,パーサはmatthewをExpressionとして還元してそのままにしておき,括弧付き式又はキャストの判定を遅らせることができる。さらに,
(int[])+3
(matthew+1)baz
のような不適切な書式は,コンパイラ解析の後の段階で削除及び拒否しなければならない。
以降の節では,Java構文の LALR(1) 文法を構成する。この文法では,前述の五つの問題は解決されている。
Goal:
CompilationUnit
Literal:
IntegerLiteral
FloatingPointLiteral
BooleanLiteral
CharacterLiteral
StringLiteral
NullLiteral
Type:
PrimitiveType
ReferenceType
PrimitiveType:
NumericType
boolean
NumericType:
IntegralType
FloatingPointType
IntegralType: one of
byte short int long char
FloatingPointType: one of
float double
ReferenceType:
ClassOrInterfaceType
ArrayType
ClassOrInterfaceType:
Name
ClassType:
ClassOrInterfaceType
InterfaceType:
ClassOrInterfaceType
ArrayType:
PrimitiveType [ ]
Name [ ]
ArrayType [ ]
Name:
SimpleName
QualifiedName
SimpleName:
Identifier
QualifiedName:
Name . Identifier
CompilationUnit:
PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt
ImportDeclarations:
ImportDeclaration
ImportDeclarations ImportDeclaration
TypeDeclarations:
TypeDeclaration
TypeDeclarations TypeDeclaration
PackageDeclaration:
package Name ;
ImportDeclaration:
SingleTypeImportDeclaration
TypeImportOnDemandDeclaration
SingleTypeImportDeclaration:
import Name ;
TypeImportOnDemandDeclaration:
import Name . * ;
TypeDeclaration:
ClassDeclaration
InterfaceDeclaration
;
Modifiers:
Modifier
Modifiers Modifier
Modifier: one of
public protected private
static
abstract final native synchronized transient volatile
ClassDeclaration:
Modifiersopt class Identifier Superopt Interfacesopt ClassBody
Super:
extends ClassType
Interfaces:
implements InterfaceTypeList
InterfaceTypeList:
InterfaceType
InterfaceTypeList , InterfaceType
ClassBody:
{ ClassBodyDeclarationsopt }
ClassBodyDeclarations:
ClassBodyDeclaration
ClassBodyDeclarations ClassBodyDeclaration
ClassBodyDeclaration:
ClassMemberDeclaration
StaticInitializer
ConstructorDeclaration
ClassMemberDeclaration:
FieldDeclaration
MethodDeclaration
FieldDeclaration:
Modifiersopt Type VariableDeclarators ;
VariableDeclarators:
VariableDeclarator
VariableDeclarators , VariableDeclarator
VariableDeclarator:
VariableDeclaratorId
VariableDeclaratorId = VariableInitializer
VariableDeclaratorId:
Identifier
VariableDeclaratorId [ ]
VariableInitializer:
Expression
ArrayInitializer
MethodDeclaration:
MethodHeader MethodBody
MethodHeader:
Modifiersopt Type MethodDeclarator Throwsopt
Modifiersopt void MethodDeclarator Throwsopt
MethodDeclarator:
Identifier ( FormalParameterListopt )
MethodDeclarator [ ]
FormalParameterList:
FormalParameter
FormalParameterList , FormalParameter
FormalParameter:
Type VariableDeclaratorId
Throws:
throws ClassTypeList
ClassTypeList:
ClassType
ClassTypeList , ClassType
MethodBody:
Block
;
StaticInitializer:
static Block
ConstructorDeclaration:
Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody
ConstructorDeclarator:
SimpleName ( FormalParameterListopt )
ConstructorBody:
{ ExplicitConstructorInvocationopt BlockStatementsopt }
ExplicitConstructorInvocation:
this ( ArgumentListopt ) ;
super ( ArgumentListopt ) ;
InterfaceDeclaration:
Modifiersopt interface Identifier ExtendsInterfacesopt InterfaceBody
ExtendsInterfaces:
extends InterfaceType
ExtendsInterfaces , InterfaceType
InterfaceBody:
{ InterfaceMemberDeclarationsopt }
InterfaceMemberDeclarations:
InterfaceMemberDeclaration
InterfaceMemberDeclarations InterfaceMemberDeclaration
InterfaceMemberDeclaration:
ConstantDeclaration
AbstractMethodDeclaration
ConstantDeclaration:
FieldDeclaration
AbstractMethodDeclaration:
MethodHeader ;
ArrayInitializer:
{ VariableInitializersopt ,opt }
VariableInitializers:
VariableInitializer
VariableInitializers , VariableInitializer
Block:
{ BlockStatementsopt }
BlockStatements:
BlockStatement
BlockStatements BlockStatement
BlockStatement:
LocalVariableDeclarationStatement
Statement
LocalVariableDeclarationStatement:
LocalVariableDeclaration ;
LocalVariableDeclaration:
Type VariableDeclarators
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 ) StatementNoShortIf else Statement
IfThenElseStatementNoShortIf:
if ( Expression ) StatementNoShortIf else StatementNoShortIf
SwitchStatement:
switch ( Expression ) SwitchBlock
SwitchBlock:
{ SwitchBlockStatementGroupsopt SwitchLabelsopt }
SwitchBlockStatementGroups:
SwitchBlockStatementGroup
SwitchBlockStatementGroups SwitchBlockStatementGroup
SwitchBlockStatementGroup:
SwitchLabels BlockStatements
SwitchLabels:
SwitchLabel
SwitchLabels SwitchLabel
SwitchLabel:
case ConstantExpression :
default :
WhileStatement:
while ( Expression ) Statement
WhileStatementNoShortIf:
while ( Expression ) StatementNoShortIf
DoStatement:
do Statement while ( Expression ) ;
ForStatement:
for ( ForInitopt ; Expressionopt ; ForUpdateopt )
Statement
ForStatementNoShortIf:
for ( ForInitopt ; Expressionopt ; ForUpdateopt )
StatementNoShortIf
ForInit:
StatementExpressionList
LocalVariableDeclaration
ForUpdate:
StatementExpressionList
StatementExpressionList:
StatementExpression
StatementExpressionList , StatementExpression
BreakStatement:
break Identifieropt ;
ContinueStatement:
continue Identifieropt ;
ReturnStatement:
return Expressionopt ;
ThrowStatement:
throw Expression ;
SynchronizedStatement:
synchronized ( Expression ) Block
TryStatement:
try Block Catches
try Block Catchesopt Finally
Catches:
CatchClause
Catches CatchClause
CatchClause:
catch ( FormalParameter ) Block
Finally:
finally Block
Primary:
PrimaryNoNewArray
ArrayCreationExpression
PrimaryNoNewArray:
Literal
this
( Expression )
ClassInstanceCreationExpression
FieldAccess
MethodInvocation
ArrayAccess
ClassInstanceCreationExpression:
new ClassType ( ArgumentListopt )
ArgumentList:
Expression
ArgumentList , Expression
ArrayCreationExpression:
new PrimitiveType DimExprs Dimsopt
new ClassOrInterfaceType DimExprs Dimsopt
DimExprs:
DimExpr
DimExprs DimExpr
DimExpr:
[ Expression ]
Dims:
[ ]
Dims [ ]
FieldAccess:
Primary . Identifier
super . Identifier
MethodInvocation:
Name ( ArgumentListopt )
Primary . Identifier ( ArgumentListopt )
super . Identifier ( 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:
( PrimitiveType Dimsopt ) UnaryExpression
( Expression ) UnaryExpressionNotPlusMinus
( Name Dims ) 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
RelationalExpression instanceof ReferenceType
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:
LeftHandSide AssignmentOperator AssignmentExpression
LeftHandSide:
Name
FieldAccess
ArrayAccess
AssignmentOperator: one of
= *= /= %= += -= <<= >>= >>>= &= ^= |=
Expression:
AssignmentExpression
ConstantExpression:
Expression