/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. src/bsh/bsh.jj */
/*@egen*//*****************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one                *
 * or more contributor license agreements.  See the NOTICE file              *
 * distributed with this work for additional information                     *
 * regarding copyright ownership.  The ASF licenses this file                *
 * to you under the Apache License, Version 2.0 (the                         *
 * "License"); you may not use this file except in compliance                *
 * with the License.  You may obtain a copy of the License at                *
 *                                                                           *
 *     http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing,                *
 * software distributed under the License is distributed on an               *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                    *
 * KIND, either express or implied.  See the License for the                 *
 * specific language governing permissions and limitations                   *
 * under the License.                                                        *
 *                                                                           *
 *                                                                           *
 * This file is part of the BeanShell Java Scripting distribution.           *
 * Documentation and updates may be found at http://www.beanshell.org/       *
 * Patrick Niemeyer (pat@pat.net)                                            *
 * Author of Learning Java, O'Reilly & Associates                            *
 *                                                                           *
 *****************************************************************************/
 
/*
	Notes:
	There is probably a lot of room for improvement in here.
	All of the syntactic lookaheads have been commented with:
		SYNTACTIC_LOOKAHEAD
	These are probably expensive and we may want to start weeding them out
	where possible.
*/

options {
    JAVA_UNICODE_ESCAPE=true;
    STATIC=false;                                                                                       
	/* Print grammar debugging info as we parse
	DEBUG_PARSER=true;
	*/
	/* Print detailed lookahead debugging info
	DEBUG_LOOKAHEAD=true;
	*/

	/*
		There are weird issues related to this flag.
		The default value, true, creates line level error detail in the parse
		exceptions.  However it gives us strange LookaheadSuccess Errors thrown
		on some syntax errors.
		http://groups-beta.google.com/group/comp.compilers.tools.javacc/browse_thread/thread/14d3471883f8794f/ecf7b1d81151839c?q=Parser$LookaheadSuccess&rnum=1&hl=en#ecf7b1d81151839c
		I have manually hacked the Parser.java to catch LookaheadSuccess in
		the jj_rescan_token() method...  The bug report indicates that this
		is fixed, apparently in some post javacc 3.2 version.
	*/
	//ERROR_REPORTING=false;

	// This breaks something for interactive use on the command line,
	// but may be useful in non-interactive use.
	//CACHE_TOKENS=true;
}

PARSER_BEGIN(Parser)
/*****************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one                *
 * or more contributor license agreements.  See the NOTICE file              *
 * distributed with this work for additional information                     *
 * regarding copyright ownership.  The ASF licenses this file                *
 * to you under the Apache License, Version 2.0 (the                         *
 * "License"); you may not use this file except in compliance                *
 * with the License.  You may obtain a copy of the License at                *
 *                                                                           *
 *     http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing,                *
 * software distributed under the License is distributed on an               *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                    *
 * KIND, either express or implied.  See the License for the                 *
 * specific language governing permissions and limitations                   *
 * under the License.                                                        *
 *                                                                           *
 *                                                                           *
 * This file is part of the BeanShell Java Scripting distribution.           *
 * Documentation and updates may be found at http://www.beanshell.org/       *
 * Patrick Niemeyer (pat@pat.net)                                            *
 * Author of Learning Java, O'Reilly & Associates                            *
 *                                                                           *
 *****************************************************************************/
package bsh;

import java.io.*;
import java.util.Vector;

/**
	This is the BeanShell parser.  It is used internally by the Interpreter
	class (which is probably what you are looking for).  The parser knows
	only how to parse the structure of the language, it does not understand
	names, commands, etc.
	<p>
	You can use the Parser from the command line to do basic structural
	validation of BeanShell files without actually executing them. e.g.
	<code><pre>
		java bsh.Parser [ -p ] file [ file ] [ ... ]
	</pre></code>
	<p>
	The -p option causes the abstract syntax to be printed.
	<p>

	From code you'd use the Parser like this:
	<p
	<code><pre>
		Parser parser = new Parser(in);
		while( !(eof=parser.Line()) ) {
			SimpleNode node = parser.popNode();
			// use the node, etc. (See bsh.BSH* classes)
		}
	</pre></code>
*/
public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants/*@egen*/
{/*@bgen(jjtree)*/
  protected JJTParserState jjtree = new JJTParserState();

/*@egen*/
	boolean retainComments = false;

	public void setRetainComments( boolean b ) {
		retainComments = b;
	}

	void jjtreeOpenNodeScope(Node n) {
		((SimpleNode)n).firstToken = getToken(1);
	}

	void jjtreeCloseNodeScope(Node n) {
		((SimpleNode)n).lastToken = getToken(0);
	}

	/**
		Re-initialize the input stream and token source.
	*/
	void reInitInput( Reader in ) {
		ReInit(in);
	}

	public SimpleNode popNode()
	{
		if ( jjtree.nodeArity() > 0)  // number of child nodes
			return (SimpleNode)jjtree.popNode();
		else
			return null;
	}

	/**
		Explicitly re-initialize just the token reader.
		This seems to be necessary to avoid certain looping errors when
		reading bogus input.  See Interpreter.
	*/
	void reInitTokenInput( Reader in ) {
		jj_input_stream.ReInit( in,
			jj_input_stream.getEndLine(),
			jj_input_stream.getEndColumn() );
	}

	public static void main( String [] args )
		throws IOException, ParseException
	{
		boolean print = false;
		int i=0;
		if ( args[0].equals("-p") ) {
			i++;
			print=true;
		}
		for(; i< args.length; i++) {
			Reader in = new FileReader(args[i]);
			Parser parser = new Parser(in);
			parser.setRetainComments(true);
			while( !parser.Line()/*eof*/ )
				if ( print )
					System.out.println( parser.popNode() );
		}
	}

	/**
		Lookahead for the enhanced for statement.
		Expect "for" "(" and then see whether we hit ":" or a ";" first.
	*/
	boolean isRegularForStatement()
	{
		int curTok = 1;
		Token tok;
		tok = getToken(curTok++);
		if ( tok.kind != FOR ) return false;
		tok = getToken(curTok++);
		if ( tok.kind != LPAREN ) return false;
		while (true)
		{
			tok = getToken(curTok++);
			switch (tok.kind) {
				case COLON:
					return false;
				case SEMICOLON:
					return true;
				case EOF:
					return false;
			}
		}
	}

	/**
		Generate a ParseException with the specified message, pointing to the
		current token.
		The auto-generated Parser.generateParseException() method does not
		provide line number info, therefore we do this.
	*/
	ParseException createParseException( String message )
	{
		Token errortok = token;
		int line = errortok.beginLine, column = errortok.beginColumn;
		String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image;
		return new ParseException( "Parse error at line " + line
			+ ", column " + column + " : " + message );
	}
}

PARSER_END(Parser)

SKIP : /* WHITE SPACE */
{
	" " | "\t" | "\r" | "\f"
	| "\n"
	| < NONPRINTABLE: (["\u0000"-" ", "\u0080"-"\u00ff"])+ >
}

SPECIAL_TOKEN : /* COMMENTS */
{
/*
	SINGLE_LINE_COMMENT includes a hack to accept SLC at the end of a file
	with no terminanting linefeed.  This is actually illegal according to
	spec, but comes up often enough to warrant it... (especially in eval()).
*/
  <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? >

| <HASH_BANG_COMMENT: "#!" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>

 /* Moved FORMAL_COMMENT to a real token.  Modified MULTI_LINE_COMMENT to not
    catch formal comments (require no star after star) */
| <MULTI_LINE_COMMENT:
	"/*" (~["*"])+ "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
}

TOKEN : /* RESERVED WORDS AND LITERALS */
{
< ABSTRACT : "abstract" >
| < BOOLEAN: "boolean" >
| < BREAK: "break" >
| < CLASS: "class" >
| < BYTE: "byte" >
| < CASE: "case" >
| < CATCH: "catch" >
| < CHAR: "char" >
| < 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" >
| < SWITCH: "switch" >
| < SYNCHRONIZED: "synchronized" >
| < TRANSIENT: "transient" >
| < THROW: "throw" >
| < THROWS: "throws" >
| < TRUE: "true" >
| < TRY: "try" >
| < VOID: "void" >
| < VOLATILE: "volatile" >
| < WHILE: "while" >
}

TOKEN : /* LITERALS */
{
  < 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"]
            )
          )
      )*
      "\""
  >
|
   < FORMAL_COMMENT:
		"/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/"
	>
}

TOKEN : /* IDENTIFIERS */
{
  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
|
  < #LETTER:
      [
       "$",
       "A"-"Z",
       "_",
       "a"-"z",
       "\u00c0"-"\u00d6",
       "\u00d8"-"\u00f6",
       "\u00f8"-"\u00ff",
       "\u0100"-"\u1fff",
       "\u3040"-"\u318f",
       "\u3300"-"\u337f",
       "\u3400"-"\u3d2d",
       "\u4e00"-"\u9fff",
       "\uf900"-"\ufaff"
      ]
  >
|
  < #DIGIT:
      [
       "0"-"9",
       "\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"
      ]
  >
}

TOKEN : /* SEPARATORS */
{
  < LPAREN: "(" >
| < RPAREN: ")" >
| < LBRACE: "{" >
| < RBRACE: "}" >
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < SEMICOLON: ";" >
| < COMMA: "," >
| < DOT: "." >
}

TOKEN : /* OPERATORS */
{
  < ASSIGN: "=" >
| < GT: ">" >
| < GTX: "@gt" >
| < LT: "<" >
| < LTX: "@lt" >
| < BANG: "!" >
| < TILDE: "~" >
| < HOOK: "?" >
| < COLON: ":" >
| < EQ: "==" >
| < LE: "<=" >
| < LEX: "@lteq" >
| < GE: ">=" >
| < GEX: "@gteq" >
| < NE: "!=" >
| < BOOL_OR: "||" >
| < BOOL_ORX: "@or" >
| < BOOL_AND: "&&" >
| < BOOL_ANDX: "@and" >
| < INCR: "++" >
| < DECR: "--" >
| < PLUS: "+" >
| < MINUS: "-" >
| < STAR: "*" >
| < SLASH: "/" >
| < BIT_AND: "&" >
| < BIT_ANDX: "@bitwise_and" >
| < BIT_OR: "|" >
| < BIT_ORX: "@bitwise_or" >
| < XOR: "^" >
| < MOD: "%" >
| < LSHIFT: "<<" >
| < LSHIFTX: "@left_shift" >
| < RSIGNEDSHIFT: ">>" >
| < RSIGNEDSHIFTX: "@right_shift" >
| < RUNSIGNEDSHIFT: ">>>" >
| < RUNSIGNEDSHIFTX: "@right_unsigned_shift" >
| < PLUSASSIGN: "+=" >
| < MINUSASSIGN: "-=" >
| < STARASSIGN: "*=" >
| < SLASHASSIGN: "/=" >
| < ANDASSIGN: "&=" >
| < ANDASSIGNX: "@and_assign" >
| < ORASSIGN: "|=" >
| < ORASSIGNX: "@or_assign" >
| < XORASSIGN: "^=" >
| < MODASSIGN: "%=" >
| < LSHIFTASSIGN: "<<=" >
| < LSHIFTASSIGNX: "@left_shift_assign" >
| < RSIGNEDSHIFTASSIGN: ">>=" >
| < RSIGNEDSHIFTASSIGNX: "@right_shift_assign" >
| < RUNSIGNEDSHIFTASSIGN: ">>>=" >
| < RUNSIGNEDSHIFTASSIGNX: "@right_unsigned_shift_assign" >
}


/*
	Thanks to Sreenivasa Viswanadha for suggesting how to get rid of expensive
	lookahead here.
*/
boolean Line() :
{}
{
  <EOF> {
	Interpreter.debug("End of File!");
	return true;
  }
|
  BlockStatement() {
	return false;
  }
}

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

/*
	Gather modifiers for a class, method, or field.
	I lookahead is true then we are being called as part of a lookahead and we
	should not enforce any rules.  Otherwise we validate based on context
	(field, method, class)
*/
Modifiers Modifiers( int context, boolean lookahead ) :
{
	Modifiers mods = null;
}
{
  (
	(
		"private" |	"protected" | "public" | "synchronized" | "final"
		| "native" | "transient" | "volatile" |	"abstract" | "static"
		| "strictfp"
	) {
		if ( !lookahead )
			try {
				if ( mods == null ) mods = new Modifiers();
				mods.addModifier( context, getToken(0).image );
			} catch ( IllegalStateException e ) {
				throw createParseException( e.getMessage() );
			}
	}
  )* {
  	return mods;
  }
}


/**
*/
void ClassDeclaration()                   :
{/*@bgen(jjtree) ClassDeclaration */
        BSHClassDeclaration jjtn000 = new BSHClassDeclaration(JJTCLASSDECLARATION);
        boolean jjtc000 = true;
        jjtree.openNodeScope(jjtn000);
        jjtreeOpenNodeScope(jjtn000);
/*@egen*/
	Modifiers mods;
	Token name;
	int numInterfaces;
}
{/*@bgen(jjtree) ClassDeclaration */
        try {
/*@egen*/
	mods = Modifiers( Modifiers.CLASS, false )
	( "class" | "interface" { jjtn000.isInterface=true; } )
	name=<IDENTIFIER>
	[ "extends" AmbiguousName() { jjtn000.extend = true; } ]
	[ "implements" numInterfaces=NameList()
		{ jjtn000.numInterfaces=numInterfaces; } ]
	Block()/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/
	{
		jjtn000.modifiers = mods;
		jjtn000.name = name.image;
	}/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

void MethodDeclaration()                    :
{/*@bgen(jjtree) MethodDeclaration */
        BSHMethodDeclaration jjtn000 = new BSHMethodDeclaration(JJTMETHODDECLARATION);
        boolean jjtc000 = true;
        jjtree.openNodeScope(jjtn000);
        jjtreeOpenNodeScope(jjtn000);
/*@egen*/
	Token t = null;
	Modifiers mods;
	int count;
}
{/*@bgen(jjtree) MethodDeclaration */
        try {
/*@egen*/
	mods = Modifiers( Modifiers.METHOD, false ) { jjtn000.modifiers = mods; }
(
	LOOKAHEAD( <IDENTIFIER> "(" )
	t = <IDENTIFIER> { jjtn000.name = t.image; }
|
    ReturnType()
	t = <IDENTIFIER> { jjtn000.name = t.image; }
)
    FormalParameters()
	[ "throws" count=NameList() { jjtn000.numThrows=count; } ]
	( Block() | ";" )/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

void PackageDeclaration ()                    :
{/*@bgen(jjtree) PackageDeclaration */
  BSHPackageDeclaration jjtn000 = new BSHPackageDeclaration(JJTPACKAGEDECLARATION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) PackageDeclaration */
        try {
/*@egen*/
	"package" AmbiguousName()/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

void ImportDeclaration()                    :
{/*@bgen(jjtree) ImportDeclaration */
    BSHImportDeclaration jjtn000 = new BSHImportDeclaration(JJTIMPORTDECLARATION);
    boolean jjtc000 = true;
    jjtree.openNodeScope(jjtn000);
    jjtreeOpenNodeScope(jjtn000);
/*@egen*/
    Token s = null;
	Token t = null;
}
{/*@bgen(jjtree) ImportDeclaration */
  try {
/*@egen*/
  LOOKAHEAD( 3 )
  "import" [ s = "static" ] AmbiguousName() [ t = "." "*" ] ";"/*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    jjtreeCloseNodeScope(jjtn000);
  }
/*@egen*/
  {
		if ( s != null ) jjtn000.staticImport = true;
		if ( t != null ) jjtn000.importPackage = true;
  }
  |
	// bsh super import statement
  "import" "*" ";"/*@bgen(jjtree)*/
                   {
                     jjtree.closeNodeScope(jjtn000, true);
                     jjtc000 = false;
                     jjtreeCloseNodeScope(jjtn000);
                   }
/*@egen*/ {
		jjtn000.superImport = true;
	}/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void VariableDeclarator()                     :
{/*@bgen(jjtree) VariableDeclarator */
        BSHVariableDeclarator jjtn000 = new BSHVariableDeclarator(JJTVARIABLEDECLARATOR);
        boolean jjtc000 = true;
        jjtree.openNodeScope(jjtn000);
        jjtreeOpenNodeScope(jjtn000);
/*@egen*/
	Token t;
}
{/*@bgen(jjtree) VariableDeclarator */
        try {
/*@egen*/
	t=<IDENTIFIER> [ "=" VariableInitializer() ]/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/
	{
  		jjtn000.name = t.image;
	}/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

/*
this originally handled postfix array dimensions...

void VariableDeclaratorId() #VariableDeclaratorId :
{ Token t; }
{
  t=<IDENTIFIER> { jjtThis.name = t.image; }
  ( "[" "]" { jjtThis.addUndefinedDimension(); } )*
}
*/

void VariableInitializer() :
{}
{
  ArrayInitializer()
|
  Expression()
}

void ArrayInitializer()                   :
{/*@bgen(jjtree) ArrayInitializer */
  BSHArrayInitializer jjtn000 = new BSHArrayInitializer(JJTARRAYINITIALIZER);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) ArrayInitializer */
  try {
/*@egen*/
  "{" [ VariableInitializer()
		( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void FormalParameters()                   :
{/*@bgen(jjtree) FormalParameters */
  BSHFormalParameters jjtn000 = new BSHFormalParameters(JJTFORMALPARAMETERS);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) FormalParameters */
  try {
/*@egen*/
  "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void FormalParameter()                  :
{/*@bgen(jjtree) FormalParameter */
  BSHFormalParameter jjtn000 = new BSHFormalParameter(JJTFORMALPARAMETER);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ Token t; }
{/*@bgen(jjtree) FormalParameter */
  try {
/*@egen*/
  // added [] to Type for bsh.  Removed [ final ] - is that legal?
  LOOKAHEAD(2) Type() t=<IDENTIFIER>/*@bgen(jjtree)*/
                                     {
                                       jjtree.closeNodeScope(jjtn000, true);
                                       jjtc000 = false;
                                       jjtreeCloseNodeScope(jjtn000);
                                     }
/*@egen*/ { jjtn000.name = t.image; }
|
  t=<IDENTIFIER>/*@bgen(jjtree)*/
                 {
                   jjtree.closeNodeScope(jjtn000, true);
                   jjtc000 = false;
                   jjtreeCloseNodeScope(jjtn000);
                 }
/*@egen*/ { jjtn000.name = t.image; }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}


/*
	Type, name and expression syntax follows.
*/
void Type()       :
{/*@bgen(jjtree) Type */
  BSHType jjtn000 = new BSHType(JJTTYPE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) Type */
  try {
/*@egen*/
	/*
		The embedded lookahead is (was?) necessary to disambiguate for
		PrimaryPrefix.  ( )* is a choice point.  It took me a while to
		figure out where to put that.  This stuff is annoying.
	*/
  ( PrimitiveType() | AmbiguousName() )
	( LOOKAHEAD(2) "[" "]" { jjtn000.addArrayDimension(); } )*/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

/*
	Originally called ResultType in the grammar
*/
void ReturnType()             :
{/*@bgen(jjtree) ReturnType */
  BSHReturnType jjtn000 = new BSHReturnType(JJTRETURNTYPE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) ReturnType */
  try {
/*@egen*/
  "void"/*@bgen(jjtree)*/
         {
           jjtree.closeNodeScope(jjtn000, true);
           jjtc000 = false;
           jjtreeCloseNodeScope(jjtn000);
         }
/*@egen*/ { jjtn000.isVoid = true; }
|
  Type()/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void PrimitiveType()                :
{/*@bgen(jjtree) PrimitiveType */
  BSHPrimitiveType jjtn000 = new BSHPrimitiveType(JJTPRIMITIVETYPE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ } {/*@bgen(jjtree) PrimitiveType */
  try {
/*@egen*/
  "boolean"/*@bgen(jjtree)*/
            {
              jjtree.closeNodeScope(jjtn000, true);
              jjtc000 = false;
              jjtreeCloseNodeScope(jjtn000);
            }
/*@egen*/ { jjtn000.type = Boolean.TYPE; }
| "char"/*@bgen(jjtree)*/
         {
           jjtree.closeNodeScope(jjtn000, true);
           jjtc000 = false;
           jjtreeCloseNodeScope(jjtn000);
         }
/*@egen*/ { jjtn000.type =  Character.TYPE; }
| "byte"/*@bgen(jjtree)*/
         {
           jjtree.closeNodeScope(jjtn000, true);
           jjtc000 = false;
           jjtreeCloseNodeScope(jjtn000);
         }
/*@egen*/ { jjtn000.type =  Byte.TYPE; }
| "short"/*@bgen(jjtree)*/
          {
            jjtree.closeNodeScope(jjtn000, true);
            jjtc000 = false;
            jjtreeCloseNodeScope(jjtn000);
          }
/*@egen*/ { jjtn000.type =  Short.TYPE; }
| "int"/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/ { jjtn000.type =  Integer.TYPE; }
| "long"/*@bgen(jjtree)*/
         {
           jjtree.closeNodeScope(jjtn000, true);
           jjtc000 = false;
           jjtreeCloseNodeScope(jjtn000);
         }
/*@egen*/ { jjtn000.type =  Long.TYPE; }
| "float"/*@bgen(jjtree)*/
          {
            jjtree.closeNodeScope(jjtn000, true);
            jjtc000 = false;
            jjtreeCloseNodeScope(jjtn000);
          }
/*@egen*/ { jjtn000.type =  Float.TYPE; }
| "double"/*@bgen(jjtree)*/
           {
             jjtree.closeNodeScope(jjtn000, true);
             jjtc000 = false;
             jjtreeCloseNodeScope(jjtn000);
           }
/*@egen*/ { jjtn000.type =  Double.TYPE; }/*@bgen(jjtree)*/
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void AmbiguousName()                :
/*
	A lookahead of 2 is required below since "Name" can be followed by a ".*"
	when used in the context of an "ImportDeclaration".
*/
{/*@bgen(jjtree) AmbiguousName */
    BSHAmbiguousName jjtn000 = new BSHAmbiguousName(JJTAMBIGUOUSNAME);
    boolean jjtc000 = true;
    jjtree.openNodeScope(jjtn000);
    jjtreeOpenNodeScope(jjtn000);
/*@egen*/
    Token t;
    StringBuffer s;
}
{/*@bgen(jjtree) AmbiguousName */
  try {
/*@egen*/
  t = <IDENTIFIER> {
  	s = new StringBuffer(t.image);
  }
  ( LOOKAHEAD(2) "." t = <IDENTIFIER> { s.append("."+t.image); } )*/*@bgen(jjtree)*/
                                                                    {
                                                                      jjtree.closeNodeScope(jjtn000, true);
                                                                      jjtc000 = false;
                                                                      jjtreeCloseNodeScope(jjtn000);
                                                                    }
/*@egen*/ {
  	jjtn000.text = s.toString();
  }/*@bgen(jjtree)*/
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

int NameList() :
{ int count = 0; }
{
  AmbiguousName() { ++count; } ( "," AmbiguousName() { ++count; } )*
  { return count; }
}

/*
 * Expression syntax follows.
 */
void Expression() :
{ }
{
	/**
		SYNTACTIC_LOOKAHEAD
		Note: the original grammar was cheating here and we've fixed that,
		but at the expense of another syntactic lookahead.
	*/
  LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
  Assignment()
|
  ConditionalExpression()
}

void Assignment()             :
{/*@bgen(jjtree) Assignment */
  BSHAssignment jjtn000 = new BSHAssignment(JJTASSIGNMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ int op ; }
{/*@bgen(jjtree) Assignment */
  try {
/*@egen*/
  PrimaryExpression()
  	op = AssignmentOperator() { jjtn000.operator = op; }
	// Add this for blocks, e.g. foo = { };
	//( Expression() | Block() )
	Expression()/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

int AssignmentOperator() :
{ Token t; }
{
    ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&=" | "^=" | "|=" |
      "<<=" | "@left_shift_assign" | ">>=" | "@right_shift_assign" |
      ">>>=" | "@right_unsigned_shift_assign" )
    {
        t = getToken(0);
        return t.kind;
    }
}

void ConditionalExpression() :
{ }
{
  ConditionalOrExpression() [ "?" Expression() ":"/*@bgen(jjtree) #TernaryExpression( 3) */
                                                   {
                                                     BSHTernaryExpression jjtn001 = new BSHTernaryExpression(JJTTERNARYEXPRESSION);
                                                     boolean jjtc001 = true;
                                                     jjtree.openNodeScope(jjtn001);
                                                     jjtreeOpenNodeScope(jjtn001);
                                                   }
                                                   try {
/*@egen*/ ConditionalExpression()/*@bgen(jjtree)*/
                                                   } catch (Throwable jjte001) {
                                                     if (jjtc001) {
                                                       jjtree.clearNodeScope(jjtn001);
                                                       jjtc001 = false;
                                                     } else {
                                                       jjtree.popNode();
                                                     }
                                                     if (jjte001 instanceof RuntimeException) {
                                                       throw (RuntimeException)jjte001;
                                                     }
                                                     if (jjte001 instanceof ParseException) {
                                                       throw (ParseException)jjte001;
                                                     }
                                                     throw (Error)jjte001;
                                                   } finally {
                                                     if (jjtc001) {
                                                       jjtree.closeNodeScope(jjtn001,  3);
                                                       jjtreeCloseNodeScope(jjtn001);
                                                     }
                                                   }
/*@egen*/ ]
}

void ConditionalOrExpression() :
{ Token t=null; }
{
  ConditionalAndExpression()
  ( ( t = "||" | t = "@or" )
    ConditionalAndExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
    {
      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  2);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/ )*
}

void ConditionalAndExpression() :
{ Token t=null; }
{
  InclusiveOrExpression()
  ( ( t = "&&" | t = "@and" )
    InclusiveOrExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
    {
      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  2);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/ )*
}

void InclusiveOrExpression() :
{ Token t=null; }
{
  ExclusiveOrExpression()
  ( ( t = "|" | t = "@bitwise_or" )
    ExclusiveOrExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
    {
      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  2);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/ )*
}

void ExclusiveOrExpression() :
{ Token t=null; }
{
  AndExpression() ( t="^" AndExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
    {
      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  2);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/ )*
}

void AndExpression() :
{ Token t=null; }
{
  EqualityExpression()
  ( ( t = "&" | t = "@bitwise_and" )
    EqualityExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
    {
      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  2);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/ )*
}

void EqualityExpression() :
{ Token t = null; }
{
  InstanceOfExpression() ( ( t= "==" | t= "!=" ) InstanceOfExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
    {
      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  2);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/
  )*
}

void InstanceOfExpression() :
{ Token t = null; }
{
  RelationalExpression()
  [ t = "instanceof" Type()/*@bgen(jjtree) #BinaryExpression( 2) */
                            {
                              BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
                              boolean jjtc001 = true;
                              jjtree.openNodeScope(jjtn001);
                              jjtreeOpenNodeScope(jjtn001);
                            }
                            try {
/*@egen*//*@bgen(jjtree)*/
                            {
                              jjtree.closeNodeScope(jjtn001,  2);
                              jjtc001 = false;
                              jjtreeCloseNodeScope(jjtn001);
                            }
/*@egen*/ { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
                            } finally {
                              if (jjtc001) {
                                jjtree.closeNodeScope(jjtn001,  2);
                                jjtreeCloseNodeScope(jjtn001);
                              }
                            }
/*@egen*/ ]
}

void RelationalExpression() :
{ Token t = null; }
{
  ShiftExpression()
  ( ( t = "<" | t = "@lt" | t = ">" | t = "@gt" |
      t = "<=" | t = "@lteq" | t = ">=" | t = "@gteq" )
  ShiftExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
  {
    BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
    boolean jjtc001 = true;
    jjtree.openNodeScope(jjtn001);
    jjtreeOpenNodeScope(jjtn001);
  }
  try {
/*@egen*//*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn001,  2);
    jjtc001 = false;
    jjtreeCloseNodeScope(jjtn001);
  }
/*@egen*/
  { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
  } finally {
    if (jjtc001) {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtreeCloseNodeScope(jjtn001);
    }
  }
/*@egen*/ )*
}

void ShiftExpression() :
{ Token t = null; }
{
  AdditiveExpression()
  ( ( t = "<<" | t = "@left_shift" | t = ">>" | t = "@right_shift" |
      t = ">>>" | t = "@right_unsigned_shift" )
  AdditiveExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
  {
    BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
    boolean jjtc001 = true;
    jjtree.openNodeScope(jjtn001);
    jjtreeOpenNodeScope(jjtn001);
  }
  try {
/*@egen*//*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn001,  2);
    jjtc001 = false;
    jjtreeCloseNodeScope(jjtn001);
  }
/*@egen*/
  { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
  } finally {
    if (jjtc001) {
      jjtree.closeNodeScope(jjtn001,  2);
      jjtreeCloseNodeScope(jjtn001);
    }
  }
/*@egen*/ )*
}

void AdditiveExpression() :
{ Token t = null; }
{
  MultiplicativeExpression()
  ( ( t= "+" | t= "-" ) MultiplicativeExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
                                                   {
                                                     BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
                                                     boolean jjtc001 = true;
                                                     jjtree.openNodeScope(jjtn001);
                                                     jjtreeOpenNodeScope(jjtn001);
                                                   }
                                                   try {
/*@egen*//*@bgen(jjtree)*/
                                                   {
                                                     jjtree.closeNodeScope(jjtn001,  2);
                                                     jjtc001 = false;
                                                     jjtreeCloseNodeScope(jjtn001);
                                                   }
/*@egen*/ { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
                                                   } finally {
                                                     if (jjtc001) {
                                                       jjtree.closeNodeScope(jjtn001,  2);
                                                       jjtreeCloseNodeScope(jjtn001);
                                                     }
                                                   }
/*@egen*/
  )*
}

void MultiplicativeExpression() :
{ Token t = null; }
{
  UnaryExpression() ( ( t= "*" | t= "/" | t= "%" )
  UnaryExpression()/*@bgen(jjtree) #BinaryExpression( 2) */
                    {
                      BSHBinaryExpression jjtn001 = new BSHBinaryExpression(JJTBINARYEXPRESSION);
                      boolean jjtc001 = true;
                      jjtree.openNodeScope(jjtn001);
                      jjtreeOpenNodeScope(jjtn001);
                    }
                    try {
/*@egen*//*@bgen(jjtree)*/
                    {
                      jjtree.closeNodeScope(jjtn001,  2);
                      jjtc001 = false;
                      jjtreeCloseNodeScope(jjtn001);
                    }
/*@egen*/ { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
                    } finally {
                      if (jjtc001) {
                        jjtree.closeNodeScope(jjtn001,  2);
                        jjtreeCloseNodeScope(jjtn001);
                      }
                    }
/*@egen*/ )*
}

void UnaryExpression() :
{ Token t = null; }
{
  ( t="+" | t="-" ) UnaryExpression()/*@bgen(jjtree) #UnaryExpression( 1) */
    {
      BSHUnaryExpression jjtn001 = new BSHUnaryExpression(JJTUNARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  1);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  1);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/
|
  PreIncrementExpression()
|
  PreDecrementExpression()
|
  UnaryExpressionNotPlusMinus()
}

void PreIncrementExpression() :
{ Token t = null; }
{
  t="++" PrimaryExpression()/*@bgen(jjtree) #UnaryExpression( 1) */
    {
      BSHUnaryExpression jjtn001 = new BSHUnaryExpression(JJTUNARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  1);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  1);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/
}

void PreDecrementExpression() :
{ Token t = null; }
{
  t="--" PrimaryExpression()/*@bgen(jjtree) #UnaryExpression( 1) */
    {
      BSHUnaryExpression jjtn001 = new BSHUnaryExpression(JJTUNARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  1);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  1);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/
}

void UnaryExpressionNotPlusMinus() :
{ Token t = null; }
{
  ( t="~" | t="!" ) UnaryExpression()/*@bgen(jjtree) #UnaryExpression( 1) */
    {
      BSHUnaryExpression jjtn001 = new BSHUnaryExpression(JJTUNARYEXPRESSION);
      boolean jjtc001 = true;
      jjtree.openNodeScope(jjtn001);
      jjtreeOpenNodeScope(jjtn001);
    }
    try {
/*@egen*//*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn001,  1);
      jjtc001 = false;
      jjtreeCloseNodeScope(jjtn001);
    }
/*@egen*/
    { jjtn001.kind = t.kind; }/*@bgen(jjtree)*/
    } finally {
      if (jjtc001) {
        jjtree.closeNodeScope(jjtn001,  1);
        jjtreeCloseNodeScope(jjtn001);
      }
    }
/*@egen*/
|
	// SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( CastLookahead() ) CastExpression()
|
  PostfixExpression()
}

// This production is to determine lookahead only.
void CastLookahead() : { }
{
  LOOKAHEAD(2) "(" PrimitiveType()
|
// SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( "(" AmbiguousName() "[" ) "(" AmbiguousName() "[" "]"
|
  "(" AmbiguousName() ")" ( "~" | "!" | "(" | <IDENTIFIER> | /* "this" | "super" | */ "new" | Literal() )
}

void PostfixExpression() :
{ Token t = null; }
{
// SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( PrimaryExpression() ("++"|"--") )
  PrimaryExpression()
	  ( t="++" | t="--" )/*@bgen(jjtree) #UnaryExpression( 1) */
                              {
                                BSHUnaryExpression jjtn001 = new BSHUnaryExpression(JJTUNARYEXPRESSION);
                                boolean jjtc001 = true;
                                jjtree.openNodeScope(jjtn001);
                                jjtreeOpenNodeScope(jjtn001);
                              }
                              try {
/*@egen*//*@bgen(jjtree)*/
                              {
                                jjtree.closeNodeScope(jjtn001,  1);
                                jjtc001 = false;
                                jjtreeCloseNodeScope(jjtn001);
                              }
/*@egen*/ {
		jjtn001.kind = t.kind; jjtn001.postfix = true; }/*@bgen(jjtree)*/
                              } finally {
                                if (jjtc001) {
                                  jjtree.closeNodeScope(jjtn001,  1);
                                  jjtreeCloseNodeScope(jjtn001);
                                }
                              }
/*@egen*/
|
  PrimaryExpression()
}

void CastExpression()                 :
{/*@bgen(jjtree) CastExpression */
  BSHCastExpression jjtn000 = new BSHCastExpression(JJTCASTEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) CastExpression */
  try {
/*@egen*/
// SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( "(" PrimitiveType() ) "(" Type() ")" UnaryExpression()
|
  "(" Type() ")" UnaryExpressionNotPlusMinus()/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void PrimaryExpression()                    : {/*@bgen(jjtree) PrimaryExpression */
  BSHPrimaryExpression jjtn000 = new BSHPrimaryExpression(JJTPRIMARYEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) PrimaryExpression */
  try {
/*@egen*/
  PrimaryPrefix() ( PrimarySuffix() )*/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void MethodInvocation()                   : {/*@bgen(jjtree) MethodInvocation */
  BSHMethodInvocation jjtn000 = new BSHMethodInvocation(JJTMETHODINVOCATION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) MethodInvocation */
   try {
/*@egen*/
   AmbiguousName() Arguments()/*@bgen(jjtree)*/
   } catch (Throwable jjte000) {
     if (jjtc000) {
       jjtree.clearNodeScope(jjtn000);
       jjtc000 = false;
     } else {
       jjtree.popNode();
     }
     if (jjte000 instanceof RuntimeException) {
       throw (RuntimeException)jjte000;
     }
     if (jjte000 instanceof ParseException) {
       throw (ParseException)jjte000;
     }
     throw (Error)jjte000;
   } finally {
     if (jjtc000) {
       jjtree.closeNodeScope(jjtn000, true);
       jjtreeCloseNodeScope(jjtn000);
     }
   }
/*@egen*/
}

void PrimaryPrefix() : { }
{
  Literal()
|
  "(" Expression() ")"
|
  AllocationExpression()
|
  // SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( MethodInvocation() )
	MethodInvocation()
|
  LOOKAHEAD( Type() "." "class" )
	Type()
|
  AmbiguousName()

/*
|
  LOOKAHEAD( "void" "." "class" )
*/
}

void PrimarySuffix()                :
{/*@bgen(jjtree) PrimarySuffix */
    BSHPrimarySuffix jjtn000 = new BSHPrimarySuffix(JJTPRIMARYSUFFIX);
    boolean jjtc000 = true;
    jjtree.openNodeScope(jjtn000);
    jjtreeOpenNodeScope(jjtn000);
/*@egen*/
    Token t = null;
}
{/*@bgen(jjtree) PrimarySuffix */
  try {
/*@egen*/
  LOOKAHEAD(2)
  "." "class"/*@bgen(jjtree)*/
              {
                jjtree.closeNodeScope(jjtn000, true);
                jjtc000 = false;
                jjtreeCloseNodeScope(jjtn000);
              }
/*@egen*/ {
        jjtn000.operation = BSHPrimarySuffix.CLASS;
    }
|
  "[" Expression() "]"/*@bgen(jjtree)*/
                       {
                         jjtree.closeNodeScope(jjtn000, true);
                         jjtc000 = false;
                         jjtreeCloseNodeScope(jjtn000);
                       }
/*@egen*/ {
        jjtn000.operation = BSHPrimarySuffix.INDEX;
    }
|
    // Field access or method invocation
  "." t = <IDENTIFIER> [ Arguments() ]/*@bgen(jjtree)*/
                                       {
                                         jjtree.closeNodeScope(jjtn000, true);
                                         jjtc000 = false;
                                         jjtreeCloseNodeScope(jjtn000);
                                       }
/*@egen*/ {
        jjtn000.operation = BSHPrimarySuffix.NAME;
        jjtn000.field = t.image;
    }
|
  "{" Expression() "}"/*@bgen(jjtree)*/
                       {
                         jjtree.closeNodeScope(jjtn000, true);
                         jjtc000 = false;
                         jjtreeCloseNodeScope(jjtn000);
                       }
/*@egen*/ {
        jjtn000.operation = BSHPrimarySuffix.PROPERTY;
    }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
/*
    For inner classes
|
  LOOKAHEAD(2)
  "." AllocationExpression()
*/
}

void Literal()          :
{/*@bgen(jjtree) Literal */
    BSHLiteral jjtn000 = new BSHLiteral(JJTLITERAL);
    boolean jjtc000 = true;
    jjtree.openNodeScope(jjtn000);
    jjtreeOpenNodeScope(jjtn000);
/*@egen*/
    Token x;
    boolean b;
    String literal;
    char ch;
}
{/*@bgen(jjtree) Literal */
  try {
/*@egen*/
  x = <INTEGER_LITERAL>/*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    jjtreeCloseNodeScope(jjtn000);
  }
/*@egen*/
  {
    literal = x.image;
    ch = literal.charAt(literal.length()-1);
    if(ch == 'l' || ch == 'L')
    {
        literal = literal.substring(0,literal.length()-1);
        jjtn000.value = new Primitive( Long.decode(literal).longValue() );

    }
    else
		try {
        	jjtn000.value = new Primitive(
				Integer.decode( literal ).intValue() );
		} catch ( NumberFormatException e ) {
			throw createParseException(
				"Error or number too big for integer type: "+ literal );
		}
  }
|
  x = <FLOATING_POINT_LITERAL>/*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    jjtreeCloseNodeScope(jjtn000);
  }
/*@egen*/
  {
    literal = x.image;
    ch = literal.charAt(literal.length()-1);
    if(ch == 'f' || ch == 'F')
    {
        literal = literal.substring(0,literal.length()-1);
        jjtn000.value = new Primitive( new Float( literal ).floatValue() );
    }
    else
    {
        if(ch == 'd' || ch == 'D')
            literal = literal.substring(0,literal.length()-1);

        jjtn000.value = new Primitive( new Double( literal ).doubleValue() );
    }
  }
|
  x = <CHARACTER_LITERAL>/*@bgen(jjtree)*/
                          {
                            jjtree.closeNodeScope(jjtn000, true);
                            jjtc000 = false;
                            jjtreeCloseNodeScope(jjtn000);
                          }
/*@egen*/ {
		try {
    		jjtn000.charSetup( x.image.substring(1, x.image.length() - 1) );
		} catch ( Exception e ) {
			throw createParseException("Error parsing character: "+x.image);
		}
    }
|
  x = <STRING_LITERAL>/*@bgen(jjtree)*/
                       {
                         jjtree.closeNodeScope(jjtn000, true);
                         jjtc000 = false;
                         jjtreeCloseNodeScope(jjtn000);
                       }
/*@egen*/ {
		try {
			jjtn000.stringSetup( x.image.substring(1, x.image.length() - 1) );
		} catch ( Exception e ) {
			throw createParseException("Error parsing string: "+x.image);
		}
    }
|
  b = BooleanLiteral()/*@bgen(jjtree)*/
                        {
                          jjtree.closeNodeScope(jjtn000, true);
                          jjtc000 = false;
                          jjtreeCloseNodeScope(jjtn000);
                        }
/*@egen*/  {
    jjtn000.value = b ? Primitive.TRUE : Primitive.FALSE; }
|
  NullLiteral()/*@bgen(jjtree)*/
                {
                  jjtree.closeNodeScope(jjtn000, true);
                  jjtc000 = false;
                  jjtreeCloseNodeScope(jjtn000);
                }
/*@egen*/ {
    jjtn000.value = Primitive.NULL;
}
|
 VoidLiteral()/*@bgen(jjtree)*/
               {
                 jjtree.closeNodeScope(jjtn000, true);
                 jjtc000 = false;
                 jjtreeCloseNodeScope(jjtn000);
               }
/*@egen*/ {
    jjtn000.value = Primitive.VOID; }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

boolean BooleanLiteral() :
{}
{
  "true" { return true; }
|
  "false" { return false; }
}

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

void VoidLiteral() :
{}
{
  "void"
}

void Arguments()            :
{/*@bgen(jjtree) Arguments */
  BSHArguments jjtn000 = new BSHArguments(JJTARGUMENTS);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) Arguments */
  try {
/*@egen*/
  "(" [ ArgumentList()  ]  ")"/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

// leave these on the stack for Arguments() to handle
void ArgumentList() :
{ }
{
  Expression()
  ( "," Expression() )*
}

void AllocationExpression()                       :
{/*@bgen(jjtree) AllocationExpression */
  BSHAllocationExpression jjtn000 = new BSHAllocationExpression(JJTALLOCATIONEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ }
{/*@bgen(jjtree) AllocationExpression */
  try {
/*@egen*/
  LOOKAHEAD(2)
  "new" PrimitiveType() ArrayDimensions()
|
  "new" AmbiguousName()
	(
		ArrayDimensions()
	|
		// SYNTACTIC_LOOKAHEAD
		Arguments() [ LOOKAHEAD(2) Block() ]
	)/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void ArrayDimensions()                  :
{/*@bgen(jjtree) ArrayDimensions */
  BSHArrayDimensions jjtn000 = new BSHArrayDimensions(JJTARRAYDIMENSIONS);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) ArrayDimensions */
  try {
/*@egen*/
	// e.g. int [4][3][][];
  LOOKAHEAD(2)
  ( LOOKAHEAD(2) "[" Expression() "]" { jjtn000.addDefinedDimension(); } )+
  ( LOOKAHEAD(2) "[" "]" { jjtn000.addUndefinedDimension(); } )*
|
	// e.g. int [][] { {1,2}, {3,4} };
  ( "[" "]" { jjtn000.addUndefinedDimension(); } )+ ArrayInitializer()/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}


/*
 * Statement syntax follows.
 */

void Statement() : { }
{
  LOOKAHEAD(2)
  LabeledStatement()
|
  Block()
|
  EmptyStatement()
|
  StatementExpression() ";"
|
  SwitchStatement()
|
  IfStatement()
|
  WhileStatement()
|
  DoStatement()
|
  LOOKAHEAD ( { isRegularForStatement() } )
  ForStatement()
|
  EnhancedForStatement()
|
  BreakStatement()
|
  ContinueStatement()
|
  ReturnStatement()
|
  SynchronizedStatement()
|
  ThrowStatement()
|
  TryStatement()
}

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

void Block()        :
{/*@bgen(jjtree) Block */
        BSHBlock jjtn000 = new BSHBlock(JJTBLOCK);
        boolean jjtc000 = true;
        jjtree.openNodeScope(jjtn000);
        jjtreeOpenNodeScope(jjtn000);
/*@egen*/
	Token s = null;
}
{/*@bgen(jjtree) Block */
        try {
/*@egen*/
/*
	Doing "static" blocks here means that we'll have to throw runtime
	exceptions if it's not used in an appropriate place.
	Is it worth moving the grammar around to make this a static parse time
	check?  (Sreeni? ;) )
*/
	[ s = "static" ] "{" ( BlockStatement() )* "}"/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/
	{
		if ( s != null ) jjtn000.isStatic = true;
	}/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

void BlockStatement() :
{
}
{
  LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) ( "class" | "interface" ) )
  ClassDeclaration()
|
  LOOKAHEAD ( Modifiers( Modifiers.METHOD, true )
		ReturnType() <IDENTIFIER> "("
  )
  	MethodDeclaration()
|
  LOOKAHEAD ( Modifiers( Modifiers.METHOD, true )
		<IDENTIFIER> FormalParameters() [ "throws" NameList() ] "{"
  )
  	MethodDeclaration()
|
  // SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) Type() <IDENTIFIER> )
  TypedVariableDeclaration() ";"
|
  Statement()

|
  // Allow BeanShell imports in any block
  ImportDeclaration()
|
  // Allow BeanShell package declarations in any block
  PackageDeclaration()
|
  FormalComment()
}

void FormalComment()                                  :
{/*@bgen(jjtree) #FormalComment( retainComments) */
        BSHFormalComment jjtn000 = new BSHFormalComment(JJTFORMALCOMMENT);
        boolean jjtc000 = true;
        jjtree.openNodeScope(jjtn000);
        jjtreeOpenNodeScope(jjtn000);
/*@egen*/
	Token t;
}
{/*@bgen(jjtree) #FormalComment( retainComments) */
        try {
/*@egen*/
	t=<FORMAL_COMMENT>/*@bgen(jjtree)*/
                            {
                              jjtree.closeNodeScope(jjtn000,  retainComments);
                              jjtc000 = false;
                              jjtreeCloseNodeScope(jjtn000);
                            }
/*@egen*/  {
		jjtn000.text=t.image;
	}/*@bgen(jjtree)*/
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000,  retainComments);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

void EmptyStatement() :
{}
{
  ";"
}

void StatementExpression() :
{ }
{
  /*
	This is looser than normal Java to simplify the grammar.  This allows
	us to type arbitrary expressions on the command line, e.g. "1+1;"
	We should turn this off in the implementation in strict java mode.
  */
  Expression()
/*
	// This was the original Java grammar.

	//  Original comment:
	//  The last expansion of this production accepts more than the legal
	//  Java expansions for StatementExpression.
	  PreIncrementExpression()
	|
	  PreDecrementExpression()
	|
	  // SYNTACTIC_LOOKAHEAD
	  LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
	  Assignment() { }
	|
	  PostfixExpression()
*/

}

void SwitchStatement()                  :
{/*@bgen(jjtree) SwitchStatement */
  BSHSwitchStatement jjtn000 = new BSHSwitchStatement(JJTSWITCHSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) SwitchStatement */
  try {
/*@egen*/
  "switch" "(" Expression() ")" "{"
    ( SwitchLabel() ( BlockStatement() )* )*
  "}"/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void SwitchLabel()              :
{/*@bgen(jjtree) SwitchLabel */
  BSHSwitchLabel jjtn000 = new BSHSwitchLabel(JJTSWITCHLABEL);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) SwitchLabel */
  try {
/*@egen*/
  "case" Expression() ":"
|
  "default" ":"/*@bgen(jjtree)*/
                {
                  jjtree.closeNodeScope(jjtn000, true);
                  jjtc000 = false;
                  jjtreeCloseNodeScope(jjtn000);
                }
/*@egen*/ { jjtn000.isDefault = true; }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

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.
 */
{/*@bgen(jjtree) IfStatement */
  BSHIfStatement jjtn000 = new BSHIfStatement(JJTIFSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) IfStatement */
  try {
/*@egen*/
  "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void WhileStatement()                 :
{/*@bgen(jjtree) WhileStatement */
  BSHWhileStatement jjtn000 = new BSHWhileStatement(JJTWHILESTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) WhileStatement */
  try {
/*@egen*/
  "while" "(" Expression() ")" Statement()/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

/*
	Do statement is just a While statement with a special hook to execute
	at least once.
*/
void DoStatement()                 :
{/*@bgen(jjtree) WhileStatement */
  BSHWhileStatement jjtn000 = new BSHWhileStatement(JJTWHILESTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) WhileStatement */
  try {
/*@egen*/
  "do" Statement() "while" "(" Expression() ")" ";"/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/
	{ jjtn000.isDoStatement=true;  }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void ForStatement()               :
{/*@bgen(jjtree) ForStatement */
  BSHForStatement jjtn000 = new BSHForStatement(JJTFORSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ Token t = null; }
{/*@bgen(jjtree) ForStatement */
  try {
/*@egen*/
  "for" "(" [ ForInit() { jjtn000.hasForInit=true; } ]
    ";" [ Expression() { jjtn000.hasExpression=true; } ]
    ";" [ ForUpdate() { jjtn000.hasForUpdate=true; } ] ")"
    Statement()/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

/*
	The new JDK1.5 enhanced for statement.
	e.g. for( int a : arrayOfInts ) { }
	We also support loose typing of the iterator var for BeanShell
	e.g. for( a : arrayOfInts ) { }
*/
void EnhancedForStatement()                       :
{/*@bgen(jjtree) EnhancedForStatement */
  BSHEnhancedForStatement jjtn000 = new BSHEnhancedForStatement(JJTENHANCEDFORSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ Token t = null; }
{/*@bgen(jjtree) EnhancedForStatement */
  try {
/*@egen*/
  LOOKAHEAD( 4 ) // look ahead for the ":" before deciding
  "for" "(" t=<IDENTIFIER> ":" Expression() ")"
    Statement()/*@bgen(jjtree)*/
                {
                  jjtree.closeNodeScope(jjtn000, true);
                  jjtc000 = false;
                  jjtreeCloseNodeScope(jjtn000);
                }
/*@egen*/ { jjtn000.varName = t.image; }
  |
  "for" "(" Type() t=<IDENTIFIER> ":" Expression() ")"
    Statement()/*@bgen(jjtree)*/
                {
                  jjtree.closeNodeScope(jjtn000, true);
                  jjtc000 = false;
                  jjtreeCloseNodeScope(jjtn000);
                }
/*@egen*/ { jjtn000.varName = t.image; }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void ForInit() :
{ Token t = null; }
{
// SYNTACTIC_LOOKAHEAD
  LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) Type() <IDENTIFIER> )
  TypedVariableDeclaration()
|
  StatementExpressionList()
}

/**
	Declared a typed variable.
	Untyped variables are not declared per-se but are handled by the part
	of the grammar that deals with assignments.
*/
void TypedVariableDeclaration()                           :
{/*@bgen(jjtree) TypedVariableDeclaration */
        BSHTypedVariableDeclaration jjtn000 = new BSHTypedVariableDeclaration(JJTTYPEDVARIABLEDECLARATION);
        boolean jjtc000 = true;
        jjtree.openNodeScope(jjtn000);
        jjtreeOpenNodeScope(jjtn000);
/*@egen*/
	Token t = null;
	Modifiers mods;
}
{/*@bgen(jjtree) TypedVariableDeclaration */
        try {
/*@egen*/
	mods = Modifiers( Modifiers.FIELD, false )
  	Type() VariableDeclarator() ( "," VariableDeclarator() )*/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/
	{
        jjtn000.modifiers = mods;
    }/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}

void StatementExpressionList()                          :
{/*@bgen(jjtree) StatementExpressionList */
  BSHStatementExpressionList jjtn000 = new BSHStatementExpressionList(JJTSTATEMENTEXPRESSIONLIST);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) StatementExpressionList */
  try {
/*@egen*/
  StatementExpression() ( "," StatementExpression() )*/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

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

void BreakStatement()                  :
{/*@bgen(jjtree) ReturnStatement */
  BSHReturnStatement jjtn000 = new BSHReturnStatement(JJTRETURNSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) ReturnStatement */
  try {
/*@egen*/
  "break" [ <IDENTIFIER> ] ";"/*@bgen(jjtree)*/
                               {
                                 jjtree.closeNodeScope(jjtn000, true);
                                 jjtc000 = false;
                                 jjtreeCloseNodeScope(jjtn000);
                               }
/*@egen*/ { jjtn000.kind = BREAK; }/*@bgen(jjtree)*/
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void ContinueStatement()                  :
{/*@bgen(jjtree) ReturnStatement */
  BSHReturnStatement jjtn000 = new BSHReturnStatement(JJTRETURNSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) ReturnStatement */
  try {
/*@egen*/
  "continue" [ <IDENTIFIER> ] ";"/*@bgen(jjtree)*/
                                  {
                                    jjtree.closeNodeScope(jjtn000, true);
                                    jjtc000 = false;
                                    jjtreeCloseNodeScope(jjtn000);
                                  }
/*@egen*/ { jjtn000.kind = CONTINUE; }/*@bgen(jjtree)*/
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void ReturnStatement()                  :
{/*@bgen(jjtree) ReturnStatement */
  BSHReturnStatement jjtn000 = new BSHReturnStatement(JJTRETURNSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) ReturnStatement */
  try {
/*@egen*/
  "return" [ Expression() ] ";"/*@bgen(jjtree)*/
                                {
                                  jjtree.closeNodeScope(jjtn000, true);
                                  jjtc000 = false;
                                  jjtreeCloseNodeScope(jjtn000);
                                }
/*@egen*/ { jjtn000.kind = RETURN; }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void SynchronizedStatement()        :
{/*@bgen(jjtree) Block */
  BSHBlock jjtn000 = new BSHBlock(JJTBLOCK);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/
}
{/*@bgen(jjtree) Block */
  try {
/*@egen*/
  "synchronized" "(" Expression() ")" Block()/*@bgen(jjtree)*/
                                              {
                                                jjtree.closeNodeScope(jjtn000, true);
                                                jjtc000 = false;
                                                jjtreeCloseNodeScope(jjtn000);
                                              }
/*@egen*/ {
  		jjtn000.isSynchronized=true;
  }/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void ThrowStatement()                 :
{/*@bgen(jjtree) ThrowStatement */
  BSHThrowStatement jjtn000 = new BSHThrowStatement(JJTTHROWSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/}
{/*@bgen(jjtree) ThrowStatement */
  try {
/*@egen*/
  "throw" Expression() ";"/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
      jjtreeCloseNodeScope(jjtn000);
    }
  }
/*@egen*/
}

void TryStatement()              :
/*
	Semantic check required here to make sure that at least one
	finally/catch is present.  (You can have a try with finally and no catch).
 */
{/*@bgen(jjtree) TryStatement */
  BSHTryStatement jjtn000 = new BSHTryStatement(JJTTRYSTATEMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
  jjtreeOpenNodeScope(jjtn000);
/*@egen*/ boolean closed = false; }
{/*@bgen(jjtree) TryStatement */
        try {
/*@egen*/
	"try" Block()
	( "catch" "(" FormalParameter() ")" Block() { closed = true; } )*
	[ "finally" Block() { closed = true; } ]/*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtreeCloseNodeScope(jjtn000);
        }
/*@egen*/
	{
		if ( !closed ) throw generateParseException();
	}/*@bgen(jjtree)*/
        } catch (Throwable jjte000) {
          if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            throw (RuntimeException)jjte000;
          }
          if (jjte000 instanceof ParseException) {
            throw (ParseException)jjte000;
          }
          throw (Error)jjte000;
        } finally {
          if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
            jjtreeCloseNodeScope(jjtn000);
          }
        }
/*@egen*/
}
