/* Copyright (c) 2006, Sun Microsystems, Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Sun Microsystems, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */


options {
  JAVA_UNICODE_ESCAPE = true;
}

PARSER_BEGIN(JavaParser)

public class JavaParser {

  public static void main(String args[]) {
    JavaParser parser;
    if (args.length == 0) {
      System.out.println("Java Parser Version 1.1:  Reading from standard input . . .");
      parser = new JavaParser(System.in);
    } else if (args.length == 1) {
      System.out.println("Java Parser Version 1.1:  Reading from file " + args[0] + " . . .");
      try {
        parser = new JavaParser(new java.io.FileInputStream(args[0]));
      } catch (java.io.FileNotFoundException e) {
        System.out.println("Java Parser Version 1.1:  File " + args[0] + " not found.");
        return;
      }
    } else {
      System.out.println("Java Parser Version 1.1:  Usage is one of:");
      System.out.println("         java JavaParser < inputfile");
      System.out.println("OR");
      System.out.println("         java JavaParser inputfile");
      return;
    }
    try {
      parser.CompilationUnit();
      System.out.println("Java Parser Version 1.1:  Java program parsed successfully.");
    } catch (ParseException e) {
      System.out.println(e.getMessage());
      System.out.println("Java Parser Version 1.1:  Encountered errors during parse.");
    }
  }

  // Semantic lookahead rules follow.

  // implements:  LOOKAHEAD( ( "abstract" | "final" | "public" )* "class" )
  static boolean isClassDeclaration() {
    int curTok = 1;
    Token tok;
    while (true) {
      tok = getToken(curTok);
      switch (tok.kind) {
      case ABSTRACT:
      case FINAL:
      case PUBLIC:
        curTok++;
        break;
      case CLASS:
        return true;
      default:
        return false;
      }
    }
  }

  // implements:  LOOKAHEAD(2)  for Initializer()
  static boolean isInitializer() {
    Token tok = getToken(1);
    if (tok.kind == LBRACE) return true;
    if (tok.kind == STATIC) {
      tok = getToken(2);
      if (tok.kind == LBRACE) return true;
    }
    return false;
  }

  // implements:  LOOKAHEAD( ( "static" | "abstract" | "final" | "public" | "protected" | "private" )* "class" )
  static boolean isNestedClassDeclaration() {
    int curTok = 1;
    Token tok;
    while (true) {
      tok = getToken(curTok);
      switch (tok.kind) {
      case STATIC:
      case ABSTRACT:
      case FINAL:
      case PUBLIC:
      case PROTECTED:
      case PRIVATE:
        curTok++;
        break;
      case CLASS:
        return true;
      default:
        return false;
      }
    }
  }

  // implements:  LOOKAHEAD( ( "static" | "abstract" | "final" | "public" | "protected" | "private" )* "interface" )
  static boolean isNestedInterfaceDeclaration() {
    int curTok = 1;
    Token tok;
    while (true) {
      tok = getToken(curTok);
      switch (tok.kind) {
      case STATIC:
      case ABSTRACT:
      case FINAL:
      case PUBLIC:
      case PROTECTED:
      case PRIVATE:
        curTok++;
        break;
      case INTERFACE:
        return true;
      default:
        return false;
      }
    }
  }

  // implements:  LOOKAHEAD( [ "public" | "protected" | "private" ] Name() "(" )
  static boolean isConstructorDeclaration() {
    int curTok = 1;
    Token tok;
    tok = getToken(1);
    switch (tok.kind) {
    case PUBLIC:
    case PROTECTED:
    case PRIVATE:
      curTok = 2;
    }
    tok = getToken(curTok++);
    if (tok.kind != IDENTIFIER) return false;
    while (true) {
      tok = getToken(curTok++);
      if (tok.kind == LPAREN) return true;
      if (tok.kind != DOT) return false;
      tok = getToken(curTok++);
      if (tok.kind != IDENTIFIER) return false;
    }
  }

  // Returns true if the next set of tokens cannot be a field declaration.
  // Returns false if the next set of tokens cannot be a method declaration.
  // Note how this method is used in the grammar.  We don't have to do a
  // comprehensive check like we have done in the lookahead methods above.
  // This show (therefore) another way you can implement lookahead methods.
  // The way we do it is to see if we can find a "(" before either a "=" or
  // a ";", in which case we return true.
  static boolean isMethodDeclaration() {
    int curTok = 1;
    Token tok;
    while (true) {
      tok = getToken(curTok++);
      switch (tok.kind) {
      case LPAREN:
        return true;
      case ASSIGN:
      case SEMICOLON:
      case EOF:
        return false;
      }
    }
  }

  // Checks that there is a "," and then there is no "}" following that.
  static boolean moreVariableInitializers() {
    return getToken(1).kind == COMMA && getToken(2).kind != RBRACE;
  }

  // Checks that this is a constructor invocation as opposed to a block
  // statement.
  static boolean isConstructorInvocation() {
    int curTok = 1;
    Token tok = getToken(1);
    switch (tok.kind) {
    case THIS:
    case SUPER:
      // We are assuming here that if the statement starts with "this"
      // or "super", and the next token is "(", then it has to be a
      // constructor invocation.
      return getToken(2).kind == LPAREN;
    case STRING_LITERAL:
    case LPAREN:
    case NEW:
    case IDENTIFIER:
      // Now move across tokens until the end of the statement - the
      // first semicolon not nested within any kind of parentheses.
      // If a "super(" is matched also not nested and before this
      // semicolon, we return true.  Otherwise return false.
      int nestingLevel = 0;
      while (true) {
        tok = getToken(curTok++);
        switch (tok.kind) {
        case SEMICOLON:
          if (nestingLevel == 0) {
            return false;
          }
          break;
        case SUPER:
          if (nestingLevel == 0) {
            return getToken(curTok).kind == LPAREN;
          }
          break;
        case LPAREN:
        case LBRACE:
        case LBRACKET:
          nestingLevel++;
          break;
        case RPAREN:
        case RBRACE:
        case RBRACKET:
          nestingLevel--;
          break;
        case EOF:
          return false;
        }
      }
    default:
      return false;
    }
  }

  // Returns true if this is a primitive type (or an array of primitive
  // type) cast.
  static boolean isPrimitiveTypeCast() {
    if (getToken(1).kind != LPAREN) return false;
    Token tok = getToken(2);
    switch (tok.kind) {
    case BOOLEAN:
    case CHAR:
    case BYTE:
    case SHORT:
    case INT:
    case LONG:
    case FLOAT:
    case DOUBLE:
      return true;
    }
    return false;
  }

  // Returns true if this is a type cast.
  static boolean isTypeCast() {
    if (isPrimitiveTypeCast()) return true;
    if (getToken(1).kind != LPAREN) return false;
    int curTok = 2;
    Token tok = getToken(curTok++);
    if (tok.kind != IDENTIFIER) return false;
    while (true) {
      tok = getToken(curTok++);
      if (tok.kind != DOT) break;
      tok = getToken(curTok++);
      if (tok.kind != IDENTIFIER) return false;
    }
    if (tok.kind == RPAREN) {
      tok = getToken(curTok);
      switch (tok.kind) {
      case TILDE:
      case BANG:
      case LPAREN:
      case IDENTIFIER:
      case THIS:
      case SUPER:
      case NEW:
      case INTEGER_LITERAL:
      case FLOATING_POINT_LITERAL:
      case CHARACTER_LITERAL:
      case STRING_LITERAL:
      case TRUE:
      case FALSE:
      case NULL:
        return true;
      }
      return false;
    } else {
      if (tok.kind != LBRACKET) return false;
      tok = getToken(curTok);
      if (tok.kind != RBRACKET) return false;
      return true;
    }
  }

  // Distinguishes between ClassSelector and Name.
  static boolean isClassSelector() {
    int curTok = 1;
    Token tok = getToken(curTok++);
    if (tok.kind != IDENTIFIER) return true;
    while (true) {
      tok = getToken(curTok++);
      while (tok.kind == LBRACKET) {
        // A simple loop to accept "[]"s.  We are a little sloppy
        // in that we don't require it to be at the end, but then
        // this is only a lookahead check.
        tok = getToken(curTok++);
        if (tok.kind != RBRACKET) return false;
        tok = getToken(curTok++);
      }
      if (tok.kind != DOT) return false;
      tok = getToken(curTok++);
      if (tok.kind == CLASS) return true;
      if (tok.kind != IDENTIFIER) return false;
    }
  }

  // implements:  LOOKAHEAD([ "final" ] Type() <IDENTIFIER>)
  static boolean isLocalVariableDeclaration() {
    int curTok = 1;
    Token tok = getToken(curTok++);
    if (tok.kind == FINAL) tok = getToken(curTok++);
    switch (tok.kind) {
    case BOOLEAN:
    case CHAR:
    case BYTE:
    case SHORT:
    case INT:
    case LONG:
    case FLOAT:
    case DOUBLE:
      tok = getToken(curTok++);
      break;
    case IDENTIFIER:
      while (true) {
        tok = getToken(curTok++);
        if (tok.kind != DOT) break;
        tok = getToken(curTok++);
        if (tok.kind != IDENTIFIER) return false;
      }
      break;
    default:
      return false;
    }
    while (tok.kind == LBRACKET) {
      tok = getToken(curTok++);
      if (tok.kind != RBRACKET) return false;
      tok = getToken(curTok++);
    }
    return tok.kind == IDENTIFIER;
  }

  static boolean isPrimarySuffix() {
    Token tok = getToken(1);
    if (tok.kind == LPAREN || tok.kind == LBRACKET) return true;
    if (tok.kind == DOT) {
      tok = getToken(2);
      switch (tok.kind) {
      case THIS:
      case NEW:
      case IDENTIFIER:
        return true;
      }
    }
    return false;
  }

}

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
}

<IN_SINGLE_LINE_COMMENT>
SPECIAL_TOKEN :
{
  <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT
}

<IN_FORMAL_COMMENT>
SPECIAL_TOKEN :
{
  <FORMAL_COMMENT: "*/" > : DEFAULT
}

<IN_MULTI_LINE_COMMENT>
SPECIAL_TOKEN :
{
  <MULTI_LINE_COMMENT: "*/" > : DEFAULT
}

<IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
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" >
}

/* LITERALS */

TOKEN :
{
  < INTEGER_LITERAL:
        <DECIMAL_LITERAL> (["l","L"])?
      | <HEX_LITERAL> (["l","L"])?
      | <OCTAL_LITERAL> (["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"])* (<EXPONENT>)? (["f","F","d","D"])?
      | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
      | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
      | (["0"-"9"])+ (<EXPONENT>)? ["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> (<LETTER>|<DIGIT>)* >
|
  < #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() )*
  (
    LOOKAHEAD(1, <ABSTRACT> | <CLASS> | <FINAL> | <INTERFACE> | <PUBLIC> | <SEMICOLON>)
    TypeDeclaration()
  )*
  <EOF>
}

void PackageDeclaration() :
{}
{
  "package" Name() ";"
}

void ImportDeclaration() :
{}
{
  "import" Name() [ "." "*" ] ";"
}

void TypeDeclaration() :
{}
{
  LOOKAHEAD( { isClassDeclaration() } )
  ClassDeclaration()
|
  InterfaceDeclaration()
|
  ";"
}


/*
 * Declaration syntax follows.
 */

void ClassDeclaration() :
{}
{
  ( "abstract" | "final" | "public" )*
  UnmodifiedClassDeclaration()
}

void UnmodifiedClassDeclaration() :
{}
{
  "class" <IDENTIFIER> [ "extends" Name() ] [ "implements" NameList() ]
  ClassBody()
}

void ClassBody() :
{}
{
  "{"
    (
      LOOKAHEAD(1, <ABSTRACT> | <BOOLEAN> | <BYTE> | <CHAR> | <CLASS> | <DOUBLE> |
                   <FINAL> | <FLOAT> | <INT> | <INTERFACE> | <LONG> | <NATIVE> |
                   <PRIVATE> | <PROTECTED> | <PUBLIC> | <SHORT> | <STATIC> |
                   <SYNCHRONIZED> | <TRANSIENT> | <VOID> | <VOLATILE> | <IDENTIFIER> |
                   <LBRACE>)
      ClassBodyDeclaration()
    )*
  "}"
}

void NestedClassDeclaration() :
{}
{
  ( "static" | "abstract" | "final" | "public" | "protected" | "private" )*
  UnmodifiedClassDeclaration()
}

void ClassBodyDeclaration() :
{}
{
  LOOKAHEAD( { isInitializer() } )
  Initializer()
|
  LOOKAHEAD( { isNestedClassDeclaration() } )
  NestedClassDeclaration()
|
  LOOKAHEAD( { isNestedInterfaceDeclaration() } )
  NestedInterfaceDeclaration()
|
  LOOKAHEAD( { isConstructorDeclaration() } )
  ConstructorDeclaration()
|
  LOOKAHEAD( { isMethodDeclaration() } )
  MethodDeclaration()
|
  FieldDeclaration()
}

void InterfaceDeclaration() :
{}
{
  ( "abstract" | "public" )*
  UnmodifiedInterfaceDeclaration()
}

void NestedInterfaceDeclaration() :
{}
{
  ( "static" | "abstract" | "final" | "public" | "protected" | "private" )*
  UnmodifiedInterfaceDeclaration()
}

void UnmodifiedInterfaceDeclaration() :
{}
{
  "interface" <IDENTIFIER> [ "extends" NameList() ]
  "{"
    (
      LOOKAHEAD(1, <ABSTRACT> | <BOOLEAN> | <BYTE> | <CHAR> | <CLASS> | <DOUBLE> |
                   <FINAL> | <FLOAT> | <INT> | <INTERFACE> | <LONG> | <NATIVE> |
                   <PRIVATE> | <PROTECTED> | <PUBLIC> | <SHORT> | <STATIC> |
                   <SYNCHRONIZED> | <TRANSIENT> | <VOID> | <VOLATILE> | <IDENTIFIER>)
      InterfaceMemberDeclaration()
    )*
  "}"
}

void InterfaceMemberDeclaration() :
{}
{
  LOOKAHEAD( { isNestedClassDeclaration() } )
  NestedClassDeclaration()
|
  LOOKAHEAD( { isNestedInterfaceDeclaration() } )
  NestedInterfaceDeclaration()
|
  LOOKAHEAD( { isMethodDeclaration() } )
  MethodDeclaration()
|
  FieldDeclaration()
}

void FieldDeclaration() :
{}
{
  ( "public" | "protected" | "private" | "static" | "final" | "transient" | "volatile" )*
  Type() VariableDeclarator() ( "," VariableDeclarator() )* ";"
}

void VariableDeclarator() :
{}
{
  VariableDeclaratorId() [ "=" VariableInitializer() ]
}

void VariableDeclaratorId() :
{}
{
  <IDENTIFIER> ( "[" "]" )*
}

void VariableInitializer() :
{}
{
  ArrayInitializer()
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> | <INT> |
               <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> | <TRUE> |
               <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
               <BANG> | <TILDE> | <INCR> | <DECR> | <PLUS> | <MINUS>)
  Expression()
}

void ArrayInitializer() :
{}
{
  "{"
    [
      LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> | <INT> |
                   <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> | <TRUE> |
                   <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                   <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
                   <LBRACE> | <BANG> | <TILDE> | <INCR> | <DECR> | <PLUS> | <MINUS>)
      VariableInitializer()
      ( LOOKAHEAD( { getToken(1).kind == COMMA && getToken(2).kind != RBRACE } )
        "," VariableInitializer()
      )*
    ]
    [ "," ]
  "}"
}

void MethodDeclaration() :
{}
{
  ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" )*
  ResultType() MethodDeclarator() [ "throws" NameList() ]
  ( Block() | ";" )
}

void MethodDeclarator() :
{}
{
  <IDENTIFIER> FormalParameters() ( "[" "]" )*
}

void FormalParameters() :
{}
{
  "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
}

void FormalParameter() :
{}
{
  [ "final" ] Type() VariableDeclaratorId()
}

void ConstructorDeclaration() :
{}
{
  [ "public" | "protected" | "private" ]
  <IDENTIFIER> FormalParameters() [ "throws" NameList() ]
  "{"
    [ LOOKAHEAD( { isConstructorInvocation() } ) ExplicitConstructorInvocation() ]
    (
      LOOKAHEAD(1, <BOOLEAN> | <BREAK> | <BYTE> | <CHAR> | <CLASS> | <CONTINUE> |
                   <DO> | <DOUBLE> | <FALSE> | <FINAL> | <FLOAT> | <FOR> | <IF> |
                   <INT> | <LONG> | <NEW> | <NULL> | <RETURN> | <SHORT> | <SUPER> |
                   <SWITCH> | <SYNCHRONIZED> | <THIS> | <THROW> | <TRUE> | <TRY> |
                   <VOID> | <WHILE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                   <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
                   <LBRACE> | <SEMICOLON> | <INCR> | <DECR>)
      BlockStatement()
    )*
  "}"
}

void ExplicitConstructorInvocation() :
{}
{
  LOOKAHEAD( { getToken(1).kind == THIS && getToken(2).kind == LPAREN } )
  "this" Arguments() ";"
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> | <INT> |
               <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> | <TRUE> |
               <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN>)
  [
    LOOKAHEAD( { getToken(1).kind != SUPER || getToken(2).kind != LPAREN } )
    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() :
{}
{
  <IDENTIFIER>
  ( LOOKAHEAD( { getToken(1).kind == DOT && getToken(2).kind == IDENTIFIER } )
    "." <IDENTIFIER>
  )*
}

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()
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
               <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
               <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> |
               <LPAREN> | <BANG> | <TILDE>)
  UnaryExpressionNotPlusMinus()
}

void PreIncrementExpression() :
{}
{
  "++" PrimaryExpression()
}

void PreDecrementExpression() :
{}
{
  "--" PrimaryExpression()
}

void UnaryExpressionNotPlusMinus() :
{}
{
  ( "~" | "!" ) UnaryExpression()
|
  LOOKAHEAD( { isTypeCast() } )
  CastExpression()
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
               <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
               <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN>)
  PostfixExpression()
}

void PostfixExpression() :
{}
{
  PrimaryExpression() [ "++" | "--" ]
}

void CastExpression() :
{}
{
  LOOKAHEAD( { isPrimitiveTypeCast() } )
  "(" Type() ")" UnaryExpression()
|
  "(" Type() ")" UnaryExpressionNotPlusMinus()
}

void PrimaryExpression() :
{}
{
  PrimaryPrefix() ( LOOKAHEAD( { isPrimarySuffix() } ) PrimarySuffix() )*
}

void PrimaryPrefix() :
{}
{
  Literal()
|
  "this"
|
  "super" "." <IDENTIFIER>
|
  "(" Expression() ")"
|
  LOOKAHEAD(1, <NEW>)
  AllocationExpression()
|
  LOOKAHEAD( { isClassSelector() } )
  ResultType() "." "class"
|
  Name()
}

void PrimarySuffix() :
{}
{
  LOOKAHEAD( { getToken(1).kind == DOT && getToken(2).kind == THIS } )
  "." "this"
|
  LOOKAHEAD( { getToken(1).kind == DOT && getToken(2).kind == NEW } )
  "." AllocationExpression()
|
  "[" Expression() "]"
|
  "." <IDENTIFIER>
|
  Arguments()
}

void Literal() :
{}
{
  <INTEGER_LITERAL>
|
  <FLOATING_POINT_LITERAL>
|
  <CHARACTER_LITERAL>
|
  <STRING_LITERAL>
|
  BooleanLiteral()
|
  NullLiteral()
}

void BooleanLiteral() :
{}
{
  "true"
|
  "false"
}

void NullLiteral() :
{}
{
  "null"
}

void Arguments() :
{}
{
  "("
    [
      LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
                   <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
                   <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                   <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
                   <BANG> | <TILDE> | <INCR> | <DECR> | <PLUS> | <MINUS>)
      ArgumentList()
    ]
  ")"
}

void ArgumentList() :
{}
{
  Expression() ( "," Expression() )*
}

void AllocationExpression() :
{}
{
  LOOKAHEAD( { getToken(2).kind != IDENTIFIER } )
  "new" PrimitiveType() ArrayDimsAndInits()
|
  "new" Name()
    (
      LOOKAHEAD(1, <LBRACKET>)
      ArrayDimsAndInits()
    |
      Arguments() [ ClassBody() ]
    )
}

/*
 * The third LOOKAHEAD specification below is to parse to PrimarySuffix
 * if there is an expression between the "[...]".
 */
void ArrayDimsAndInits() :
{}
{
  LOOKAHEAD( { getToken(2).kind != RBRACKET } )
  ( LOOKAHEAD( { getToken(1).kind == LBRACKET && getToken(2).kind != RBRACKET } )
    "[" Expression() "]"
  )+
  ( LOOKAHEAD( { getToken(1).kind == LBRACKET && getToken(2).kind == RBRACKET } )
    "[" "]"
  )*
|
  ( "[" "]" )+ ArrayInitializer()
}


/*
 * Statement syntax follows.
 */

void Statement() :
{}
{
  LOOKAHEAD( { getToken(1).kind == IDENTIFIER && getToken(2).kind == COLON } )
  LabeledStatement()
|
  Block()
|
  EmptyStatement()
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
               <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
               <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> |
               <LPAREN> | <INCR> | <DECR>)
  StatementExpression() ";"
|
  SwitchStatement()
|
  IfStatement()
|
  WhileStatement()
|
  DoStatement()
|
  ForStatement()
|
  BreakStatement()
|
  ContinueStatement()
|
  ReturnStatement()
|
  ThrowStatement()
|
  SynchronizedStatement()
|
  TryStatement()
}

void LabeledStatement() :
{}
{
  <IDENTIFIER> ":" Statement()
}

void Block() :
{}
{
  "{"
    (
      LOOKAHEAD(1, <BOOLEAN> | <BREAK> | <BYTE> | <CHAR> | <CLASS> | <CONTINUE> |
                   <DO> | <DOUBLE> | <FALSE> | <FINAL> | <FLOAT> | <FOR> | <IF> |
                   <INT> | <LONG> | <NEW> | <NULL> | <RETURN> | <SHORT> | <SUPER> |
                   <SWITCH> | <SYNCHRONIZED> | <THIS> | <THROW> | <TRUE> | <TRY> |
                   <VOID> | <WHILE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                   <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> |
                   <LPAREN> | <LBRACE> | <SEMICOLON> | <INCR> | <DECR>)
      BlockStatement()
    )*
  "}"
}

void BlockStatement() :
{}
{
  LOOKAHEAD( { isLocalVariableDeclaration() } )
  LocalVariableDeclaration() ";"
|
  LOOKAHEAD(1, <BOOLEAN> | <BREAK> | <BYTE> | <CHAR> | <CONTINUE> | <DO> |
               <DOUBLE> | <FALSE> | <FLOAT> | <FOR> | <IF> | <INT> | <LONG> |
               <NEW> | <NULL> | <RETURN> | <SHORT> | <SUPER> | <SWITCH> |
               <SYNCHRONIZED> | <THIS> | <THROW> | <TRUE> | <TRY> | <VOID> |
               <WHILE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
               <LBRACE> | <SEMICOLON> | <INCR> | <DECR>)
  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()
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
               <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
               <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN>)
  PrimaryExpression()
  [
    "++"
  |
    "--"
  |
    AssignmentOperator() Expression()
  ]
}

void SwitchStatement() :
{}
{
  "switch" "(" Expression() ")" "{"
    (
      SwitchLabel()
      (
        LOOKAHEAD(1, <BOOLEAN> | <BREAK> | <BYTE> | <CHAR> | <CLASS> | <CONTINUE> |
                     <DO> | <DOUBLE> | <FALSE> | <FINAL> | <FLOAT> | <FOR> | <IF> |
                     <INT> | <LONG> | <NEW> | <NULL> | <RETURN> | <SHORT> | <SUPER> |
                     <SWITCH> | <SYNCHRONIZED> | <THIS> | <THROW> | <TRUE> | <TRY> |
                     <VOID> | <WHILE> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                     <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> |
                     <LPAREN> | <LBRACE> | <SEMICOLON> | <INCR> | <DECR>)
        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" "("
    [
      LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FINAL> |
                   <FLOAT> | <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> |
                   <THIS> | <TRUE> | <VOID> | <INTEGER_LITERAL> |
                   <FLOATING_POINT_LITERAL> | <CHARACTER_LITERAL> | <STRING_LITERAL> |
                   <IDENTIFIER> | <LPAREN> | <INCR> | <DECR>)
      ForInit()
    ]
    ";"
    [
      LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
                   <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
                   <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                   <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
                   <BANG> | <TILDE> | <INCR> | <DECR> | <PLUS> | <MINUS>)
      Expression()
    ]
    ";"
    [
      LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
                   <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
                   <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                   <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
                   <INCR> | <DECR>)
      ForUpdate()
    ]
    ")"
    Statement()
}

void ForInit() :
{}
{
  LOOKAHEAD( { isLocalVariableDeclaration() } )
  LocalVariableDeclaration()
|
  LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
               <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
               <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
               <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
               <INCR> | <DECR>)
  StatementExpressionList()
}

void StatementExpressionList() :
{}
{
  StatementExpression() ( "," StatementExpression() )*
}

void ForUpdate() :
{}
{
  StatementExpressionList()
}

void BreakStatement() :
{}
{
  "break" [ <IDENTIFIER> ] ";"
}

void ContinueStatement() :
{}
{
  "continue" [ <IDENTIFIER> ] ";"
}

void ReturnStatement() :
{}
{
  "return"
  [
    LOOKAHEAD(1, <BOOLEAN> | <BYTE> | <CHAR> | <DOUBLE> | <FALSE> | <FLOAT> |
                 <INT> | <LONG> | <NEW> | <NULL> | <SHORT> | <SUPER> | <THIS> |
                 <TRUE> | <VOID> | <INTEGER_LITERAL> | <FLOATING_POINT_LITERAL> |
                 <CHARACTER_LITERAL> | <STRING_LITERAL> | <IDENTIFIER> | <LPAREN> |
                 <BANG> | <TILDE> | <INCR> | <DECR> | <PLUS> | <MINUS>)
    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() ]
}
