/**
*
* This is a modified version of the grammar written by Sriram Sankar for Java 1.1
* and modified by David Williamns for Java 1.2. It has been modified to accept Java
* sources for Java 1.4. The grammar have been modified in four parts:
* 1) 'assert' has been included to the keyword list
* 2) AssertStatement() production has been added
* 3) the production Statement() has been modified in order to support AssertStatement()
* 4) in the main the string "for Java1.2 code" has been changed with "for Java1.4 code"
*
* To track changes, search for the string "// added by Andrea Gini"
*
* Andrea Gini, 24/02/2002
* ginian@tiscali.it
*
* ==================================================================
*
* This file is a modified version of one originally found in the
* JavaGrammars Examples directory of JavaCC1_1. It has been
* modified to accept Java source code for Java 1.2. Basically,
* this means a new key word was added, 'strictfp', and that keyword
* added to the appropriate productions and LOOKAHEADs (where other,
* similar keywords are listed as possible choices). This involved
* changing 11 lines.
*
* Minor changes were also made to the main program for testing.
*
* The goal of this effort was for the grammar to be able to parse
* any legal Java 1.2 source code. It does not reject all illegal
* cases, but neither did the original. Plus, when it comes to
* the new 'strictfp' keyword, the Java Compiler from Sun (JDK1.2.1)
* also does not reject all illegal cases, as defined by the
* "Updates" document found at
* http://java.sun.com/docs/books/jls/strictfp-changes.pdf
* (see the testcases.txt file for details).
*
* David Williams, 7/99
* ===================================================================
*
*
* Copyright (C) 1996, 1997 Sun Microsystems Inc.
*
* Use of this file and the system it is part of is constrained by the
* file COPYRIGHT in the root directory of this system. You may, however,
* make any modifications you wish to this file.
*
* Java files generated by running JavaCC on this file (or modified versions
* of this file) may be used in exactly the same manner as Java files
* generated from any grammar developed by you.
*
* Author: Sriram Sankar
* Date: 3/5/97
*
* This file contains a Java grammar and actions that implement a front-end.
*
*/
options {
JAVA_UNICODE_ESCAPE = true;
STATIC = false;
}
PARSER_BEGIN(JavaParser)
public class JavaParser
{
// modified main Andrea Gini 24/02/2002
// modified main. DW, 7/99
public static void main (String [] args) {
JavaParser parser;
String filename = null;
long initTime = 0;
long parseTime = 0;
long startTime = 0;
long stopTime = 0;
if (args.length == 0)
{
System.out.println("Java Parser Version 1.1 (for Java1.4 code): Reading from standard input . . .");
parser = new JavaParser(System.in);
} else if (args.length == 1)
{
filename = args[0];
System.out.println("Java Parser Version 1.1 (for Java1.4 code): Reading from file " + filename + " . . .");
try
{
startTime = System.currentTimeMillis();
parser = new JavaParser(new java.io.FileInputStream(filename));
stopTime = System.currentTimeMillis();
initTime = stopTime - startTime;
} catch (java.io.FileNotFoundException e)
{
System.out.println("Java Parser Version 1.1 (for Java1.4 code): File " + filename + " not found.");
return;
}
} else
{
System.out.println("Java Parser Version 1.1 (for Java1.4 code): Usage is one of:");
System.out.println(" java JavaParser < inputfile");
System.out.println("OR");
System.out.println(" java JavaParser inputfile");
return;
}
try
{
startTime = System.currentTimeMillis();
parser.CompilationUnit();
stopTime = System.currentTimeMillis();
parseTime = stopTime - startTime;
System.out.println("Java Parser Version 1.1 (for Java1.4 code): ");
System.out.println(" Java program parsed " + filename + " successfully in " + (initTime + parseTime) + " ms.");
System.out.println(" parser initialization time was " + initTime + " ms.");
System.out.println(" parser parse time was " + parseTime + " ms.");
} catch (ParseException e)
{
System.out.println(e.getMessage());
System.out.println("Java Parser Version 1.1 (for Java1.4 code): Encountered errors during parse.");
}
}
}
PARSER_END(JavaParser)
/* WHITE SPACE */
SKIP :
{
" "
| "\t"
| "\n"
| "\r"
| "\f"
}
/* COMMENTS */
MORE :
{
"//" : IN_SINGLE_LINE_COMMENT
|
<"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
|
"/*" : IN_MULTI_LINE_COMMENT
}
SPECIAL_TOKEN :
{
: DEFAULT
}
SPECIAL_TOKEN :
{
: DEFAULT
}
SPECIAL_TOKEN :
{
: DEFAULT
}
MORE :
{
< ~[] >
}
/* RESERVED WORDS AND LITERALS */
TOKEN :
{
< ABSTRACT: "abstract" >
| < BOOLEAN: "boolean" >
| < BREAK: "break" >
| < BYTE: "byte" >
| < CASE: "case" >
| < CATCH: "catch" >
| < CHAR: "char" >
| < CLASS: "class" >
| < CONST: "const" >
| < CONTINUE: "continue" >
| < _DEFAULT: "default" >
| < DO: "do" >
| < DOUBLE: "double" >
| < ELSE: "else" >
| < EXTENDS: "extends" >
| < FALSE: "false" >
| < FINAL: "final" >
| < FINALLY: "finally" >
| < FLOAT: "float" >
| < FOR: "for" >
| < GOTO: "goto" >
| < IF: "if" >
| < IMPLEMENTS: "implements" >
| < IMPORT: "import" >
| < INSTANCEOF: "instanceof" >
| < INT: "int" >
| < INTERFACE: "interface" >
| < LONG: "long" >
| < NATIVE: "native" >
| < NEW: "new" >
| < NULL: "null" >
| < PACKAGE: "package">
| < PRIVATE: "private" >
| < PROTECTED: "protected" >
| < PUBLIC: "public" >
| < RETURN: "return" >
| < SHORT: "short" >
| < STATIC: "static" >
| < SUPER: "super" >
| < SWITCH: "switch" >
| < SYNCHRONIZED: "synchronized" >
| < THIS: "this" >
| < THROW: "throw" >
| < THROWS: "throws" >
| < TRANSIENT: "transient" >
| < TRUE: "true" >
| < TRY: "try" >
| < VOID: "void" >
| < VOLATILE: "volatile" >
| < WHILE: "while" >
| < STRICTFP: "strictfp" >
// added by Andrea Gini
| < ASSERT: "assert" >
}
/* LITERALS */
TOKEN :
{
< INTEGER_LITERAL:
(["l","L"])?
| (["l","L"])?
| (["l","L"])?
>
|
< #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
|
< #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
|
< #OCTAL_LITERAL: "0" (["0"-"7"])* >
|
< FLOATING_POINT_LITERAL:
(["0"-"9"])+ "." (["0"-"9"])* ()? (["f","F","d","D"])?
| "." (["0"-"9"])+ ()? (["f","F","d","D"])?
| (["0"-"9"])+ (["f","F","d","D"])?
| (["0"-"9"])+ ()? ["f","F","d","D"]
>
|
< #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|
< CHARACTER_LITERAL:
"'"
( (~["'","\\","\n","\r"])
| ("\\"
( ["n","t","b","r","f","\\","'","\""]
| ["0"-"7"] ( ["0"-"7"] )?
| ["0"-"3"] ["0"-"7"] ["0"-"7"]
)
)
)
"'"
>
|
< STRING_LITERAL:
"\""
( (~["\"","\\","\n","\r"])
| ("\\"
( ["n","t","b","r","f","\\","'","\""]
| ["0"-"7"] ( ["0"-"7"] )?
| ["0"-"3"] ["0"-"7"] ["0"-"7"]
)
)
)*
"\""
>
}
/* IDENTIFIERS */
TOKEN :
{
< IDENTIFIER: (|)* >
|
< #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"
]
>
|
< #DIGIT:
[
"\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"
]
>
}
/* SEPARATORS */
TOKEN :
{
< LPAREN: "(" >
| < RPAREN: ")" >
| < LBRACE: "{" >
| < RBRACE: "}" >
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < SEMICOLON: ";" >
| < COMMA: "," >
| < DOT: "." >
}
/* OPERATORS */
TOKEN :
{
< ASSIGN: "=" >
| < GT: ">" >
| < LT: "<" >
| < BANG: "!" >
| < TILDE: "~" >
| < HOOK: "?" >
| < COLON: ":" >
| < EQ: "==" >
| < LE: "<=" >
| < GE: ">=" >
| < NE: "!=" >
| < SC_OR: "||" >
| < SC_AND: "&&" >
| < INCR: "++" >
| < DECR: "--" >
| < PLUS: "+" >
| < MINUS: "-" >
| < STAR: "*" >
| < SLASH: "/" >
| < BIT_AND: "&" >
| < BIT_OR: "|" >
| < XOR: "^" >
| < REM: "%" >
| < LSHIFT: "<<" >
| < RSIGNEDSHIFT: ">>" >
| < RUNSIGNEDSHIFT: ">>>" >
| < PLUSASSIGN: "+=" >
| < MINUSASSIGN: "-=" >
| < STARASSIGN: "*=" >
| < SLASHASSIGN: "/=" >
| < ANDASSIGN: "&=" >
| < ORASSIGN: "|=" >
| < XORASSIGN: "^=" >
| < REMASSIGN: "%=" >
| < LSHIFTASSIGN: "<<=" >
| < RSIGNEDSHIFTASSIGN: ">>=" >
| < RUNSIGNEDSHIFTASSIGN: ">>>=" >
}
/*****************************************
* THE JAVA LANGUAGE GRAMMAR STARTS HERE *
*****************************************/
/*
* Program structuring syntax follows.
*/
void CompilationUnit() :
{}
{
[ PackageDeclaration() ]
( ImportDeclaration() )*
( TypeDeclaration() )*
}
void PackageDeclaration() :
{}
{
"package" Name() ";"
}
void ImportDeclaration() :
{}
{
"import" Name() [ "." "*" ] ";"
}
void TypeDeclaration() :
{}
{
LOOKAHEAD( ( "abstract" | "final" | "public" | "strictfp" )* "class" )
ClassDeclaration()
|
InterfaceDeclaration()
|
";"
}
/*
* Declaration syntax follows.
*/
void ClassDeclaration() :
{}
{
( "abstract" | "final" | "public" | "strictfp")*
UnmodifiedClassDeclaration()
}
void UnmodifiedClassDeclaration() :
{}
{
"class" [ "extends" Name() ] [ "implements" NameList() ]
ClassBody()
}
void ClassBody() :
{}
{
"{" ( ClassBodyDeclaration() )* "}"
}
void NestedClassDeclaration() :
{}
{
( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp")*
UnmodifiedClassDeclaration()
}
void ClassBodyDeclaration() :
{}
{
LOOKAHEAD(2)
Initializer()
|
LOOKAHEAD( ( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp")* "class" )
NestedClassDeclaration()
|
LOOKAHEAD( ( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp")* "interface" )
NestedInterfaceDeclaration()
|
LOOKAHEAD( [ "public" | "protected" | "private" ] Name() "(" )
ConstructorDeclaration()
|
LOOKAHEAD( MethodDeclarationLookahead() )
MethodDeclaration()
|
FieldDeclaration()
}
// This production is to determine lookahead only.
void MethodDeclarationLookahead() :
{}
{
( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" | "strictfp")*
ResultType() "("
}
void InterfaceDeclaration() :
{}
{
( "abstract" | "public" | "strictfp")*
UnmodifiedInterfaceDeclaration()
}
void NestedInterfaceDeclaration() :
{}
{
( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp")*
UnmodifiedInterfaceDeclaration()
}
void UnmodifiedInterfaceDeclaration() :
{}
{
"interface" [ "extends" NameList() ]
"{" ( InterfaceMemberDeclaration() )* "}"
}
void InterfaceMemberDeclaration() :
{}
{
LOOKAHEAD( ( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp")* "class" )
NestedClassDeclaration()
|
LOOKAHEAD( ( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp")* "interface" )
NestedInterfaceDeclaration()
|
LOOKAHEAD( MethodDeclarationLookahead() )
MethodDeclaration()
|
FieldDeclaration()
}
void FieldDeclaration() :
{}
{
( "public" | "protected" | "private" | "static" | "final" | "transient" | "volatile" )*
Type() VariableDeclarator() ( "," VariableDeclarator() )* ";"
}
void VariableDeclarator() :
{}
{
VariableDeclaratorId() [ "=" VariableInitializer() ]
}
void VariableDeclaratorId() :
{}
{
( "[" "]" )*
}
void VariableInitializer() :
{}
{
ArrayInitializer()
|
Expression()
}
void ArrayInitializer() :
{}
{
"{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
}
void MethodDeclaration() :
{}
{
( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" | "strictfp")*
ResultType() MethodDeclarator() [ "throws" NameList() ]
( Block() | ";" )
}
void MethodDeclarator() :
{}
{
FormalParameters() ( "[" "]" )*
}
void FormalParameters() :
{}
{
"(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
}
void FormalParameter() :
{}
{
[ "final" ] Type() VariableDeclaratorId()
}
void ConstructorDeclaration() :
{}
{
[ "public" | "protected" | "private" ]
FormalParameters() [ "throws" NameList() ]
"{"
[ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ]
( BlockStatement() )*
"}"
}
void ExplicitConstructorInvocation() :
{}
{
LOOKAHEAD("this" Arguments() ";")
"this" Arguments() ";"
|
[ LOOKAHEAD(2) PrimaryExpression() "." ] "super" Arguments() ";"
}
void Initializer() :
{}
{
[ "static" ] Block()
}
/*
* Type, name and expression syntax follows.
*/
void Type() :
{}
{
( PrimitiveType() | Name() ) ( "[" "]" )*
}
void PrimitiveType() :
{}
{
"boolean"
|
"char"
|
"byte"
|
"short"
|
"int"
|
"long"
|
"float"
|
"double"
}
void ResultType() :
{}
{
"void"
|
Type()
}
void Name() :
/*
* A lookahead of 2 is required below since "Name" can be followed
* by a ".*" when used in the context of an "ImportDeclaration".
*/
{}
{
( LOOKAHEAD(2) "."
)*
}
void NameList() :
{}
{
Name()
( "," Name()
)*
}
/*
* Expression syntax follows.
*/
void Expression() :
/*
* This expansion has been written this way instead of:
* Assignment() | ConditionalExpression()
* for performance reasons.
* However, it is a weakening of the grammar for it allows the LHS of
* assignments to be any conditional expression whereas it can only be
* a primary expression. Consider adding a semantic predicate to work
* around this.
*/
{}
{
ConditionalExpression()
[
AssignmentOperator() Expression()
]
}
void AssignmentOperator() :
{}
{
"=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|="
}
void ConditionalExpression() :
{}
{
ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression() ]
}
void ConditionalOrExpression() :
{}
{
ConditionalAndExpression() ( "||" ConditionalAndExpression() )*
}
void ConditionalAndExpression() :
{}
{
InclusiveOrExpression() ( "&&" InclusiveOrExpression() )*
}
void InclusiveOrExpression() :
{}
{
ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )*
}
void ExclusiveOrExpression() :
{}
{
AndExpression() ( "^" AndExpression() )*
}
void AndExpression() :
{}
{
EqualityExpression() ( "&" EqualityExpression() )*
}
void EqualityExpression() :
{}
{
InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )*
}
void InstanceOfExpression() :
{}
{
RelationalExpression() [ "instanceof" Type() ]
}
void RelationalExpression() :
{}
{
ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )*
}
void ShiftExpression() :
{}
{
AdditiveExpression() ( ( "<<" | ">>" | ">>>" ) AdditiveExpression() )*
}
void AdditiveExpression() :
{}
{
MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )*
}
void MultiplicativeExpression() :
{}
{
UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )*
}
void UnaryExpression() :
{}
{
( "+" | "-" ) UnaryExpression()
|
PreIncrementExpression()
|
PreDecrementExpression()
|
UnaryExpressionNotPlusMinus()
}
void PreIncrementExpression() :
{}
{
"++" PrimaryExpression()
}
void PreDecrementExpression() :
{}
{
"--" PrimaryExpression()
}
void UnaryExpressionNotPlusMinus() :
{}
{
( "~" | "!" ) UnaryExpression()
|
LOOKAHEAD( CastLookahead() )
CastExpression()
|
PostfixExpression()
}
// This production is to determine lookahead only. The LOOKAHEAD specifications
// below are not used, but they are there just to indicate that we know about
// this.
void CastLookahead() :
{}
{
LOOKAHEAD(2)
"(" PrimitiveType()
|
LOOKAHEAD("(" Name() "[")
"(" Name() "[" "]"
|
"(" Name() ")" ( "~" | "!" | "(" | | "this" | "super" | "new" | Literal() )
}
void PostfixExpression() :
{}
{
PrimaryExpression() [ "++" | "--" ]
}
void CastExpression() :
{}
{
LOOKAHEAD("(" PrimitiveType())
"(" Type() ")" UnaryExpression()
|
"(" Type() ")" UnaryExpressionNotPlusMinus()
}
void PrimaryExpression() :
{}
{
PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )*
}
void PrimaryPrefix() :
{}
{
Literal()
|
"this"
|
"super" "."
|
"(" Expression() ")"
|
AllocationExpression()
|
LOOKAHEAD( ResultType() "." "class" )
ResultType() "." "class"
|
Name()
}
void PrimarySuffix() :
{}
{
LOOKAHEAD(2)
"." "this"
|
LOOKAHEAD(2)
"." AllocationExpression()
|
"[" Expression() "]"
|
"."
|
Arguments()
}
void Literal() :
{}
{
|
|
|
|
BooleanLiteral()
|
NullLiteral()
}
void BooleanLiteral() :
{}
{
"true"
|
"false"
}
void NullLiteral() :
{}
{
"null"
}
void Arguments() :
{}
{
"(" [ ArgumentList() ] ")"
}
void ArgumentList() :
{}
{
Expression() ( "," Expression() )*
}
void AllocationExpression() :
{}
{
LOOKAHEAD(2)
"new" PrimitiveType() ArrayDimsAndInits()
|
"new" Name()
(
ArrayDimsAndInits()
|
Arguments() [ ClassBody() ]
)
}
/*
* The second LOOKAHEAD specification below is to parse to PrimarySuffix
* if there is an expression between the "[...]".
*/
void ArrayDimsAndInits() :
{}
{
LOOKAHEAD(2)
( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )*
|
( "[" "]" )+ ArrayInitializer()
}
/*
* Statement syntax follows.
*/
void Statement() :
{}
{
LOOKAHEAD(2)
LabeledStatement()
|
Block()
|
EmptyStatement()
|
StatementExpression() ";"
|
SwitchStatement()
|
IfStatement()
|
WhileStatement()
|
DoStatement()
|
ForStatement()
|
BreakStatement()
|
ContinueStatement()
|
ReturnStatement()
|
ThrowStatement()
|
SynchronizedStatement()
|
TryStatement()
// added by Andrea Gini
|
AssertStatement()
}
void LabeledStatement() :
{}
{
":" Statement()
}
void Block() :
{}
{
"{" ( BlockStatement() )* "}"
}
void BlockStatement() :
{}
{
LOOKAHEAD([ "final" ] Type() )
LocalVariableDeclaration() ";"
|
Statement()
|
UnmodifiedClassDeclaration()
|
UnmodifiedInterfaceDeclaration()
}
void LocalVariableDeclaration() :
{}
{
[ "final" ] Type() VariableDeclarator() ( "," VariableDeclarator() )*
}
void EmptyStatement() :
{}
{
";"
}
void StatementExpression() :
/*
* The last expansion of this production accepts more than the legal
* Java expansions for StatementExpression. This expansion does not
* use PostfixExpression for performance reasons.
*/
{}
{
PreIncrementExpression()
|
PreDecrementExpression()
|
PrimaryExpression()
[
"++"
|
"--"
|
AssignmentOperator() Expression()
]
}
void SwitchStatement() :
{}
{
"switch" "(" Expression() ")" "{"
( SwitchLabel() ( BlockStatement() )* )*
"}"
}
void SwitchLabel() :
{}
{
"case" Expression() ":"
|
"default" ":"
}
void IfStatement() :
/*
* The disambiguating algorithm of JavaCC automatically binds dangling
* else's to the innermost if statement. The LOOKAHEAD specification
* is to tell JavaCC that we know what we are doing.
*/
{}
{
"if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]
}
void WhileStatement() :
{}
{
"while" "(" Expression() ")" Statement()
}
void DoStatement() :
{}
{
"do" Statement() "while" "(" Expression() ")" ";"
}
void ForStatement() :
{}
{
"for" "(" [ ForInit() ] ";" [ Expression() ] ";" [ ForUpdate() ] ")" Statement()
}
void ForInit() :
{}
{
LOOKAHEAD( [ "final" ] Type() )
LocalVariableDeclaration()
|
StatementExpressionList()
}
void StatementExpressionList() :
{}
{
StatementExpression() ( "," StatementExpression() )*
}
void ForUpdate() :
{}
{
StatementExpressionList()
}
void BreakStatement() :
{}
{
"break" [ ] ";"
}
void ContinueStatement() :
{}
{
"continue" [ ] ";"
}
void ReturnStatement() :
{}
{
"return" [ Expression() ] ";"
}
void ThrowStatement() :
{}
{
"throw" Expression() ";"
}
void SynchronizedStatement() :
{}
{
"synchronized" "(" Expression() ")" Block()
}
void TryStatement() :
/*
* Semantic check required here to make sure that at least one
* finally/catch is present.
*/
{}
{
"try" Block()
( "catch" "(" FormalParameter() ")" Block() )*
[ "finally" Block() ]
}
// added by Andrea Gini
void AssertStatement() :
{}
{
"assert" Expression() [ ":" Expression() ] ";"
}