antlr/tool/playground/JavaParser.g

757 lines
16 KiB
Plaintext

ûparser grammar JavaParser;
options {backtrack=true; memoize=true; tokenVocab=JavaLexer;}
// starting point for parsing a java file
/* The annotations are separated out to make parsing faster, but must be associated with
a packageDeclaration or a typeDeclaration (and not an empty one). */
compilationUnit
: annotations
( packageDeclaration importDeclaration* typeDeclaration*
| classOrInterfaceDeclaration typeDeclaration*
)
| packageDeclaration? importDeclaration* typeDeclaration*
;
packageDeclaration
: 'package' qualifiedName ';'
;
importDeclaration
: 'import' 'static'? qualifiedName ('.' '*')? ';'
;
typeDeclaration
: classOrInterfaceDeclaration
| ';'
;
classOrInterfaceDeclaration
: classOrInterfaceModifiers (classDeclaration | interfaceDeclaration)
;
classOrInterfaceModifiers
: classOrInterfaceModifier*
;
classOrInterfaceModifier
: annotation // class or interface
| 'public' // class or interface
| 'protected' // class or interface
| 'private' // class or interface
| 'abstract' // class or interface
| 'static' // class or interface
| 'final' // class only -- does not apply to interfaces
| 'strictfp' // class or interface
;
modifiers
: modifier*
;
classDeclaration
: normalClassDeclaration
| enumDeclaration
;
normalClassDeclaration
: 'class' Identifier typeParameters?
('extends' type)?
('implements' typeList)?
classBody
;
typeParameters
: '<' typeParameter (',' typeParameter)* '>'
;
typeParameter
: Identifier ('extends' typeBound)?
;
typeBound
: type ('&' type)*
;
enumDeclaration
: ENUM Identifier ('implements' typeList)? enumBody
;
enumBody
: '{' enumConstants? ','? enumBodyDeclarations? '}'
;
enumConstants
: enumConstant (',' enumConstant)*
;
enumConstant
: annotations? Identifier arguments? classBody?
;
enumBodyDeclarations
: ';' (classBodyDeclaration)*
;
interfaceDeclaration
: normalInterfaceDeclaration
| annotationTypeDeclaration
;
normalInterfaceDeclaration
: 'interface' Identifier typeParameters? ('extends' typeList)? interfaceBody
;
typeList
: type (',' type)*
;
classBody
: '{' classBodyDeclaration* '}'
;
interfaceBody
: '{' interfaceBodyDeclaration* '}'
;
classBodyDeclaration
: ';'
| 'static'? block
| modifiers memberDecl
;
memberDecl
: genericMethodOrConstructorDecl
| memberDeclaration
| 'void' Identifier voidMethodDeclaratorRest
| Identifier constructorDeclaratorRest
| interfaceDeclaration
| classDeclaration
;
memberDeclaration
: type (methodDeclaration | fieldDeclaration)
;
genericMethodOrConstructorDecl
: typeParameters genericMethodOrConstructorRest
;
genericMethodOrConstructorRest
: (type | 'void') Identifier methodDeclaratorRest
| Identifier constructorDeclaratorRest
;
methodDeclaration
: Identifier methodDeclaratorRest
;
fieldDeclaration
: variableDeclarators ';'
;
interfaceBodyDeclaration
: modifiers interfaceMemberDecl
| ';'
;
interfaceMemberDecl
: interfaceMethodOrFieldDecl
| interfaceGenericMethodDecl
| 'void' Identifier voidInterfaceMethodDeclaratorRest
| interfaceDeclaration
| classDeclaration
;
interfaceMethodOrFieldDecl
: type Identifier interfaceMethodOrFieldRest
;
interfaceMethodOrFieldRest
: constantDeclaratorsRest ';'
| interfaceMethodDeclaratorRest
;
methodDeclaratorRest
: formalParameters ('[' ']')*
('throws' qualifiedNameList)?
( methodBody
| ';'
)
;
voidMethodDeclaratorRest
: formalParameters ('throws' qualifiedNameList)?
( methodBody
| ';'
)
;
interfaceMethodDeclaratorRest
: formalParameters ('[' ']')* ('throws' qualifiedNameList)? ';'
;
interfaceGenericMethodDecl
: typeParameters (type | 'void') Identifier
interfaceMethodDeclaratorRest
;
voidInterfaceMethodDeclaratorRest
: formalParameters ('throws' qualifiedNameList)? ';'
;
constructorDeclaratorRest
: formalParameters ('throws' qualifiedNameList)? constructorBody
;
constantDeclarator
: Identifier constantDeclaratorRest
;
variableDeclarators
: variableDeclarator (',' variableDeclarator)*
;
variableDeclarator
: variableDeclaratorId ('=' variableInitializer)?
;
constantDeclaratorsRest
: constantDeclaratorRest (',' constantDeclarator)*
;
constantDeclaratorRest
: ('[' ']')* '=' variableInitializer
;
variableDeclaratorId
: Identifier ('[' ']')*
;
variableInitializer
: arrayInitializer
| expression
;
arrayInitializer
: '{' (variableInitializer (',' variableInitializer)* (',')? )? '}'
;
modifier
: annotation
| 'public'
| 'protected'
| 'private'
| 'static'
| 'abstract'
| 'final'
| 'native'
| 'synchronized'
| 'transient'
| 'volatile'
| 'strictfp'
;
packageOrTypeName
: qualifiedName
;
enumConstantName
: Identifier
;
typeName
: qualifiedName
;
type
: classOrInterfaceType ('[' ']')*
| primitiveType ('[' ']')*
;
classOrInterfaceType
: Identifier typeArguments? ('.' Identifier typeArguments? )*
;
primitiveType
: 'boolean'
| 'char'
| 'byte'
| 'short'
| 'int'
| 'long'
| 'float'
| 'double'
;
variableModifier
: 'final'
| annotation
;
typeArguments
: '<' typeArgument (',' typeArgument)* '>'
;
typeArgument
: type
| '?' (('extends' | 'super') type)?
;
qualifiedNameList
: qualifiedName (',' qualifiedName)*
;
formalParameters
: '(' formalParameterDecls? ')'
;
formalParameterDecls
: variableModifiers type formalParameterDeclsRest
;
formalParameterDeclsRest
: variableDeclaratorId (',' formalParameterDecls)?
| '...' variableDeclaratorId
;
methodBody
: block
;
constructorBody
: '{' explicitConstructorInvocation? blockStatement* '}'
;
explicitConstructorInvocation
: nonWildcardTypeArguments? ('this' | 'super') arguments ';'
| primary '.' nonWildcardTypeArguments? 'super' arguments ';'
;
qualifiedName
: Identifier ('.' Identifier)*
;
literal
: integerLiteral
| FloatingPointLiteral
| CharacterLiteral
| StringLiteral
| booleanLiteral
| 'null'
;
integerLiteral
: HexLiteral
| OctalLiteral
| DecimalLiteral
;
booleanLiteral
: 'true'
| 'false'
;
// ANNOTATIONS
annotations
: annotation+
;
annotation
: '@' annotationName ( '(' ( elementValuePairs | elementValue )? ')' )?
;
annotationName
: Identifier ('.' Identifier)*
;
elementValuePairs
: elementValuePair (',' elementValuePair)*
;
elementValuePair
: Identifier '=' elementValue
;
elementValue
: conditionalExpression
| annotation
| elementValueArrayInitializer
;
elementValueArrayInitializer
: '{' (elementValue (',' elementValue)*)? (',')? '}'
;
annotationTypeDeclaration
: '@' 'interface' Identifier annotationTypeBody
;
annotationTypeBody
: '{' (annotationTypeElementDeclaration)* '}'
;
annotationTypeElementDeclaration
: modifiers annotationTypeElementRest
;
annotationTypeElementRest
: type annotationMethodOrConstantRest ';'
| normalClassDeclaration ';'?
| normalInterfaceDeclaration ';'?
| enumDeclaration ';'?
| annotationTypeDeclaration ';'?
;
annotationMethodOrConstantRest
: annotationMethodRest
| annotationConstantRest
;
annotationMethodRest
: Identifier '(' ')' defaultValue?
;
annotationConstantRest
: variableDeclarators
;
defaultValue
: 'default' elementValue
;
// STATEMENTS / BLOCKS
block
: '{' blockStatement* '}'
;
blockStatement
: localVariableDeclarationStatement
| classOrInterfaceDeclaration
| statement
;
localVariableDeclarationStatement
: localVariableDeclaration ';'
;
localVariableDeclaration
: variableModifiers type variableDeclarators
;
variableModifiers
: variableModifier*
;
statement
: block
| ASSERT expression (':' expression)? ';'
| 'if' parExpression statement (options {k=1;}:'else' statement)?
| 'for' '(' forControl ')' statement
| 'while' parExpression statement
| 'do' statement 'while' parExpression ';'
| 'try' block
( catches 'finally' block
| catches
| 'finally' block
)
| 'switch' parExpression '{' switchBlockStatementGroups '}'
| 'synchronized' parExpression block
| 'return' expression? ';'
| 'throw' expression ';'
| 'break' Identifier? ';'
| 'continue' Identifier? ';'
| ';'
| statementExpression ';'
| Identifier ':' statement
;
catches
: catchClause (catchClause)*
;
catchClause
: 'catch' '(' formalParameter ')' block
;
formalParameter
: variableModifiers type variableDeclaratorId
;
switchBlockStatementGroups
: (switchBlockStatementGroup)*
;
/* The change here (switchLabel -> switchLabel+) technically makes this grammar
ambiguous; but with appropriately greedy parsing it yields the most
appropriate AST, one in which each group, except possibly the last one, has
labels and statements. */
switchBlockStatementGroup
: switchLabel+ blockStatement*
;
switchLabel
: 'case' constantExpression ':'
| 'case' enumConstantName ':'
| 'default' ':'
;
forControl
options {k=3;} // be efficient for common case: for (ID ID : ID) ...
: enhancedForControl
| forInit? ';' expression? ';' forUpdate?
;
forInit
: localVariableDeclaration
| expressionList
;
enhancedForControl
: variableModifiers type Identifier ':' expression
;
forUpdate
: expressionList
;
// EXPRESSIONS
parExpression
: '(' expression ')'
;
expressionList
: expression (',' expression)*
;
statementExpression
: expression
;
constantExpression
: expression
;
expression
: conditionalExpression (assignmentOperator expression)?
;
assignmentOperator
: '='
| '+='
| '-='
| '*='
| '/='
| '&='
| '|='
| '^='
| '%='
| '<' '<' '='
| '>' '>' '>' '='
| '>' '>' '='
/*
| ('<' '<' '=')=> t1='<' t2='<' t3='='
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() &&
$t2.getLine() == $t3.getLine() &&
$t2.getCharPositionInLine() + 1 == $t3.getCharPositionInLine() }?
| ('>' '>' '>' '=')=> t1='>' t2='>' t3='>' t4='='
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() &&
$t2.getLine() == $t3.getLine() &&
$t2.getCharPositionInLine() + 1 == $t3.getCharPositionInLine() &&
$t3.getLine() == $t4.getLine() &&
$t3.getCharPositionInLine() + 1 == $t4.getCharPositionInLine() }?
| ('>' '>' '=')=> t1='>' t2='>' t3='='
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() &&
$t2.getLine() == $t3.getLine() &&
$t2.getCharPositionInLine() + 1 == $t3.getCharPositionInLine() }?
*/
;
conditionalExpression
: conditionalOrExpression ( '?' conditionalExpression ':' conditionalExpression )?
;
conditionalOrExpression
: conditionalAndExpression ( '||' conditionalAndExpression )*
;
conditionalAndExpression
: inclusiveOrExpression ( '&&' inclusiveOrExpression )*
;
inclusiveOrExpression
: exclusiveOrExpression ( '|' exclusiveOrExpression )*
;
exclusiveOrExpression
: andExpression ( '^' andExpression )*
;
andExpression
: equalityExpression ( '&' equalityExpression )*
;
equalityExpression
: instanceOfExpression ( ('==' | '!=') instanceOfExpression )*
;
instanceOfExpression
: relationalExpression ('instanceof' type)?
;
relationalExpression
: shiftExpression ( relationalOp shiftExpression )*
;
relationalOp
: '<' '='
| '>' '='
| '<'
| '>'
;
/*
relationalOp
: ('<' '=')=> t1='<' t2='='
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() }?
| ('>' '=')=> t1='>' t2='='
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() }?
| '<'
| '>'
;
*/
shiftExpression
: additiveExpression ( shiftOp additiveExpression )*
;
shiftOp
: '<' '<'
| '>' '>' '>'
| '>' '>'
;
/*
shiftOp
: ('<' '<')=> t1='<' t2='<'
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() }?
| ('>' '>' '>')=> t1='>' t2='>' t3='>'
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() &&
$t2.getLine() == $t3.getLine() &&
$t2.getCharPositionInLine() + 1 == $t3.getCharPositionInLine() }?
| ('>' '>')=> t1='>' t2='>'
{ $t1.getLine() == $t2.getLine() &&
$t1.getCharPositionInLine() + 1 == $t2.getCharPositionInLine() }?
;
*/
additiveExpression
: multiplicativeExpression ( ('+' | '-') multiplicativeExpression )*
;
multiplicativeExpression
: unaryExpression ( ( '*' | '/' | '%' ) unaryExpression )*
;
unaryExpression
: '+' unaryExpression
| '-' unaryExpression
| '++' unaryExpression
| '--' unaryExpression
| unaryExpressionNotPlusMinus
;
unaryExpressionNotPlusMinus
: '~' unaryExpression
| '!' unaryExpression
| castExpression
| primary selector* ('++'|'--')?
;
castExpression
: '(' primitiveType ')' unaryExpression
| '(' (type | expression) ')' unaryExpressionNotPlusMinus
;
primary
: parExpression
| 'this' ('.' Identifier)* identifierSuffix?
| 'super' superSuffix
| literal
| 'new' creator
| Identifier ('.' Identifier)* identifierSuffix?
| primitiveType ('[' ']')* '.' 'class'
| 'void' '.' 'class'
;
identifierSuffix
: ('[' ']')+ '.' 'class'
// | ('[' expression ']')+ // can also be matched by selector, but do here
| arguments
| '.' 'class'
| '.' explicitGenericInvocation
| '.' 'this'
| '.' 'super' arguments
| '.' 'new' innerCreator
;
creator
: nonWildcardTypeArguments createdName classCreatorRest
| createdName (arrayCreatorRest | classCreatorRest)
;
createdName
: classOrInterfaceType
| primitiveType
;
innerCreator
: nonWildcardTypeArguments? Identifier classCreatorRest
;
arrayCreatorRest
: '['
( ']' ('[' ']')* arrayInitializer
| expression ']' ('[' expression ']')* ('[' ']')*
)
;
classCreatorRest
: arguments classBody?
;
explicitGenericInvocation
: nonWildcardTypeArguments Identifier arguments
;
nonWildcardTypeArguments
: '<' typeList '>'
;
selector
: '.' Identifier arguments?
| '.' 'this'
| '.' 'super' superSuffix
| '.' 'new' innerCreator
| '[' expression ']'
;
superSuffix
: arguments
| '.' Identifier arguments?
;
arguments
: '(' expressionList? ')'
;