/** A Java 1.5 grammar for ANTLR v3 derived from the spec * * This is a very close representation of the spec; the changes * are comestic (remove left recursion) and also fixes (the spec * isn't exactly perfect). I have run this on the 1.4.2 source * and some nasty looking enums from 1.5, but have not really * tested for 1.5 compatibility. * * I built this with: java -Xmx100M org.antlr.Tool java.g * and got two errors that are ok (for now): * java.g:691:9: Decision can match input such as * "'0'..'9'{'E', 'e'}{'+', '-'}'0'..'9'{'D', 'F', 'd', 'f'}" * using multiple alternatives: 3, 4 * As a result, alternative(s) 4 were disabled for that input * java.g:734:35: Decision can match input such as "{'$', 'A'..'Z', * '_', 'a'..'z', '\u00C0'..'\u00D6', '\u00D8'..'\u00F6', * '\u00F8'..'\u1FFF', '\u3040'..'\u318F', '\u3300'..'\u337F', * '\u3400'..'\u3D2D', '\u4E00'..'\u9FFF', '\uF900'..'\uFAFF'}" * using multiple alternatives: 1, 2 * As a result, alternative(s) 2 were disabled for that input * * You can turn enum on/off as a keyword :) * * Version 1.0 -- initial release July 5, 2006 (requires 3.0b2 or higher) * * Primary author: Terence Parr, July 2006 * * Version 1.0.1 -- corrections by Koen Vanderkimpen & Marko van Dooren, * October 25, 2006; * fixed normalInterfaceDeclaration: now uses typeParameters instead * of typeParameter (according to JLS, 3rd edition) * fixed castExpression: no longer allows expression next to type * (according to semantics in JLS, in contrast with syntax in JLS) */ grammar Java; options {k=2; backtrack=true; memoize=true;} @lexer::members { protected boolean enumIsKeyword = false; } // starting point for parsing a java file compilationUnit : annotations? packageDeclaration? importDeclaration* typeDeclaration* ; packageDeclaration : 'package' qualifiedName ';' ; importDeclaration : 'import' 'static'? Identifier ('.' Identifier)* ('.' '*')? ';' ; typeDeclaration : classOrInterfaceDeclaration | ';' ; classOrInterfaceDeclaration : modifier* (classDeclaration | interfaceDeclaration) ; classDeclaration : normalClassDeclaration | enumDeclaration ; normalClassDeclaration : 'class' Identifier (typeParameters)? ('extends' type)? ('implements' typeList)? classBody ; typeParameters : '<' typeParameter (',' typeParameter)* '>' ; typeParameter : Identifier ('extends' bound)? ; bound : 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 | modifier* memberDecl ; memberDecl : genericMethodOrConstructorDecl | methodDeclaration | fieldDeclaration | 'void' Identifier voidMethodDeclaratorRest | Identifier constructorDeclaratorRest | interfaceDeclaration | classDeclaration ; genericMethodOrConstructorDecl : typeParameters genericMethodOrConstructorRest ; genericMethodOrConstructorRest : (type | 'void') Identifier methodDeclaratorRest | Identifier constructorDeclaratorRest ; methodDeclaration : type Identifier methodDeclaratorRest ; fieldDeclaration : type variableDeclarators ';' ; interfaceBodyDeclaration : modifier* 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)? methodBody ; constantDeclarator : Identifier constantDeclaratorRest ; variableDeclarators : variableDeclarator (',' variableDeclarator)* ; variableDeclarator : Identifier variableDeclaratorRest ; variableDeclaratorRest : ('[' ']')+ ('=' variableInitializer)? | '=' 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 : Identifier ('.' Identifier)* ; enumConstantName : Identifier ; typeName : Identifier | packageOrTypeName '.' Identifier ; type : Identifier (typeArguments)? ('.' Identifier (typeArguments)? )* ('[' ']')* | primitiveType ('[' ']')* ; 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 : 'final'? annotations? type formalParameterDeclsRest? ; formalParameterDeclsRest : variableDeclaratorId (',' formalParameterDecls)? | '...' variableDeclaratorId ; methodBody : block ; qualifiedName : Identifier ('.' Identifier)* ; literal : integerLiteral | FloatingPointLiteral | CharacterLiteral | StringLiteral | booleanLiteral | 'null' ; integerLiteral : HexLiteral | OctalLiteral | DecimalLiteral ; booleanLiteral : 'true' | 'false' ; // ANNOTATIONS annotations : annotation+ ; annotation : '@' typeName ('(' (Identifier '=')? elementValue ')')? ; elementValue : conditionalExpression | annotation | elementValueArrayInitializer ; elementValueArrayInitializer : '{' (elementValue)? (',')? '}' ; annotationTypeDeclaration : '@' 'interface' Identifier annotationTypeBody ; annotationTypeBody : '{' (annotationTypeElementDeclarations)? '}' ; annotationTypeElementDeclarations : (annotationTypeElementDeclaration) (annotationTypeElementDeclaration)* ; annotationTypeElementDeclaration : (modifier)* annotationTypeElementRest ; annotationTypeElementRest : type Identifier annotationMethodOrConstantRest ';' | classDeclaration | interfaceDeclaration | enumDeclaration | annotationTypeDeclaration ; annotationMethodOrConstantRest : annotationMethodRest | annotationConstantRest ; annotationMethodRest : '(' ')' (defaultValue)? ; annotationConstantRest : variableDeclarators ; defaultValue : 'default' elementValue ; // STATEMENTS / BLOCKS block : '{' blockStatement* '}' ; blockStatement : localVariableDeclaration | classOrInterfaceDeclaration | statement ; localVariableDeclaration : ('final')? type variableDeclarators ';' ; statement : block | 'assert' expression (':' expression)? ';' | 'if' parExpression statement ('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 : variableModifier* type variableDeclaratorId ; switchBlockStatementGroups : (switchBlockStatementGroup)* ; switchBlockStatementGroup : switchLabel blockStatement* ; switchLabel : 'case' constantExpression ':' | 'case' enumConstantName ':' | 'default' ':' ; moreStatementExpressions : (',' statementExpression)* ; forControl : forVarControl | forInit? ';' expression? ';' forUpdate? ; forInit : 'final'? type variableDeclarators | expressionList ; forVarControl : 'final'? (annotation)? type Identifier forVarControlRest ; forVarControlRest : variableDeclaratorRest (',' variableDeclarator)* ';' expression? ':' forUpdate? | ':' expression ; forUpdate : expressionList ; // EXPRESSIONS parExpression : '(' expression ')' ; expressionList : expression (',' expression)* ; statementExpression : expression ; constantExpression : expression ; expression : conditionalExpression (assignmentOperator expression)? ; assignmentOperator : '=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '%=' | '<' '<' '=' | '>' '>' '=' | '>' '>' '>' '=' ; conditionalExpression : conditionalOrExpression ( '?' expression ':' expression )? ; 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 : ('<' '=' | '>' '=' | '<' | '>') ; shiftExpression : additiveExpression ( shiftOp additiveExpression )* ; // TODO: need a sem pred to check column on these >>> shiftOp : ('<' '<' | '>' '>' '>' | '>' '>') ; additiveExpression : multiplicativeExpression ( ('+' | '-') multiplicativeExpression )* ; multiplicativeExpression : unaryExpression ( ( '*' | '/' | '%' ) unaryExpression )* ; unaryExpression : '+' unaryExpression | '-' unaryExpression | '++' primary | '--' primary | unaryExpressionNotPlusMinus ; unaryExpressionNotPlusMinus : '~' unaryExpression | '!' unaryExpression | castExpression | primary selector* ('++'|'--')? ; castExpression : '(' primitiveType ')' unaryExpression | '(' (expression | type) ')' unaryExpressionNotPlusMinus ; primary : parExpression | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) | 'this' (arguments)? | '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' (nonWildcardTypeArguments)? innerCreator ; creator : nonWildcardTypeArguments? createdName (arrayCreatorRest | classCreatorRest) ; createdName : Identifier nonWildcardTypeArguments? ('.' Identifier nonWildcardTypeArguments?)* | primitiveType ; innerCreator : Identifier classCreatorRest ; arrayCreatorRest : '[' ( ']' ('[' ']')* arrayInitializer | expression ']' ('[' expression ']')* ('[' ']')* ) ; classCreatorRest : arguments classBody? ; explicitGenericInvocation : nonWildcardTypeArguments explicitGenericInvocationSuffix ; nonWildcardTypeArguments : '<' typeList '>' ; explicitGenericInvocationSuffix : 'super' superSuffix | Identifier arguments ; selector : '.' Identifier (arguments)? | '.' 'this' | '.' 'super' superSuffix | '.' 'new' (nonWildcardTypeArguments)? innerCreator | '[' expression ']' ; superSuffix : arguments | '.' Identifier (arguments)? ; arguments : '(' expressionList? ')' ; // LEXER HexLiteral : '0' ('x'|'X') HexDigit+ IntegerTypeSuffix? ; DecimalLiteral : ('0' | '1'..'9' '0'..'9'*) IntegerTypeSuffix? ; OctalLiteral : '0' ('0'..'7')+ IntegerTypeSuffix? ; fragment HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ; fragment IntegerTypeSuffix : ('l'|'L') ; FloatingPointLiteral : ('0'..'9')+ '.' ('0'..'9')* Exponent? FloatTypeSuffix? | '.' ('0'..'9')+ Exponent? FloatTypeSuffix? | ('0'..'9')+ Exponent FloatTypeSuffix? | ('0'..'9')+ Exponent? FloatTypeSuffix ; fragment Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; fragment FloatTypeSuffix : ('f'|'F'|'d'|'D') ; CharacterLiteral : '\'' ( EscapeSequence | ~('\''|'\\') ) '\'' ; StringLiteral : '"' ( EscapeSequence | ~('\\'|'"') )* '"' ; fragment EscapeSequence : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') | UnicodeEscape | OctalEscape ; fragment OctalEscape : '\\' ('0'..'3') ('0'..'7') ('0'..'7') | '\\' ('0'..'7') ('0'..'7') | '\\' ('0'..'7') ; fragment UnicodeEscape : '\\' 'u' HexDigit HexDigit HexDigit HexDigit ; ENUM: 'enum' {if ( !enumIsKeyword ) $type=Identifier;} ; Identifier : Letter (Letter|JavaIDDigit)* ; /**I found this char range in JavaCC's grammar, but Letter and Digit overlap. Still works, but... */ fragment Letter : '\u0024' | '\u0041'..'\u005a' | '\u005f' | '\u0061'..'\u007a' | '\u00c0'..'\u00d6' | '\u00d8'..'\u00f6' | '\u00f8'..'\u00ff' | '\u0100'..'\u1fff' | '\u3040'..'\u318f' | '\u3300'..'\u337f' | '\u3400'..'\u3d2d' | '\u4e00'..'\u9fff' | '\uf900'..'\ufaff' ; fragment JavaIDDigit : '\u0030'..'\u0039' | '\u0660'..'\u0669' | '\u06f0'..'\u06f9' | '\u0966'..'\u096f' | '\u09e6'..'\u09ef' | '\u0a66'..'\u0a6f' | '\u0ae6'..'\u0aef' | '\u0b66'..'\u0b6f' | '\u0be7'..'\u0bef' | '\u0c66'..'\u0c6f' | '\u0ce6'..'\u0cef' | '\u0d66'..'\u0d6f' | '\u0e50'..'\u0e59' | '\u0ed0'..'\u0ed9' | '\u1040'..'\u1049' ; WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;} ; COMMENT : '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;} ; LINE_COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} ;