All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javacc.parser.java_1_5.jj Maven / Gradle / Ivy


/**
 * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * California 95054, U.S.A. All rights reserved.  Sun Microsystems, Inc. has
 * intellectual property rights relating to technology embodied in the product
 * that is described in this document. In particular, and without limitation,
 * these intellectual property rights may include one or more of the U.S.
 * patents listed at http://www.sun.com/patents and one or more additional
 * patents or pending patent applications in the U.S. and in other countries.
 * U.S. Government Rights - Commercial software. Government users are subject
 * to the Sun Microsystems, Inc. standard license agreement and applicable
 * provisions of the FAR and its supplements.  Use is subject to license terms.
 * Sun,  Sun Microsystems,  the Sun logo and  Java are trademarks or registered
 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.  This
 * product is covered and controlled by U.S. Export Control laws and may be
 * subject to the export or import laws in other countries.  Nuclear, missile,
 * chemical biological weapons or nuclear maritime end uses or end users,
 * whether direct or indirect, are strictly prohibited.  Export or reexport
 * to countries subject to U.S. embargo or to entities identified on U.S.
 * export exclusion lists, including, but not limited to, the denied persons
 * and specially designated nationals lists is strictly prohibited.
 */

options {
  LOOKAHEAD=1; 
  STATIC=false;
  CACHE_TOKENS=true;
  ERROR_REPORTING = true;
  JAVA_UNICODE_ESCAPE=false;
  UNICODE_INPUT=true;
  DEBUG_PARSER=false;
  DEBUG_LOOKAHEAD=false;
  DEBUG_TOKEN_MANAGER=false;
}

PARSER_BEGIN(JavaParser)
package japa.parser;

import java.io.*;
import java.util.*;
import japa.parser.ast.*;
import japa.parser.ast.body.*;
import japa.parser.ast.expr.*;
import japa.parser.ast.stmt.*;
import japa.parser.ast.type.*;

/**
 * Grammar to parse Java version 1.5
 * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5
 * @author J?lio Vilmar Gesser - bug fixes and added AST generation
 */
public final class JavaParser {

    private static JavaParser parser;

    public static CompilationUnit parse(InputStream in) throws ParseException {
        if (parser == null) {
            parser = new JavaParser(in);
        } else {
            parser.ReInit(in);
        }
        return parser.CompilationUnit();
    }
    	
    public static CompilationUnit parse(File file) throws ParseException {
        try {
	        FileInputStream in = new FileInputStream(file);
	        try {
	        	return parse(in);
	        } finally {
	        	in.close();
	        }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    private List add(List list, Object obj) {
    	if (list == null) {
    		list = new LinkedList();
    	}
    	list.add(obj);
    	return list;
    }

	private class Modifier {
		
		final int modifiers;
		final List annotations;
		
		public Modifier(int modifiers, List annotations) {
			this.modifiers = modifiers;
			this.annotations = annotations;
		}
		
	}

}

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" >
| < ASSERT: "assert" >
| < 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" >
| < ENUM: "enum" >
| < 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" >
| < STRICTFP: "strictfp" >
| < SUPER: "super" >
| < SWITCH: "switch" >
| < SYNCHRONIZED: "synchronized" >
| < THIS: "this" >
| < THROW: "throw" >
| < THROWS: "throws" >
| < TRANSIENT: "transient" >
| < TRUE: "true" >
| < TRY: "try" >
| < VOID: "void" >
| < VOLATILE: "volatile" >
| < WHILE: "while" >
}

/* LITERALS */

TOKEN :
{
  < LONG_LITERAL:
         (["l","L"])
      |  (["l","L"])
      |  (["l","L"])
  >
|
  < INTEGER_LITERAL:
        
      | 
      | 
  >
|
  < #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"]
            )
          )
        | ("\\u"
        	["0"-"9","A"-"F","a"-"f"]
        	["0"-"9","A"-"F","a"-"f"]
        	["0"-"9","A"-"F","a"-"f"]
        	["0"-"9","A"-"F","a"-"f"]
          )
      )
      "'"
  >
|
  < STRING_LITERAL:
      "\""
      (   (~["\"","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
        | ("\\u"
        	["0"-"9","A"-"F","a"-"f"]
        	["0"-"9","A"-"F","a"-"f"]
        	["0"-"9","A"-"F","a"-"f"]
        	["0"-"9","A"-"F","a"-"f"]
          )
      )*
      "\""
  >
}

/* 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: "." >
| < AT: "@" >
}

/* OPERATORS */

TOKEN :
{
  < ASSIGN: "=" >
| < 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: "<<" >
| < PLUSASSIGN: "+=" >
| < MINUSASSIGN: "-=" >
| < STARASSIGN: "*=" >
| < SLASHASSIGN: "/=" >
| < ANDASSIGN: "&=" >
| < ORASSIGN: "|=" >
| < XORASSIGN: "^=" >
| < REMASSIGN: "%=" >
| < LSHIFTASSIGN: "<<=" >
| < RSIGNEDSHIFTASSIGN: ">>=" >
| < RUNSIGNEDSHIFTASSIGN: ">>>=" >
| < ELLIPSIS: "..." >
}

/* >'s need special attention due to generics syntax. */
TOKEN :
{
  < RUNSIGNEDSHIFT: ">>>" >
  {
     matchedToken.kind = GT;
     ((Token.GTToken)matchedToken).realKind = RUNSIGNEDSHIFT;
     input_stream.backup(2);
  }
| < RSIGNEDSHIFT: ">>" >
  {
     matchedToken.kind = GT;
     ((Token.GTToken)matchedToken).realKind = RSIGNEDSHIFT;
     input_stream.backup(1);
  }
| < GT: ">" >
}


/*****************************************
 * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
 *****************************************/

/*
 * Program structuring syntax follows.
 */

CompilationUnit CompilationUnit():
{
	NameExpr pakage = null;
	List imports = null;
	ImportDeclaration in = null;
	List types = null;
	TypeDeclaration tn = null;
}
{
  [ pakage = PackageDeclaration() ]
  ( in = ImportDeclaration() { imports = add(imports, in); } )*
  ( tn = TypeDeclaration() { types = add(types, tn); } )*
  
  { return new CompilationUnit(pakage, imports, types); }
}

NameExpr PackageDeclaration():
{
	NameExpr ret;
}
{
  "package" ret = Name() ";"
  { return ret; }
}

ImportDeclaration ImportDeclaration():
{
	NameExpr name;
	boolean isStatic = false;
	boolean isAsterisk = false;
}
{
  "import" [ "static" { isStatic = true; } ] name = Name() [ "." "*" { isAsterisk = true; } ] ";"
  { return new ImportDeclaration(name, isStatic, isAsterisk); }
}

/*
 * Modifiers. We match all modifiers in a single rule to reduce the chances of
 * syntax errors for simple modifier mistakes. It will also enable us to give
 * better error messages.
 */

Modifier Modifiers():
{
   int modifiers = 0;
   List annotations = null;
   AnnotationExpr ann;
}
{
 (
  LOOKAHEAD(2)
  (
   "public" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.PUBLIC, token); }
  |
   "static" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.STATIC, token); }
  |
   "protected" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.PROTECTED, token); }
  |
   "private" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.PRIVATE, token); }
  |
   "final" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.FINAL, token); }
  |
   "abstract" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.ABSTRACT, token); }
  |
   "synchronized" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.SYNCHRONIZED, token); }
  |
   "native" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.NATIVE, token); }
  |
   "transient" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.TRANSIENT, token); }
  |
   "volatile" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.VOLATILE, token); }
  |
   "strictfp" { modifiers = ModifierSet.addModifier(modifiers, ModifierSet.STRICTFP, token); }
  |
   ann = Annotation() { annotations = add(annotations, ann); }
  )
 )*

 {
    return new Modifier(modifiers, annotations);
 }
}

/*
 * Declaration syntax follows.
 */
TypeDeclaration TypeDeclaration():
{
   Modifier modifier;
   TypeDeclaration ret;
}
{
  ";" { return EmptyTypeDeclaration.SINGLETON; }
|
  modifier = Modifiers()
  (
     ret = ClassOrInterfaceDeclaration(modifier)
   |
     ret = EnumDeclaration(modifier)
   |
     ret = AnnotationTypeDeclaration(modifier)
  )
  { return ret; }
}


ClassOrInterfaceDeclaration ClassOrInterfaceDeclaration(Modifier modifier):
{
   boolean isInterface = false;
   String name;
   List typePar = null;
   List extList = null;
   List impList = null;
   List members;
}
{
  ( "class" | "interface" { isInterface = true; } )
   { name = token.image; }
  [ typePar = TypeParameters() ]
  [ extList = ExtendsList(isInterface) ]
  [ impList = ImplementsList(isInterface) ]
  members = ClassOrInterfaceBody(isInterface)
  
  { return new ClassOrInterfaceDeclaration(modifier.modifiers, modifier.annotations, isInterface, name, typePar, extList, impList, members); }
}

List ExtendsList(boolean isInterface):
{
   boolean extendsMoreThanOne = false;
   List ret = new LinkedList();
   ClassOrInterfaceType cit;
}
{
   "extends" cit = ClassOrInterfaceType() { ret.add(cit); }
   ( "," cit = ClassOrInterfaceType() { ret.add(cit); extendsMoreThanOne = true; } )*
   {
      if (extendsMoreThanOne && !isInterface)
         throw new ParseException(token, "A class cannot extend more than one other class");
   }
   { return ret; }
}

List ImplementsList(boolean isInterface):
{
   List ret = new LinkedList();
   ClassOrInterfaceType cit;
}
{
   "implements" cit = ClassOrInterfaceType() { ret.add(cit); }
   ( "," cit = ClassOrInterfaceType() { ret.add(cit); } )*
   {
      if (isInterface)
         throw new ParseException(token, "An interface cannot implement other interfaces");
   }
   { return ret; }
}

EnumDeclaration EnumDeclaration(Modifier modifier):
{
	String name;
	List impList = null;
	EnumConstantDeclaration entry;
	List entries = null;
	BodyDeclaration member;
	List members = null;
}
{
  "enum"  { name = token.image; }
  [ impList = ImplementsList(false) ]
  "{"
  	[
    	{ entries = new LinkedList(); }
    	entry = EnumConstant() { entries.add(entry); } ( LOOKAHEAD(2) "," entry = EnumConstant() { entries.add(entry); } )*
  	]
 	[ 
 		","
 	  |
 	 	( ";" ( member = ClassOrInterfaceBodyDeclaration(false) { members = add(members, member); } )* )
 	]
  "}"
  
  { return new EnumDeclaration(modifier.modifiers, modifier.annotations, name, impList, entries, members); }
}


EnumConstantDeclaration EnumConstant():
{
	String name;
	List args = null;
	List classBody = null;
}
{
   { name = token.image; } [ args = Arguments() ] [ classBody = ClassOrInterfaceBody(false) ]
  { return new EnumConstantDeclaration(name, args, classBody);  }
}

List TypeParameters():
{
	List ret = new LinkedList();
	TypeParameter tp;
}
{
   "<"   tp = TypeParameter() { ret.add(tp); } 
   ( "," tp = TypeParameter() { ret.add(tp); } )* ">"
   { return ret; }
}

TypeParameter TypeParameter():
{
	String name;
	List typeBound = null;
}
{
    { name = token.image; } [ typeBound = TypeBound() ]
   { return new TypeParameter(name, typeBound); }
}

List TypeBound():
{
	List ret = new LinkedList();
	ClassOrInterfaceType cit;
}
{
   "extends" cit = ClassOrInterfaceType() { ret.add(cit); }
   ( "&"     cit = ClassOrInterfaceType() { ret.add(cit); } )*
   { return ret; }
}

List ClassOrInterfaceBody(boolean isInterface):
{
	List ret = null;
	BodyDeclaration member;
}
{
  "{" ( member = ClassOrInterfaceBodyDeclaration(isInterface) { ret = add(ret, member); }  )* "}"
  { return ret; }
}

BodyDeclaration ClassOrInterfaceBodyDeclaration(boolean isInterface):
{
   boolean isNestedInterface = false;
   Modifier modifier;
   BodyDeclaration ret;
}
{
  (
	  LOOKAHEAD(2)
	  ret = Initializer()
	  {
	     if (isInterface)
	        throw new ParseException(token, "An interface cannot have initializers");
	  }
	|
	  modifier = Modifiers() // Just get all the modifiers out of the way. If you want to do
	              // more checks, pass the modifiers down to the member
	  (
	      ret = ClassOrInterfaceDeclaration(modifier)
	    |
	      ret = EnumDeclaration(modifier)
	    |
	      ret = AnnotationTypeDeclaration(modifier)
	    |
	      LOOKAHEAD( [ TypeParameters() ]  "(" )
	      ret = ConstructorDeclaration(modifier)
	    |
	      LOOKAHEAD( Type()  ( "[" "]" )* ( "," | "=" | ";" ) )
	      ret = FieldDeclaration(modifier)
	    |
	      ret = MethodDeclaration(modifier)
	  )
	|
	  ";" { ret = EmptyMemberDeclaration.SINGLETON; }
  )
  { return ret; }
}

FieldDeclaration FieldDeclaration(Modifier modifier):
{
	Type type;
	List variables = new LinkedList();
	VariableDeclarator val;
}
{
  // Modifiers are already matched in the caller
  type = Type() 
        val = VariableDeclarator() { variables.add(val); } 
  ( "," val = VariableDeclarator() { variables.add(val); } )* ";"
  
  { return new FieldDeclaration(modifier.modifiers, modifier.annotations, type, variables); }
}

VariableDeclarator VariableDeclarator():
{
	VariableDeclaratorId id;
	Expression init = null;
}
{
  id = VariableDeclaratorId() [ "=" init = VariableInitializer() ]
  { return new  VariableDeclarator(id, init); }
}

VariableDeclaratorId VariableDeclaratorId():
{
	String name;
	int arrayCount = 0;
}
{
   { name = token.image; }  ( "[" "]" { arrayCount++; } )*
  { return new VariableDeclaratorId(name, arrayCount); }
}

Expression VariableInitializer():
{
	Expression ret;
}
{
  (
	  ret = ArrayInitializer()
	|
	  ret = Expression()
  )
  { return ret;}
}

ArrayInitializerExpr ArrayInitializer():
{
	List values = null;
	Expression val;
}
{
  "{" [ val = VariableInitializer() { values = add(values, val); } ( LOOKAHEAD(2) "," val = VariableInitializer() { values = add(values, val); } )* ] [ "," ] "}"
  { return new ArrayInitializerExpr(values); }
}

MethodDeclaration MethodDeclaration(Modifier modifier):
{
	List typeParameters = null;
	Type type;
	String name;
	List parameters;
	int arrayCount = 0;
	List throws_ = null;
	BlockStmt block = null;
}
{
  // Modifiers already matched in the caller!
  [ typeParameters = TypeParameters() ]
  type = ResultType()
   { name = token.image; } parameters = FormalParameters() ( "[" "]" { arrayCount++; } )*
  [ "throws" throws_ = NameList() ]
  ( block = Block() | ";" )
  
  { return new MethodDeclaration(modifier.modifiers, modifier.annotations, typeParameters, type, name, parameters, arrayCount, throws_, block); }
}

List FormalParameters():
{
	List ret = null;
	Parameter par;
}
{
  "(" [ par = FormalParameter() { ret = add(ret, par); } ( "," par = FormalParameter() { ret = add(ret, par); } )* ] ")"
  
  { return ret; }
}

Parameter FormalParameter():
{
	Modifier modifier;
	Type type;
	boolean isVarArg = false;
	VariableDeclaratorId id;
}
{
  modifier = Modifiers() type = Type() [ "..." { isVarArg = true;} ] id = VariableDeclaratorId()
  
  { return new Parameter(modifier.modifiers, modifier.annotations, type, isVarArg, id); }
}

ConstructorDeclaration ConstructorDeclaration(Modifier modifier):
{
	List typeParameters = null;
	String name;
	List parameters;
	List throws_ = null;
	ExplicitConstructorInvocationStmt exConsInv = null;
	List stmts;
}
{
  [ typeParameters = TypeParameters() ]
  // Modifiers matched in the caller
   { name = token.image;} parameters = FormalParameters() [ "throws" throws_ = NameList() ]
  "{"
    [ LOOKAHEAD(ExplicitConstructorInvocation()) exConsInv = ExplicitConstructorInvocation() ]
    stmts = Statements()
  "}"
  
  { 
  	if (exConsInv != null) {
  		if (stmts == null) {
  			stmts = new LinkedList();
  		}
  		stmts.add(0, exConsInv);
  	}
  	return new ConstructorDeclaration(modifier.modifiers, modifier.annotations, typeParameters, name, parameters, throws_, new BlockStmt(stmts)); 
  }
}

ExplicitConstructorInvocationStmt ExplicitConstructorInvocation():
{
	boolean isThis = false;
	List args;
	Expression expr = null;
}
{
  (
	  LOOKAHEAD("this" Arguments() ";")
	  "this" { isThis = true; } args = Arguments() ";"
	|
	  [ LOOKAHEAD(2) expr = PrimaryExpression() "." ] "super" args = Arguments() ";"
  )
  { return new ExplicitConstructorInvocationStmt(isThis, expr, args); }
}

List Statements():
{
	List ret = null;
	Statement stmt;
}
{
	( stmt = BlockStatement() { ret = add(ret, stmt); } )*
	{ return ret; }
}

InitializerDeclaration Initializer():
{
	BlockStmt block;
}
{
  [ "static" ] block = Block()
  { return new InitializerDeclaration(block); }
}


/*
 * Type, name and expression syntax follows.
 */

Type Type():
{
	Type ret;
}
{
 (
   LOOKAHEAD(2) ret = ReferenceType()
 |
   ret = PrimitiveType()
 )
 { return ret; }
}

ReferenceType ReferenceType():
{
	Type type;
	int arrayCount = 0;
}
{
  (
   type = PrimitiveType() ( LOOKAHEAD(2) "[" "]" { arrayCount++; } )+
  |
   type = ClassOrInterfaceType() ( LOOKAHEAD(2) "[" "]" { arrayCount++; } )*
  )
  { return new ReferenceType(type, arrayCount); }
}

ClassOrInterfaceType ClassOrInterfaceType():
{
	ClassOrInterfaceType ret;
	String name;
	List typeArgs = null;
}
{
   { name = token.image; } [ LOOKAHEAD(2) typeArgs = TypeArguments() ] { ret = new ClassOrInterfaceType(null, name, typeArgs); }
  ( LOOKAHEAD(2) "."  { name = token.image; } [ LOOKAHEAD(2) typeArgs = TypeArguments() ] { ret = new ClassOrInterfaceType(ret, name, typeArgs); } )*
  { return ret; }
}

List TypeArguments():
{
	List ret = new LinkedList();
	Type type;
}
{
   "<" type = TypeArgument() { ret.add(type); } ( "," type = TypeArgument() { ret.add(type); } )* ">"
   { return ret; }
}

Type TypeArgument():
{
	Type ret;
}
{
 (
   ret = ReferenceType()
 |
   ret = Wildcard()
 )
 { return ret; }
}

WildcardType Wildcard():
{
	ReferenceType ext = null;
	ReferenceType sup = null;
}
{
   "?" 
   [
		"extends" ext = ReferenceType()
	|
		"super" sup = ReferenceType()
   ]
   { return new WildcardType(ext, sup); }
}

PrimitiveType PrimitiveType():
{
	PrimitiveType ret;
}
{
(
  "boolean" { ret = PrimitiveType.BOOLEAN; }
|
  "char" { ret = PrimitiveType.CHAR; }
|
  "byte" { ret = PrimitiveType.BYTE; }
|
  "short" { ret = PrimitiveType.SHORT; }
|
  "int" { ret = PrimitiveType.INT; }
|
  "long" { ret = PrimitiveType.LONG; }
|
  "float" { ret = PrimitiveType.FLOAT; }
|
  "double" { ret = PrimitiveType.DOUBLE; }
)
{ return ret; }
}

Type ResultType():
{
	Type ret;
}
{
  (
	  "void" { ret = VoidType.SINGLETON; }
	|
	  ret = Type()
  )
  { return ret; }
}

NameExpr Name():
/*
 * A lookahead of 2 is required below since "Name" can be followed
 * by a ".*" when used in the context of an "ImportDeclaration".
 */
{
	NameExpr ret;	
}
{
   { ret = new NameExpr(token.image); }
  ( LOOKAHEAD(2) "."  { ret = new QualifiedNameExpr(ret, token.image); } )*
  { return ret; }
}

List NameList():
{
	List ret = new LinkedList();
	NameExpr name;
}
{
  name = Name() { ret.add(name); }  ( "," name = Name() { ret.add(name); } )*
  
  { return ret; }
}


/*
 * Expression syntax follows.
 */

Expression 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.
 */
{
	Expression ret;
	AssignExpr.Operator op;
	Expression value;
}
{
  ret = ConditionalExpression()
  [
    LOOKAHEAD(2)
    op = AssignmentOperator() value = Expression() { ret = new AssignExpr(ret, value, op); }
  ]
  { return ret; }
}

AssignExpr.Operator AssignmentOperator():
{
	AssignExpr.Operator ret;
}
{
  (
      "="    { ret = AssignExpr.Operator.assign; }
    | "*="   { ret = AssignExpr.Operator.star; }
    | "/="   { ret = AssignExpr.Operator.slash; }
    | "%="   { ret = AssignExpr.Operator.rem; }
    | "+="   { ret = AssignExpr.Operator.plus; }
    | "-="   { ret = AssignExpr.Operator.minus; }
    | "<<="  { ret = AssignExpr.Operator.lShift; }
    | ">>="  { ret = AssignExpr.Operator.rSignedShift; }
    | ">>>=" { ret = AssignExpr.Operator.rUnsignedShift; }
    | "&="   { ret = AssignExpr.Operator.and; }
    | "^="   { ret = AssignExpr.Operator.xor; }
    | "|="   { ret = AssignExpr.Operator.or; }
  )
  { return ret; }
}

Expression ConditionalExpression():
{
	Expression ret;
	Expression left;
	Expression right;
}
{
  ret = ConditionalOrExpression() [ "?" left = Expression() ":" right = Expression() { ret = new ConditionalExpr(ret, left, right); } ]
  { return ret; }
}

Expression ConditionalOrExpression():
{
	Expression ret;
	Expression right;
}
{
  ret = ConditionalAndExpression() ( "||" right = ConditionalAndExpression() { ret = new BinaryExpr(ret, right, BinaryExpr.Operator.or); } )*
  { return ret; }
}

Expression ConditionalAndExpression():
{
	Expression ret;
	Expression right;
}
{
  ret = InclusiveOrExpression() ( "&&" right = InclusiveOrExpression() { ret = new BinaryExpr(ret, right, BinaryExpr.Operator.and); } )*
  { return ret; }
}

Expression InclusiveOrExpression():
{
	Expression ret;
	Expression right;
}
{
  ret = ExclusiveOrExpression() ( "|" right = ExclusiveOrExpression() { ret = new BinaryExpr(ret, right, BinaryExpr.Operator.binOr); } )*
  { return ret; }
}

Expression ExclusiveOrExpression():
{
	Expression ret;
	Expression right;
}
{
  ret = AndExpression() ( "^" right = AndExpression() { ret = new BinaryExpr(ret, right, BinaryExpr.Operator.xor); } )*
  { return ret; }
}

Expression AndExpression():
{
	Expression ret;
	Expression right;
}
{
  ret = EqualityExpression() ( "&" right = EqualityExpression() { ret = new BinaryExpr(ret, right, BinaryExpr.Operator.binAnd); } )*
  { return ret; }
}

Expression EqualityExpression():
{
	Expression ret;
	Expression right;
	BinaryExpr.Operator op;
}
{
  ret = InstanceOfExpression() 
  ( 
    ( "==" { op = BinaryExpr.Operator.equals; } | 
      "!=" { op = BinaryExpr.Operator.notEquals; } 
    ) right = InstanceOfExpression() { ret = new BinaryExpr(ret, right, op); } 
  )*
  { return ret; }
}

Expression InstanceOfExpression():
{
	Expression ret;
	Type type;
}
{
  ret = RelationalExpression() [ "instanceof" type = Type() { ret = new InstanceOfExpr(ret, type); } ]
  { return ret; }
}

Expression RelationalExpression():
{
	Expression ret;
	Expression right;
	BinaryExpr.Operator op;
}
{
  ret = ShiftExpression() 
  (
  	( "<"  { op = BinaryExpr.Operator.less; } | 
  	  ">"  { op = BinaryExpr.Operator.greater; } | 
  	  "<=" { op = BinaryExpr.Operator.lessEquals; } | 
  	  ">=" { op = BinaryExpr.Operator.greaterEquals; }
  	) right = ShiftExpression() { ret = new BinaryExpr(ret, right, op); }
  )*
  { return ret; }
}

Expression ShiftExpression():
{
	Expression ret;
	Expression right;
	BinaryExpr.Operator op;
}
{
  ret = AdditiveExpression()
  (
  	( "<<"             { op = BinaryExpr.Operator.lShift; } | 
  	  RSIGNEDSHIFT()   { op = BinaryExpr.Operator.rSignedShift; } | 
  	  RUNSIGNEDSHIFT() { op = BinaryExpr.Operator.rUnsignedShift; }
  	) right = AdditiveExpression() { ret = new BinaryExpr(ret, right, op); }
  )*
  { return ret; }
}

Expression AdditiveExpression():
{
	Expression ret;
	Expression right;
	BinaryExpr.Operator op;
}
{
  ret = MultiplicativeExpression() 
  ( 
  	( "+" { op = BinaryExpr.Operator.plus; } | 
  	  "-" { op = BinaryExpr.Operator.minus; }
  	) right = MultiplicativeExpression() { ret = new BinaryExpr(ret, right, op); }
  )*
  { return ret; }
}

Expression MultiplicativeExpression():
{
	Expression ret;
	Expression right;
	BinaryExpr.Operator op;
}
{
  ret = UnaryExpression() 
  ( 
  	( "*" { op = BinaryExpr.Operator.times; } | 
  	  "/" { op = BinaryExpr.Operator.divide; } |
  	  "%" { op = BinaryExpr.Operator.remainder; }
  	) right = UnaryExpression() { ret = new BinaryExpr(ret, right, op); }
  )*
  { return ret; }
}

Expression UnaryExpression():
{
	Expression ret;
	UnaryExpr.Operator op;
}
{
  (
	  ( "+" { op = UnaryExpr.Operator.positive; } | 
	    "-" { op = UnaryExpr.Operator.negative; }
	  ) ret = UnaryExpression() { ret = new UnaryExpr(ret, op); }
	|
	  ret = PreIncrementExpression()
	|
	  ret = PreDecrementExpression()
	|
	  ret = UnaryExpressionNotPlusMinus()
  )
  { return ret; }
}

Expression PreIncrementExpression():
{
	Expression ret;
}
{
  "++" ret = PrimaryExpression() { ret = new UnaryExpr(ret, UnaryExpr.Operator.preIncrement); }
  { return ret; }
}

Expression PreDecrementExpression():
{
	Expression ret;
}
{
  "--" ret = PrimaryExpression() { ret = new UnaryExpr(ret, UnaryExpr.Operator.preDecrement); }
  { return ret; }
}

Expression UnaryExpressionNotPlusMinus():
{
	Expression ret;
	UnaryExpr.Operator op;
}
{
  (
	  ( "~" { op = UnaryExpr.Operator.inverse; } | 
	    "!" { op = UnaryExpr.Operator.not; }
	  ) ret = UnaryExpression() { ret = new UnaryExpr(ret, op); }
	|
	  LOOKAHEAD( CastLookahead() )
	  ret = CastExpression()
	|
	  ret = PostfixExpression()
  )
  { return ret; }
}

// 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("(" Type() "[")
  "(" Type() "[" "]"
|
  "(" Type() ")" ( "~" | "!" | "(" |  | "this" | "super" | "new" | Literal() )
}

Expression PostfixExpression():
{
	Expression ret;
	UnaryExpr.Operator op;
}
{
  ret = PrimaryExpression() 
  [
  	LOOKAHEAD(2)  
    ( "++" { op = UnaryExpr.Operator.posIncrement; } | 
      "--" { op = UnaryExpr.Operator.posDecrement; }
    ) { ret = new UnaryExpr(ret, op); }
  ]
  { return ret; }
}

Expression CastExpression():
{
	Expression ret;
	Type type;
}
{
  (
	  LOOKAHEAD("(" PrimitiveType())
	  "(" type = Type() ")" ret = UnaryExpression() { ret = new CastExpr(ret, type); }
	|
	  "(" type = Type() ")" ret = UnaryExpressionNotPlusMinus() { ret = new CastExpr(ret, type); }
  )
  { return ret; }
}

Expression PrimaryExpression():
{
	Expression ret;
	Expression inner;
}
{
  ret = PrimaryPrefix() ( LOOKAHEAD(2) ret = PrimarySuffix(ret) )*
  { return ret; }
}

Expression PrimaryPrefix():
{
	Expression ret;
	NameExpr name;
	Type type;
}
{
  (
	  ret = Literal()
	|
	  "this" { ret = ThisExpr.SINGLETON; }
	|
	  "super" "."  { ret = new SuperMemberAccessExpr(token.image); }
	|
	  "(" ret = Expression() ")" { ret = new EnclosedExpr(ret); }
	|
	  ret = AllocationExpression(null)
	|
	  LOOKAHEAD( ResultType() "." "class" )
	  type = ResultType() "." "class" { ret = new ClassExpr(type); }
	|
	  ret = Name()
  )
  { return ret; }
}

Expression PrimarySuffix(Expression scope):
{
	Expression ret;
	List list = null;
}
{
  (
  	"."
  	(
		"this" { ret = new ThisExpr(scope); }
	  |
	  	"super" { ret = new SuperExpr(scope); }
	  |
	  	ret = AllocationExpression(scope)
	  |
	  	[ list = TypeArguments() ]  { ret = new FieldAccessExpr(scope, list, token.image); }
	)
	|
	  "[" ret = Expression() "]" { ret = new ArrayAccessExpr(scope, ret); }
	|
	  list = Arguments() { ret = new MethodCallExpr(scope, list); }
  )
  { return ret; }
}

Expression Literal():
{
	Expression ret;
}
{
  (
	   {
	  	try {
	  		ret = LiteralExpr.newIntegerLiteral(token.image);
	  	} catch (NumberFormatException e) {
	  		throw new ParseException(token, "Integer literal out of range");
	  	}	
	  }
	|
	   { 
	  	try {
	  		ret = LiteralExpr.newLongLiteral(token.image);
	  	} catch (NumberFormatException e) {
	  		throw new ParseException(token, "Long literal out of range");
	  	}	
	  }
	|
	    {
	  	try { 
	  		ret = new LiteralExpr(Double.parseDouble(token.image));
	  	} catch (NumberFormatException e) {
	  		throw new ParseException(token, "Invalid floating literal format");
	  	}
	  }
	|
	    { 
	  	try { 
	  		ret = LiteralExpr.newCharLiteral(token.image);
	  	} catch (NumberFormatException e) {
	  		throw new ParseException(token, "Invalid char literal format");
	  	}
	  }
	|
	    { ret = new LiteralExpr(token.image.substring(1, token.image.length()-1)); }
	|
	  ret = BooleanLiteral()
	|
	  ret = NullLiteral()
  )
  { return ret; }
}

Expression BooleanLiteral():
{
	Expression ret;
}
{
  (
	  "true" { ret = new LiteralExpr(Boolean.TRUE); }
	|
	  "false" { ret = new LiteralExpr(Boolean.FALSE); }
  )
  { return ret; }
}

Expression NullLiteral():
{}
{
  "null"
  { return new LiteralExpr(null); }
}

List Arguments():
{
	List ret = null;
}
{
  "(" [ ret = ArgumentList() ] ")"
  { return ret; }
}

List ArgumentList():
{
	List ret = new LinkedList();
	Expression expr;
}
{
  expr = Expression() { ret.add(expr); } ( "," expr = Expression() { ret.add(expr); } )*
  { return ret; }
}

Expression AllocationExpression(Expression scope):
{
	Expression ret;
	Type type;
	Object[] arr = null;
	List typeArgs = null;
	List anonymousBody = null;
	List args;
}
{
  (
	  LOOKAHEAD(2)
	  "new" type = PrimitiveType() arr = ArrayDimsAndInits()
	  { 
	  	if (arr[0] instanceof Integer) {
		  	ret = new ArrayCreationExpr(type, null, ((Integer)arr[0]).intValue(), (ArrayInitializerExpr)arr[1]);
	  	} else {
		  	ret = new ArrayCreationExpr(type, null, (List)arr[0], ((Integer)arr[1]).intValue());
	  	}
	  }
	|
	  "new" type = ClassOrInterfaceType() [ typeArgs = TypeArguments() ]
	    (
	      arr = ArrayDimsAndInits()
		  {
		  	if (arr[0] instanceof Integer) {
			  	ret = new ArrayCreationExpr(type, typeArgs, ((Integer)arr[0]).intValue(), (ArrayInitializerExpr)arr[1]);
		  	} else {
			  	ret = new ArrayCreationExpr(type, typeArgs, (List)arr[0], ((Integer)arr[1]).intValue());
		  	}
		  }
	    |
	      args = Arguments() [ LOOKAHEAD(2) anonymousBody = ClassOrInterfaceBody(false) ]
	      { ret = new ObjectCreationExpr(scope, (ClassOrInterfaceType) type, typeArgs, args, anonymousBody); }
	    )
  )
  { return ret; }
}

/*
 * The third LOOKAHEAD specification below is to parse to PrimarySuffix
 * if there is an expression between the "[...]".
 */
Object[] ArrayDimsAndInits():
{
	Object[] ret = new Object[2];
	Expression expr;
	List inits = null;
	int i = 0;
}
{
  (
	  LOOKAHEAD(2)
	  ( LOOKAHEAD(2) "[" expr = Expression() { inits = add(inits, expr); } "]" )+ ( LOOKAHEAD(2) "[" "]" { i++; } )* { ret[0] = inits; ret[1] = new Integer(i); }
	|
	  ( "[" "]" { i++; } )+ expr = ArrayInitializer() { ret[0] = new Integer(i); ret[1] = expr; }
  )
  { return ret; }
}


/*
 * Statement syntax follows.
 */

Statement Statement():
{
	Statement ret;
}
{
  (
	  LOOKAHEAD(2)
	  ret = LabeledStatement()
	|
	  ret = AssertStatement()
	|
	  ret = Block()
	|
	  ret = EmptyStatement()
	|
	  ret = StatementExpression()
	|
	  ret = SwitchStatement()
	|
	  ret = IfStatement()
	|
	  ret = WhileStatement()
	|
	  ret = DoStatement()
	|
	  ret = ForStatement()
	|
	  ret = BreakStatement()
	|
	  ret = ContinueStatement()
	|
	  ret = ReturnStatement()
	|
	  ret = ThrowStatement()
	|
	  ret = SynchronizedStatement()
	|
	  ret = TryStatement()
  )
  { return ret; }
}

AssertStmt AssertStatement():
{
	Expression check;
	Expression msg = null;
}
{
  "assert" check = Expression() [ ":" msg = Expression() ] ";"
  { return new AssertStmt(check, msg);  }
}

LabeledStmt LabeledStatement():
{
	String label;
	Statement stmt;
}
{
   { label = token.image; } ":" stmt = Statement()
  { return new LabeledStmt(label, stmt); }
}

BlockStmt Block():
{
	List stmts;
}
{
  "{" stmts = Statements() "}"
  { return new BlockStmt(stmts); }
}

/*
 * Classes inside block stametents can only be abstract or final. The semantic must check it. 
 */
Statement BlockStatement():
{
	Statement ret;
	Expression expr;
	ClassOrInterfaceDeclaration typeDecl;
	Modifier modifier;
}
{
  (
	  LOOKAHEAD( Modifiers() ("class" | "interface") )
	  modifier = Modifiers()
	  typeDecl = ClassOrInterfaceDeclaration(modifier) { ret = new TypeDeclarationStmt(typeDecl); }
	|
  	  LOOKAHEAD(VariableDeclarationExpression() )
	  expr = VariableDeclarationExpression() { ret = new ExpressionStmt(expr); } ";"
    |
	  ret = Statement()
  )
  { return ret; }
}

VariableDeclarationExpr VariableDeclarationExpression():
{
	Modifier modifier;
	Type type;
	List vars = new LinkedList();
	VariableDeclarator var;
}
{
  modifier = Modifiers() type = Type() var = VariableDeclarator() { vars.add(var); } ( "," var = VariableDeclarator() { vars.add(var); } )*
  { return new VariableDeclarationExpr(modifier.modifiers, modifier.annotations, type, vars); }
}

EmptyStmt EmptyStatement():
{}
{
  ";"
  { return EmptyStmt.SINGLETON; }
}

ExpressionStmt 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.
 */
{
	Expression expr;
	AssignExpr.Operator op;
	Expression value;
}
{
  (
	  expr = PreIncrementExpression()
	|
	  expr = PreDecrementExpression()
	|
	  expr = PrimaryExpression()
	  [
	    "++" { expr = new UnaryExpr(expr, UnaryExpr.Operator.posIncrement);  }
	  |
	    "--" { expr = new UnaryExpr(expr, UnaryExpr.Operator.posDecrement);  }
	  |
	    op = AssignmentOperator() value = Expression() { expr = new AssignExpr(expr, value, op); }
	  ]
  )
  ";"
  { return new ExpressionStmt(expr); }
}

SwitchStmt SwitchStatement():
{
	Expression selector;
	SwitchEntryStmt entry;
	List entries = null;
}
{
  "switch" "(" selector = Expression() ")" "{"
    ( entry = SwitchEntry() { entries = add(entries, entry); } )*
  "}"
  
  { return new SwitchStmt(selector, entries); }
}

SwitchEntryStmt SwitchEntry():
{
	Expression label = null;
	List stmts;
}
{
  (
	  "case" label = Expression()
	|
	  "default"
  )
  ":" stmts = Statements()
  
  { return new SwitchEntryStmt(label, stmts); }
}

IfStmt 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.
 */
{
	Expression condition;
	Statement thenStmt;
	Statement elseStmt = null;
}
{
  "if" "(" condition = Expression() ")" thenStmt = Statement() [ LOOKAHEAD(1) "else" elseStmt = Statement() ]
  { return new IfStmt(condition, thenStmt, elseStmt); }
}

WhileStmt WhileStatement():
{
	Expression condition;
	Statement body;
}
{
  "while" "(" condition = Expression() ")" body = Statement()
  { return new WhileStmt(condition, body); }
}

DoStmt DoStatement():
{
	Expression condition;
	Statement body;
}
{
  "do" body = Statement() "while" "(" condition = Expression() ")" ";"
  { return new DoStmt(condition, body); }
}

Statement ForStatement():
{
	String id = null;
	VariableDeclarationExpr varExpr = null;
	Expression expr = null;
	List init = null;
	List update = null;
	Statement body;
}
{
  "for" "("

  (
      LOOKAHEAD(VariableDeclarationExpression() ":")
      varExpr = VariableDeclarationExpression() ":" expr = Expression() 
    |
     [ init = ForInit() ] ";" [ expr = Expression() ] ";" [ update = ForUpdate() ]
  )

  ")" body = Statement()
  
  {
  	if (varExpr != null) {
  		return new ForeachStmt(varExpr, expr, body);
  	}
	return new ForStmt(init, expr, update, body);
  }
}

List ForInit():
{
	List ret;
	Expression expr;
}
{
  (
	  LOOKAHEAD( Modifiers() Type()  )
	  expr = VariableDeclarationExpression() { ret = new LinkedList(); ret.add(expr); }
	|
	  ret = ExpressionList()
  )
  { return ret; }
}

List ExpressionList():
{
	List ret = new LinkedList();
	Expression expr;
}
{
  expr = Expression() { ret.add(expr); } ( "," expr = Expression()  { ret.add(expr); } )*
  
  { return ret; }
}

List ForUpdate():
{
	List ret;
}
{
  ret = ExpressionList()
  
  { return ret; }
}

BreakStmt BreakStatement():
{
	String id = null;
}
{
  "break" [  { id = token.image; } ] ";"
  { return id == null ? BreakStmt.SINGLETON : new BreakStmt(id); }
}

ContinueStmt ContinueStatement():
{
	String id = null;
}
{
  "continue" [  { id = token.image; } ] ";"
  { return id == null ? ContinueStmt.SINGLETON : new ContinueStmt(id); }
}

ReturnStmt ReturnStatement():
{
	Expression expr = null;
}
{
  "return" [ expr = Expression() ] ";"
  { return new ReturnStmt(expr); }
}

ThrowStmt ThrowStatement():
{
	Expression expr;
}
{
  "throw" expr = Expression() ";"
  { return new ThrowStmt(expr); }
}

SynchronizedStmt SynchronizedStatement():
{
	Expression expr;
	BlockStmt block;
}
{
  "synchronized" "(" expr = Expression() ")" block = Block()
  { return new SynchronizedStmt(expr, block); }
}

TryStmt TryStatement():
/*
 * Semantic check required here to make sure that at least one
 * finally/catch is present.
 */
{
	BlockStmt tryBlock;
	BlockStmt finallyBlock = null;
	List catchs = null;
	Parameter except;
	BlockStmt catchBlock;
}
{
  "try" tryBlock = Block()
  ( "catch" "(" except = FormalParameter() ")" catchBlock = Block() { catchs = add(catchs, new CatchClause(except, catchBlock)); } )*
  [ "finally" finallyBlock = Block() ]
  { return new TryStmt(tryBlock, catchs, finallyBlock); }
}

/* We use productions to match >>>, >> and > so that we can keep the
 * type declaration syntax with generics clean
 */

void RUNSIGNEDSHIFT():
{}
{
  ( LOOKAHEAD({ getToken(1).kind == GT &&
                ((Token.GTToken)getToken(1)).realKind == RUNSIGNEDSHIFT} )
   ">" ">" ">"
  )
}

void RSIGNEDSHIFT():
{}
{
  ( LOOKAHEAD({ getToken(1).kind == GT &&
                ((Token.GTToken)getToken(1)).realKind == RSIGNEDSHIFT} )
  ">" ">"
  )
}

/* Annotation syntax follows. */

AnnotationExpr Annotation():
{
	AnnotationExpr ret;
}
{
  (
	   LOOKAHEAD( "@" Name() "(" (  "=" | ")" ))
	   ret = NormalAnnotation()
	 |
	   LOOKAHEAD( "@" Name() "(" )
	   ret = SingleMemberAnnotation()
	 |
	   ret = MarkerAnnotation()
  )
  { return ret; }
}

NormalAnnotationExpr NormalAnnotation():
{
	NameExpr name;
	List pairs = null;
}
{
   "@" name = Name() "(" [ pairs = MemberValuePairs() ] ")"
   { return new NormalAnnotationExpr(name, pairs); }
}

MarkerAnnotationExpr MarkerAnnotation():
{
	NameExpr name;
}
{
  "@" name = Name()
  { return new MarkerAnnotationExpr(name); }
}

SingleMemberAnnotationExpr SingleMemberAnnotation():
{
	NameExpr name;
	Expression memberVal;
}
{
  "@" name = Name() "(" memberVal = MemberValue() ")"
  { return new SingleMemberAnnotationExpr(name, memberVal); }
}

List MemberValuePairs():
{
	List ret = new LinkedList();
	MemberValuePair pair;
}
{
   pair = MemberValuePair() { ret.add(pair); } ( "," pair = MemberValuePair() { ret.add(pair); } )*
   { return ret; }
}

MemberValuePair MemberValuePair():
{
	String name;
	Expression value;
}
{
     { name = token.image; } "=" value = MemberValue()
    { return new MemberValuePair(name, value); } 
}

Expression MemberValue():
{
	Expression ret;
}
{
  (
	   ret = Annotation()
	 |
	   ret = MemberValueArrayInitializer()
	 |
	   ret = ConditionalExpression()
  )
  { return ret; }
}

Expression  MemberValueArrayInitializer():
{
	List ret = new LinkedList();
	Expression member;
}
{
  "{" member = MemberValue() { ret.add(member); } ( LOOKAHEAD(2) "," member = MemberValue() { ret.add(member); } )* [ "," ] "}"
  { return new ArrayInitializerExpr(ret); }
}


/* Annotation Types. */

AnnotationDeclaration AnnotationTypeDeclaration(Modifier modifier):
{
	String name;
	List members;
}
{
  "@" "interface"  { name = token.image; } members = AnnotationTypeBody()
  
  { return new AnnotationDeclaration(modifier.modifiers, modifier.annotations, name, members); }
}

List AnnotationTypeBody():
{
	List ret = null;
	BodyDeclaration member;
}
{
  "{" ( member = AnnotationBodyDeclaration() { ret = add(ret, member); } )* "}"
  
  { return ret; }
}

BodyDeclaration AnnotationBodyDeclaration():
{
   Modifier modifier;
   BodyDeclaration ret;
}
{
  modifier = Modifiers()
  (
    (
	   LOOKAHEAD(Type()  "(")
	   ret = AnnotationTypeMemberDeclaration(modifier)
	  |
	   ret = ClassOrInterfaceDeclaration(modifier)
	  |
	   ret = EnumDeclaration(modifier)
	  |
	   ret = AnnotationTypeDeclaration(modifier)
	  |
	   ret = FieldDeclaration(modifier)
	 )
	 |
	   ";" { ret = EmptyTypeDeclaration.SINGLETON; }
  )
  { return ret; }
}

AnnotationMemberDeclaration AnnotationTypeMemberDeclaration(Modifier modifier):
{
	Type type;
	String name;
	Expression defaultVal = null;
}
{
	type = Type()  { name = token.image; } "(" ")" [ defaultVal = DefaultValue() ] ";"
	
	{ return new AnnotationMemberDeclaration(modifier.modifiers, modifier.annotations, type, name, defaultVal); }
}

Expression DefaultValue():
{
	Expression ret;
}
{
  "default" ret = MemberValue()
  { return ret; }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy