/*------------------------------------------------------------------
 * Copyright (C)
 *   1996, 1997, 1998 Dmitri Bronnikov, All rights reserved.
 *
 * THIS GRAMMAR IS PROVIDED "AS IS" WITHOUT  ANY  EXPRESS  OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES  OF  MERCHANTABILITY  AND  FITNESS  FOR  A  PARTICULAR
 * PURPOSE, OR NON-INFRINGMENT.
 *
 * Bronikov@inreach.com
 *
 *------------------------------------------------------------------
 *
 * VERSION 1.06 DATE 20 AUG 1998
 *
 *------------------------------------------------------------------
 *
 * UPDATES
 *
 * 1.06 Correction of Java 1.1 syntax
 * 1.05 Yet more Java 1.1
 *      <qualified name>.<allocation expression>
 * 1.04 More Java 1.1 features:
 *      <class name>.this
 *      <type name>.class
 * 1.03 Added Java 1.1 features:
 *      inner classes,
 *      anonymous classes,
 *      non-static initializer blocks,
 *      array initialization by new operator
 * 1.02 Corrected cast expression syntax
 * 1.01 All shift/reduce conflicts, except dangling else, resolved
 *
 *------------------------------------------------------------------
 *
 * PARSING CONFLICTS RESOLVED
 *
 * Some Shift/Reduce conflicts have been resolved at the expense of
 * the grammar defines a superset of the language. The following
 * actions have to be performed to complete program syntax checking:
 *
 * 1) Check that modifiers applied to a class, interface, field,
 *    or constructor are allowed in respectively a class, inteface,
 *    field or constructor declaration. For example, a class
 *    declaration should not allow other modifiers than abstract,
 *    final and public.
 *
 * 2) For an expression statement, check it is either increment, or
 *    decrement, or assignment expression.
 *
 * 3) Check that type expression in a cast operator indicates a type.
 *    Some of the compilers that I have tested will allow simultaneous
 *    use of identically named type and variable in the same scope
 *    depending on context.
 *
 * 4) Change lexical definition to change '[' optionally followed by
 *    any number of white-space characters immediately followed by ']'
 *    to OP_DIM token. I defined this token as [\[]{white_space}*[\]]
 *    in the lexer.
 *
 *------------------------------------------------------------------
 *
 * UNRESOLVED SHIFT/REDUCE CONFLICTS
 *
 * Dangling else in if-then-else
 *
 *------------------------------------------------------------------
 */

%token DOPEN     "\(";
%token DCLOSE    "\)";
%token COPEN     "\{";
%token CCLOSE    "\}";
%token BOPEN     "\[";
%token BCLOSE    "\]";
%token SEMICOLON "\;";
%token COMMA     "\,";
%right DOT       "\.";

%token OP_EQ    "==";
%token OP_LE    "\<=";
%token OP_GE    "\>=";
%token OP_NE    "!=";
%token OP_LOR   "\|\|";
%token OP_LAND  "&&";
%token OP_INC   "\+\+";
%token OP_DEC   "\-\-";
%token OP_SHR   "\>\>";
%token OP_SHL   "\<\<";
%token OP_SHRR  "\>\>\>";
%token ASS_OP   "\+= | \-= | \*= | /= | &= | \|= | \^= | \%= | \<\<= | \>\>= | \>\>\>=";

%right EQ    "\=";
%token GT    "\>";
%token LT    "\<";
%token NOT   "\!";
%token TILDE "\~";
%token QM    "\?";
%token COLON "\:";
%token PLUS  "\+";
%token MINUS "\-";
%token MULT  "\*";
%token DIV   "\/";
%token AND   "\&";
%token OR    "\|";
%token XOR   "\^";
%token MOD   "\%";

%token BOOLLIT "true|false";

%token ABSTRACT     "abstract";
%token DO           "do";
%token IMPLEMENTS   "implements";
%token PACKAGE      "package";
%token THROW        "throw";
%token BOOLEAN      "boolean";
%token DOUBLE       "double";
%token IMPORT       "import";
%token PRIVATE      "private";
%token THROWS       "throws";
%token BREAK        "break";

%right ELSE         "else";

%token INNER        "inner";
%token PROTECTED    "protected";
%token TRANSIENT    "transient";
%token BYTE         "byte";
%token EXTENDS      "extends";
%token INSTANCEOF   "instanceof";
%token PUBLIC       "public";
%token TRY          "try";
%token CASE         "case";
%token FINAL        "final";
%token INT          "int";
%token REST         "rest";
%token VAR          "var";
%token CAST         "cast";
%token FINALLY      "finally";
%token INTERFACE    "interface";
%token RETURN       "return";
%token VOID         "void";
%token CATCH        "catch";
%token FLOAT        "float";
%token LONG         "long";
%token SHORT        "short";
%token VOLATILE     "volatile";
%token CHAR         "char";
%token FOR          "for";
%token NATIVE       "native";
%token STATIC       "static";
%token WHILE        "while";
%token CLASS        "class";
%token FUTURE       "future";
%token NEW          "new";
%token SUPER        "super";
%token CONST        "const";
%token GENERIC      "generic";
%token NULL         "null";
%token SWITCH       "switch";
%token CONTINUE     "continue";
%token GOTO         "goto";
%token OPERATOR     "operator";
%token SYNCHRONIZED "synchronized";
%token DEFAULT      "default";
%token IF           "if";
%token OUTER        "outer";
%token THIS         "this";

%ab HexDigit        "[0-9a-fA-F]";
%ab Digit           "[0-9]";
%ab OctalDigit      "[0-7]";
%ab TetraDigit      "[0-3]";
%ab NonZeroDigit    "[1-9]";
%ab Letter          "[a-zA-Z_]";
%ab AnyButSlash     "[^\/]";
%ab AnyButAstr      "[^\*]";
%ab UniEsc          "[\1b]";

%ab OctEscape1      "\\ <OctalDigit>";
%ab OctEscape2      "\\ <OctalDigit><OctalDigit>";
%ab OctEscape3      "\\ <TetraDigit><OctalDigit><OctalDigit>";
%ab OctEscape       "(<OctEscape1>|<OctEscape2>|<OctEscape3>)";

%ab Escape          "[\\]([rnbft\\\'\"])";
%ab ULetter         "(<Letter>|<UniEsc>)";
%ab Identifier      "<ULetter>(<ULetter>|<Digit>)*";

%ab IntSuffix       "(l|L)";
%ab DecimalNum      "<NonZeroDigit><Digit>*<IntSuffix>?";
%ab OctalNum        "0 <OctalDigit>*<IntSuffix>?";
%ab HexNum          "0 (x|X) <HexDigit><HexDigit>*<IntSuffix>?";
%ab IntegerLiteral  "(<DecimalNum>|<OctalNum>|<HexNum>)";

%ab Sign            "(\+ | \-)";
%ab FlSuffix        "(f|F|d|D)";
%ab SignedInt       "<Sign>?<Digit>+";
%ab Expo            "(e|E)";
%ab ExponentPart    "<Expo><SignedInt>?";
%ab Float1          "<Digit>+ \. (<Digit>+)?<ExponentPart>?<FlSuffix>?";
%ab Float2          "\. <Digit>+<ExponentPart>?<FlSuffix>?";
%ab Float3          "<Digit>+<ExponentPart><FlSuffix>?";
%ab Float4          "<Digit>+<FlSuffix>";
%ab FloatingPoint   "(<Float1>|<Float2>|<Float3>|<Float4>)";

%ab AnyChrChr       "[^\\']";
%ab AnyStrChr       "[^\\\"]";
%ab Character       "\' (<Escape>|<OctEscape>|<AnyChrChr>)  \'";
%ab String          "\" (<Escape>|<OctEscape>|<AnyStrChr>)* \"";
%ab Numeric         "(<IntegerLiteral>|<FloatingPoint>)";

%token LITERAL      "(<Numeric>|<Character>|<String>)";

%token IDENTIFIER   "([a-zA-Z_]|[\1b])(([a-zA-Z_]|[\1b])|[0-9])*";


%token OP_DIM "\[ ([\r\n\t\ ]|( \/ \* ([^\*]| \* [^\/])* \*  \/ |
               \/ \/ (.*)))* \]";

%token SPACES "(\ )+";
%token TAB "\t";

%token EOL "\r(\n)?|\n"; // eol

%token JAVADOC           "/ \* \* ([^\*]|[\*][^/])* \* /";
%token MULTILINECOMMENT  "/ \* ([^\*]|\*[^/])* \* /";

%token SINGLELINECOMMENT "\/ \/ (.*)";

%start CompilationUnit;

%%

TypeSpecifier
	: TypeName
	| TypeName Dims
	;

TypeName
	: PrimitiveType
	| QualifiedName %prec DOT
	;

ClassNameList
  : QualifiedName
  | ClassNameList COMMA QualifiedName
	;

PrimitiveType
	: BOOLEAN
	| CHAR
	| BYTE
	| SHORT
	| INT
	| LONG
	| FLOAT
	| DOUBLE
	| VOID
	;

SemiColons
	: SEMICOLON
  | SemiColons SEMICOLON
  ;

CompilationUnit
	: ProgramFile
  ;

ProgramFile
	: PackageStatement ImportStatements TypeDeclarations
	| PackageStatement ImportStatements
	| PackageStatement                  TypeDeclarations
	|                  ImportStatements TypeDeclarations
	| PackageStatement
	|                  ImportStatements
	|                                   TypeDeclarations
	;

PackageStatement
	: PACKAGE QualifiedName SemiColons
	;

TypeDeclarations
	: TypeDeclarationOptSemi
	| TypeDeclarations TypeDeclarationOptSemi
	;

TypeDeclarationOptSemi
  : TypeDeclaration
  | TypeDeclaration SemiColons
  ;

ImportStatements
	: ImportStatement
	| ImportStatements ImportStatement
	;

ImportStatement
	: IMPORT QualifiedName SemiColons
	| IMPORT QualifiedName DOT MULT SemiColons
	;

QualifiedName
	: IDENTIFIER 
	| QualifiedName DOT IDENTIFIER 
	;

TypeDeclaration
	:         ClassHeader COPEN FieldDeclarations CCLOSE
	|         ClassHeader COPEN CCLOSE
  | JAVADOC ClassHeader COPEN FieldDeclarations CCLOSE
  | JAVADOC ClassHeader COPEN CCLOSE
	;

ClassHeader
	: Modifiers ClassWord IDENTIFIER Extends Interfaces
	| Modifiers ClassWord IDENTIFIER Extends
	| Modifiers ClassWord IDENTIFIER         Interfaces
	|           ClassWord IDENTIFIER Extends Interfaces
	| Modifiers ClassWord IDENTIFIER
	|           ClassWord IDENTIFIER Extends
	|           ClassWord IDENTIFIER         Interfaces
	|           ClassWord IDENTIFIER
	;

Modifiers
	: Modifier 
	| Modifiers Modifier 
	;

Modifier
	: ABSTRACT
	| FINAL
	| PUBLIC
	| PROTECTED
	| PRIVATE
	| STATIC
	| TRANSIENT
	| VOLATILE
	| NATIVE
	| SYNCHRONIZED
	;

ClassWord
	: CLASS
	| INTERFACE
	;

Interfaces
	: IMPLEMENTS ClassNameList
	;

FieldDeclarations
	: FieldDeclarationOptSemi
  | FieldDeclarations FieldDeclarationOptSemi
	;

FieldDeclarationOptSemi
  : FieldDeclaration
  | FieldDeclaration SemiColons
  ;

FieldDeclaration
	: FieldVariableDeclaration SEMICOLON
	| MethodDeclaration
	| ConstructorDeclaration
	| StaticInitializer
  | NonStaticInitializer
  | TypeDeclaration
	;

FieldVariableDeclaration
	:         Modifiers TypeSpecifier VariableDeclarators
	|                   TypeSpecifier VariableDeclarators
  | JAVADOC Modifiers TypeSpecifier VariableDeclarators
  | JAVADOC           TypeSpecifier VariableDeclarators
	;

VariableDeclarators
	: VariableDeclarator
	| VariableDeclarators COMMA VariableDeclarator
	;

VariableDeclarator
	: DeclaratorName
	| DeclaratorName EQ VariableInitializer
	;

VariableInitializer
	: Expression
	| COPEN CCLOSE
  | COPEN ArrayInitializers CCLOSE
  ;

ArrayInitializers
	: VariableInitializer
	| ArrayInitializers COMMA VariableInitializer
	| ArrayInitializers COMMA
	;

MethodDeclaration
	:         Modifiers TypeSpecifier MethodDeclarator Throws MethodBody
	|         Modifiers TypeSpecifier MethodDeclarator        MethodBody
	|                   TypeSpecifier MethodDeclarator Throws MethodBody
	|                   TypeSpecifier MethodDeclarator        MethodBody
  | JAVADOC Modifiers TypeSpecifier MethodDeclarator Throws MethodBody
  | JAVADOC Modifiers TypeSpecifier MethodDeclarator        MethodBody
  | JAVADOC           TypeSpecifier MethodDeclarator Throws MethodBody
  | JAVADOC           TypeSpecifier MethodDeclarator        MethodBody
	;

MethodDeclarator
	: DeclaratorName DOPEN ParameterList DCLOSE
	| DeclaratorName DOPEN DCLOSE
	| MethodDeclarator OP_DIM
	;

ParameterList
	: Parameter
	| ParameterList COMMA Parameter
	;

Parameter
	: TypeSpecifier DeclaratorName
  | FINAL TypeSpecifier DeclaratorName
	;

DeclaratorName
	: IDENTIFIER
  | DeclaratorName OP_DIM
  ;

Throws
	: THROWS ClassNameList
	;

MethodBody
	: Block
	| SEMICOLON
	;

ConstructorDeclaration
	:         Modifiers ConstructorDeclarator Throws Block
	|         Modifiers ConstructorDeclarator        Block
	|                   ConstructorDeclarator Throws Block
	|                   ConstructorDeclarator        Block
  | JAVADOC Modifiers ConstructorDeclarator Throws Block
  | JAVADOC Modifiers ConstructorDeclarator        Block
  | JAVADOC           ConstructorDeclarator Throws Block
  | JAVADOC           ConstructorDeclarator        Block
	;

ConstructorDeclarator
	: IDENTIFIER DOPEN ParameterList DCLOSE
	| IDENTIFIER DOPEN DCLOSE
	;

StaticInitializer
	:         STATIC Block
  | JAVADOC STATIC Block
	;

NonStaticInitializer
  : Block
  ;

Extends
	: EXTENDS TypeName
	| Extends COMMA TypeName
	;

Block
	: COPEN LocalVariableDeclarationsAndStatements CCLOSE
	| COPEN CCLOSE
  ;

LocalVariableDeclarationsAndStatements
	: LocalVariableDeclarationOrStatement 
	| LocalVariableDeclarationsAndStatements LocalVariableDeclarationOrStatement 
	;

LocalVariableDeclarationOrStatement
	: LocalVariableDeclarationStatement
	| Statement
	;

LocalVariableDeclarationStatement
	: TypeSpecifier VariableDeclarators SEMICOLON
  | FINAL TypeSpecifier VariableDeclarators SEMICOLON
	;

Statement
	: EmptyStatement
	| LabelStatement
	| ExpressionStatement SEMICOLON
  | SelectionStatement
  | IterationStatement
	| JumpStatement
	| GuardingStatement
	| Block
	;

EmptyStatement
	: SEMICOLON
  ;

LabelStatement
	: IDENTIFIER COLON
  | CASE ConstantExpression COLON
	| DEFAULT COLON
  ;

ExpressionStatement
	: Expression
	;

SelectionStatement
	: IF DOPEN Expression DCLOSE Statement %prec ELSE
  | IF DOPEN Expression DCLOSE Statement ELSE Statement %prec ELSE
  | SWITCH DOPEN Expression DCLOSE Block
  ;

IterationStatement
	: WHILE DOPEN Expression DCLOSE Statement
	| DO Statement WHILE DOPEN Expression DCLOSE SEMICOLON
	| FOR DOPEN ForInit ForExpr ForIncr DCLOSE Statement
	| FOR DOPEN ForInit ForExpr         DCLOSE Statement
	;

ForInit
	: ExpressionStatements SEMICOLON
	| LocalVariableDeclarationStatement
	| SEMICOLON
	;

ForExpr
	: Expression SEMICOLON
	| SEMICOLON
	;

ForIncr
	: ExpressionStatements
	;

ExpressionStatements
	: ExpressionStatement 
	| ExpressionStatements COMMA ExpressionStatement
	;

JumpStatement
	: BREAK IDENTIFIER SEMICOLON
	| BREAK            SEMICOLON
  | CONTINUE IDENTIFIER SEMICOLON
	| CONTINUE            SEMICOLON
	| RETURN Expression SEMICOLON
	| RETURN            SEMICOLON
	| THROW Expression SEMICOLON
	;

GuardingStatement
	: SYNCHRONIZED DOPEN Expression DCLOSE Statement
	| TRY Block Finally
	| TRY Block Catches
	| TRY Block Catches Finally
	;

Catches
	: Catch
	| Catches Catch
	;

Catch
	: CatchHeader Block
	;

CatchHeader
	: CATCH DOPEN TypeSpecifier IDENTIFIER DCLOSE
	| CATCH DOPEN TypeSpecifier DCLOSE
	;

Finally
	: FINALLY Block
	;

PrimaryExpression
	: QualifiedName %prec DOPEN
	| NotJustName 
	;

NotJustName
	: SpecialName 
	| NewAllocationExpression 
	| ComplexPrimary 
	;

ComplexPrimary
	: DOPEN Expression DCLOSE
	| ComplexPrimaryNoParenthesis 
	;

ComplexPrimaryNoParenthesis
	: LITERAL
	| BOOLLIT
	| ArrayAccess
	| FieldAccess
	| MethodCall
	;

ArrayAccess
	: QualifiedName  BOPEN Expression BCLOSE
	| ComplexPrimary BOPEN Expression BCLOSE
	;

FieldAccess
	: NotJustName DOT IDENTIFIER
	| RealPostfixExpression DOT IDENTIFIER
  | QualifiedName DOT THIS
  | QualifiedName DOT CLASS
  | PrimitiveType DOT CLASS
	;

MethodCall
	: MethodAccess DOPEN ArgumentList DCLOSE
	| MethodAccess DOPEN DCLOSE
	;

MethodAccess
	: ComplexPrimaryNoParenthesis
	| SpecialName
	| QualifiedName
	;

SpecialName
	: THIS
	| SUPER
	| NULL
	;

ArgumentList
	: Expression
	| ArgumentList COMMA Expression
	;

NewAllocationExpression
  : PlainNewAllocationExpression
  | QualifiedName DOT PlainNewAllocationExpression
  ;

PlainNewAllocationExpression
 	: ArrayAllocationExpression
 	| ClassAllocationExpression
 	| ArrayAllocationExpression COPEN CCLOSE
 	| ClassAllocationExpression COPEN CCLOSE
 	| ArrayAllocationExpression COPEN ArrayInitializers CCLOSE
 	| ClassAllocationExpression COPEN FieldDeclarations CCLOSE
 	;

ClassAllocationExpression
	: NEW TypeName DOPEN ArgumentList DCLOSE
	| NEW TypeName DOPEN              DCLOSE
  ;

ArrayAllocationExpression
	: NEW TypeName DimExprs Dims
	| NEW TypeName DimExprs
  | NEW TypeName Dims
	;

DimExprs
	: DimExpr
	| DimExprs DimExpr
	;

DimExpr
	: BOPEN Expression BCLOSE
	;

Dims
	: OP_DIM
	| Dims OP_DIM
	;

PostfixExpression
	: PrimaryExpression 
	| RealPostfixExpression 
	;

RealPostfixExpression
	: PostfixExpression OP_INC
	| PostfixExpression OP_DEC
	;

UnaryExpression
	: OP_INC UnaryExpression
	| OP_DEC UnaryExpression
	| ArithmeticUnaryOperator CastExpression
	| LogicalUnaryExpression 
	;

LogicalUnaryExpression
	: PostfixExpression 
	| LogicalUnaryOperator UnaryExpression
	;

LogicalUnaryOperator
	: TILDE
	| NOT
	;

ArithmeticUnaryOperator
	: PLUS
	| MINUS
	;

CastExpression
	: UnaryExpression 
	| DOPEN PrimitiveTypeExpression DCLOSE CastExpression
	| DOPEN ClassTypeExpression DCLOSE CastExpression
	| DOPEN Expression DCLOSE LogicalUnaryExpression
	;

PrimitiveTypeExpression
	: PrimitiveType 
  | PrimitiveType Dims
  ;

ClassTypeExpression
	: QualifiedName Dims
  ;

MultiplicativeExpression
	: CastExpression 
	| MultiplicativeExpression MULT CastExpression
	| MultiplicativeExpression DIV CastExpression
	| MultiplicativeExpression MOD CastExpression
	;

AdditiveExpression
	: MultiplicativeExpression 
  | AdditiveExpression PLUS MultiplicativeExpression
	| AdditiveExpression MINUS MultiplicativeExpression
  ;

ShiftExpression 
	: AdditiveExpression 
  | ShiftExpression OP_SHL AdditiveExpression
  | ShiftExpression OP_SHR AdditiveExpression
  | ShiftExpression OP_SHRR AdditiveExpression
	;

RelationalExpression
	: ShiftExpression 
  | RelationalExpression LT ShiftExpression
	| RelationalExpression GT ShiftExpression
	| RelationalExpression OP_LE ShiftExpression
	| RelationalExpression OP_GE ShiftExpression
	| RelationalExpression INSTANCEOF TypeSpecifier
	;

EqualityExpression
	: RelationalExpression 
  | EqualityExpression OP_EQ RelationalExpression
  | EqualityExpression OP_NE RelationalExpression
  ;

AndExpression
	: EqualityExpression 
  | AndExpression AND EqualityExpression
  ;

ExclusiveOrExpression
	: AndExpression 
	| ExclusiveOrExpression XOR AndExpression
	;

InclusiveOrExpression
	: ExclusiveOrExpression 
	| InclusiveOrExpression OR ExclusiveOrExpression
	;

ConditionalAndExpression
	: InclusiveOrExpression 
	| ConditionalAndExpression OP_LAND InclusiveOrExpression
	;

ConditionalOrExpression
	: ConditionalAndExpression 
	| ConditionalOrExpression OP_LOR ConditionalAndExpression
	;

ConditionalExpression
	: ConditionalOrExpression 
	| ConditionalOrExpression QM Expression COLON ConditionalExpression
	;

AssignmentExpression
	: ConditionalExpression 
	| UnaryExpression AssignmentOperator AssignmentExpression
	;

AssignmentOperator
	: EQ
	| ASS_OP
	;

Expression
	: AssignmentExpression
  ;

ConstantExpression
	: ConditionalExpression
	;


