PageRenderTime 1851ms CodeModel.GetById 14ms app.highlight 91ms RepoModel.GetById 1ms app.codeStats 1735ms

/jEdit/tags/jedit-4-1-pre5/bsh/bsh.jjt

#
Unknown | 1207 lines | 1100 code | 107 blank | 0 comment | 0 complexity | 2724af6fd88aab12c84965197bc9c7c7 MD5 | raw file
   1/*****************************************************************************
   2 *                                                                           *
   3 *  This file is part of the BeanShell Java Scripting distribution.          *
   4 *  Documentation and updates may be found at http://www.beanshell.org/      *
   5 *                                                                           *
   6 *  Sun Public License Notice:                                               *
   7 *                                                                           *
   8 *  The contents of this file are subject to the Sun Public License Version  *
   9 *  1.0 (the "License"); you may not use this file except in compliance with *
  10 *  the License. A copy of the License is available at http://www.sun.com    * 
  11 *                                                                           *
  12 *  The Original Code is BeanShell. The Initial Developer of the Original    *
  13 *  Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright     *
  14 *  (C) 2000.  All Rights Reserved.                                          *
  15 *                                                                           *
  16 *  GNU Public License Notice:                                               *
  17 *                                                                           *
  18 *  Alternatively, the contents of this file may be used under the terms of  *
  19 *  the GNU Lesser General Public License (the "LGPL"), in which case the    *
  20 *  provisions of LGPL are applicable instead of those above. If you wish to *
  21 *  allow use of your version of this file only under the  terms of the LGPL *
  22 *  and not to allow others to use your version of this file under the SPL,  *
  23 *  indicate your decision by deleting the provisions above and replace      *
  24 *  them with the notice and other provisions required by the LGPL.  If you  *
  25 *  do not delete the provisions above, a recipient may use your version of  *
  26 *  this file under either the SPL or the LGPL.                              *
  27 *                                                                           *
  28 *  Patrick Niemeyer (pat@pat.net)                                           *
  29 *  Author of Learning Java, O'Reilly & Associates                           *
  30 *  http://www.pat.net/~pat/                                                 *
  31 *                                                                           *
  32 *****************************************************************************/
  33
  34/*
  35	Notes:
  36	There is probably a lot of room for improvement in here.
  37	All of the syntactic lookaheads have been commented with:
  38		SYNTACTIC_LOOKAHEAD
  39	These are probably expensive and we may want to start weeding them out
  40	where possible.
  41*/
  42
  43options {
  44    JAVA_UNICODE_ESCAPE=true;
  45    STATIC=false;
  46    MULTI=true;
  47    NODE_DEFAULT_VOID=true;
  48	NODE_SCOPE_HOOK=true;
  49	NODE_PREFIX="BSH";
  50	/* Print grammar debugging info as we parse 
  51	DEBUG_PARSER=true;
  52	*/
  53	/* Print detailed lookahead debugging info
  54	DEBUG_LOOKAHEAD=true;
  55	*/
  56}
  57
  58PARSER_BEGIN(Parser)
  59package bsh;
  60
  61import java.io.Reader;
  62
  63class Parser { 
  64
  65	void jjtreeOpenNodeScope(Node n) {
  66		((SimpleNode)n).firstToken = getToken(1);
  67	}
  68
  69	void jjtreeCloseNodeScope(Node n) {
  70		((SimpleNode)n).lastToken = getToken(0);
  71	}
  72
  73	/**
  74		Re-initialize the input stream and token source.
  75	*/
  76	void reInitInput( Reader in ) {
  77		ReInit(in);
  78	}
  79
  80	/**
  81		Explicitly re-initialize just the token reader.
  82		This seems to be necessary to avoid certain looping errors when
  83		reading bogus input.  See Interpreter.
  84	*/
  85	void reInitTokenInput( Reader in ) {
  86		jj_input_stream.ReInit( in, 
  87			jj_input_stream.getEndLine(), 
  88			jj_input_stream.getEndColumn() );
  89	}
  90
  91}
  92
  93
  94PARSER_END(Parser)
  95
  96SKIP : /* WHITE SPACE */
  97{ 
  98	" " | "\t" | "\r" | "\f"
  99	| "\n" 
 100	| < NONPRINTABLE: (["\u0000"-"\u0020", "\u0080"-"\u00ff"])+ >
 101}
 102
 103SPECIAL_TOKEN : /* COMMENTS */
 104{
 105/*
 106	SINGLE_LINE_COMMENT includes a hack to accept SLC at the end of a file
 107	with no terminanting linefeed.  This is actually illegal according to 
 108	spec, but comes up often enough to warrant it... (especially in eval()).
 109*/
 110  <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
 111| <HASH_BANG_COMMENT: "#!" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
 112| <FORMAL_COMMENT: "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
 113| <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
 114}
 115
 116TOKEN : /* RESERVED WORDS AND LITERALS */
 117{
 118< BOOLEAN: "boolean" >
 119| < BREAK: "break" >
 120| < CLASS: "class" >
 121| < BYTE: "byte" >
 122| < CASE: "case" >
 123| < CATCH: "catch" >
 124| < CHAR: "char" >
 125| < CONST: "const" >
 126| < CONTINUE: "continue" >
 127| < _DEFAULT: "default" >
 128| < DO: "do" >
 129| < DOUBLE: "double" >
 130| < ELSE: "else" >
 131| < FALSE: "false" >
 132| < FINAL: "final" >
 133| < FINALLY: "finally" >
 134| < FLOAT: "float" >
 135| < FOR: "for" >
 136| < GOTO: "goto" >
 137| < IF: "if" >
 138| < IMPORT: "import" >
 139| < INSTANCEOF: "instanceof" >
 140| < INT: "int" >
 141| < INTERFACE: "interface" >
 142| < LONG: "long" >
 143| < NEW: "new" >
 144| < NULL: "null" >
 145| < PRIVATE: "private" >
 146| < PROTECTED: "protected" >
 147| < PUBLIC: "public" >
 148| < RETURN: "return" >
 149| < SHORT: "short" >
 150| < STATIC: "static" >
 151| < SWITCH: "switch" >
 152| < THROW: "throw" >
 153| < TRUE: "true" >
 154| < TRY: "try" >
 155| < VOID: "void" >
 156| < WHILE: "while" >
 157}
 158
 159TOKEN : /* LITERALS */
 160{
 161  < INTEGER_LITERAL:
 162        <DECIMAL_LITERAL> (["l","L"])?
 163      | <HEX_LITERAL> (["l","L"])?
 164      | <OCTAL_LITERAL> (["l","L"])?
 165  >
 166|
 167  < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
 168|
 169  < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
 170|
 171  < #OCTAL_LITERAL: "0" (["0"-"7"])* >
 172|
 173  < FLOATING_POINT_LITERAL:
 174        (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
 175      | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
 176      | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
 177      | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
 178  >
 179|
 180  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
 181|
 182  < CHARACTER_LITERAL:
 183      "'"
 184      (   (~["'","\\","\n","\r"])
 185        | ("\\"
 186            ( ["n","t","b","r","f","\\","'","\""]
 187            | ["0"-"7"] ( ["0"-"7"] )?
 188            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
 189            )
 190          )
 191      )
 192      "'"
 193  >
 194|
 195  < STRING_LITERAL:
 196      "\""
 197      (   (~["\"","\\","\n","\r"])
 198        | ("\\"
 199            ( ["n","t","b","r","f","\\","'","\""]
 200            | ["0"-"7"] ( ["0"-"7"] )?
 201            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
 202            )
 203          )
 204      )*
 205      "\""
 206  >
 207}
 208
 209TOKEN : /* IDENTIFIERS */
 210{
 211  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
 212|
 213  < #LETTER:
 214      [
 215       "\u0024",
 216       "\u0041"-"\u005a",
 217       "\u005f",
 218       "\u0061"-"\u007a",
 219       "\u00c0"-"\u00d6",
 220       "\u00d8"-"\u00f6",
 221       "\u00f8"-"\u00ff",
 222       "\u0100"-"\u1fff",
 223       "\u3040"-"\u318f",
 224       "\u3300"-"\u337f",
 225       "\u3400"-"\u3d2d",
 226       "\u4e00"-"\u9fff",
 227       "\uf900"-"\ufaff"
 228      ]
 229  >
 230|
 231  < #DIGIT:
 232      [
 233       "\u0030"-"\u0039",
 234       "\u0660"-"\u0669",
 235       "\u06f0"-"\u06f9",
 236       "\u0966"-"\u096f",
 237       "\u09e6"-"\u09ef",
 238       "\u0a66"-"\u0a6f",
 239       "\u0ae6"-"\u0aef",
 240       "\u0b66"-"\u0b6f",
 241       "\u0be7"-"\u0bef",
 242       "\u0c66"-"\u0c6f",
 243       "\u0ce6"-"\u0cef",
 244       "\u0d66"-"\u0d6f",
 245       "\u0e50"-"\u0e59",
 246       "\u0ed0"-"\u0ed9",
 247       "\u1040"-"\u1049"
 248      ]
 249  >
 250}
 251
 252TOKEN : /* SEPARATORS */
 253{
 254  < LPAREN: "(" >
 255| < RPAREN: ")" >
 256| < LBRACE: "{" >
 257| < RBRACE: "}" >
 258| < LBRACKET: "[" >
 259| < RBRACKET: "]" >
 260| < SEMICOLON: ";" >
 261| < COMMA: "," >
 262| < DOT: "." >
 263}
 264
 265TOKEN : /* OPERATORS */
 266{
 267  < ASSIGN: "=" >
 268| < GT: ">" >
 269| < GTX: "@gt" >
 270| < LT: "<" >
 271| < LTX: "@lt" >
 272| < BANG: "!" >
 273| < TILDE: "~" >
 274| < HOOK: "?" >
 275| < COLON: ":" >
 276| < EQ: "==" >
 277| < LE: "<=" >
 278| < LEX: "@lteq" >
 279| < GE: ">=" >
 280| < GEX: "@gteq" >
 281| < NE: "!=" >
 282| < BOOL_OR: "||" >
 283| < BOOL_ORX: "@or" >
 284| < BOOL_AND: "&&" >
 285| < BOOL_ANDX: "@and" >
 286| < INCR: "++" >
 287| < DECR: "--" >
 288| < PLUS: "+" >
 289| < MINUS: "-" >
 290| < STAR: "*" >
 291| < SLASH: "/" >
 292| < BIT_AND: "&" >
 293| < BIT_ANDX: "@bitwise_and" >
 294| < BIT_OR: "|" >
 295| < BIT_ORX: "@bitwise_or" >
 296| < XOR: "^" >
 297| < MOD: "%" >
 298| < LSHIFT: "<<" >
 299| < LSHIFTX: "@left_shift" >
 300| < RSIGNEDSHIFT: ">>" >
 301| < RSIGNEDSHIFTX: "@right_shift" >
 302| < RUNSIGNEDSHIFT: ">>>" >
 303| < RUNSIGNEDSHIFTX: "@right_unsigned_shift" >
 304| < PLUSASSIGN: "+=" >
 305| < MINUSASSIGN: "-=" >
 306| < STARASSIGN: "*=" >
 307| < SLASHASSIGN: "/=" >
 308| < ANDASSIGN: "&=" >
 309| < ANDASSIGNX: "@and_assign" >
 310| < ORASSIGN: "|=" >
 311| < ORASSIGNX: "@or_assign" >
 312| < XORASSIGN: "^=" >
 313| < MODASSIGN: "%=" >
 314| < LSHIFTASSIGN: "<<=" >
 315| < LSHIFTASSIGNX: "@left_shift_assign" >
 316| < RSIGNEDSHIFTASSIGN: ">>=" >
 317| < RSIGNEDSHIFTASSIGNX: "@right_shift_assign" >
 318| < RUNSIGNEDSHIFTASSIGN: ">>>=" >
 319| < RUNSIGNEDSHIFTASSIGNX: "@right_unsigned_shift_assign" >
 320}
 321
 322
 323boolean Line() :
 324{}
 325{
 326  <EOF> { 
 327	Interpreter.debug("End of File!"); 
 328	return true; 
 329	}
 330|
 331  (
 332	/*
 333		SYNTACTIC_LOOKAHEAD
 334		I'm guessing this is expensive, but I don't know how to work around
 335		it...  Is there another syntactic indication that we are working 
 336		through an expression as opposed to a statement?
 337		What is the difference?  Well, some statements don't require a
 338		semicolon and they don't return vlues...  We could probably broaden
 339		bsh to allow everything to return a value, but the semi-colon thing
 340		is tougher.  You don't want to have to say if ( foo ) { } ;
 341		Maybe we can invert ths and enumerate all of those types of 
 342		statements in a special lookahead that's cheaper??
 343	*/
 344   LOOKAHEAD( Expression() ";" )
 345   Expression() ";" 
 346  |
 347   BlockStatement()
 348  )
 349	{ 
 350		return false; 
 351	}
 352}
 353
 354/*****************************************
 355 * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
 356 *****************************************/
 357
 358void MethodDeclaration() #MethodDeclaration :
 359{ Token t = null; }
 360{
 361	// SYNTACTIC_LOOKAHEAD
 362	// this one seems cheap enough
 363    LOOKAHEAD( MethodDeclarationTypeLookahead() )
 364    ReturnType() t = <IDENTIFIER> { jjtThis.name = t.image; }
 365    FormalParameters() Block()
 366|
 367    t = <IDENTIFIER> { jjtThis.name = t.image; }
 368    FormalParameters() Block()
 369}
 370
 371void MethodDeclarationLookahead() : { }
 372{
 373	// SYNTACTIC_LOOKAHEAD
 374	// this one seems cheap enough
 375    LOOKAHEAD( MethodDeclarationTypeLookahead() )
 376    ReturnType() <IDENTIFIER> FormalParameters() "{"
 377|
 378    <IDENTIFIER> FormalParameters() "{"
 379}
 380
 381void MethodDeclarationTypeLookahead() : { }
 382{
 383    ReturnType() <IDENTIFIER> "("
 384}
 385
 386void ImportDeclaration() #ImportDeclaration :
 387{
 388    Token t = null;
 389}
 390{
 391  LOOKAHEAD( 2 )
 392
 393  "import" AmbiguousName() [ t = "." "*" ] ";" {
 394    if ( t != null )
 395        jjtThis.importPackage = true;
 396    }
 397  |
 398	// bsh super import statement
 399  "import" "*" ";" {
 400		jjtThis.superImport = true;
 401	}
 402}
 403
 404void VariableDeclarator() #VariableDeclarator :
 405{ Token t; }
 406{
 407  t=<IDENTIFIER> [ "=" VariableInitializer() ] { jjtThis.name = t.image; }
 408}
 409
 410/*
 411Can get rid of this if we ignore postfix array dimensions in declarations.
 412I don't like them and I don't want to deal with them right now.
 413
 414void VariableDeclaratorId() #VariableDeclaratorId :
 415{ Token t; }
 416{
 417  t=<IDENTIFIER> { jjtThis.name = t.image; }
 418  ( "[" "]" { jjtThis.addArrayDimension(); } )*
 419}
 420*/
 421
 422void VariableInitializer() :
 423{}
 424{
 425  ArrayInitializer()
 426|
 427  Expression()
 428}
 429
 430void ArrayInitializer() #ArrayInitializer :
 431{}
 432{
 433  "{" [ VariableInitializer() 
 434		( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
 435}
 436
 437void FormalParameters() #FormalParameters :
 438{}
 439{
 440  "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
 441}
 442
 443/*
 444void FormalParameter() #FormalParameter :
 445{ Token t; }
 446{
 447    // added [] to Type for bsh.  Removed [ final ] - is that legal?
 448  [ LOOKAHEAD(2) Type() ] t=<IDENTIFIER> { jjtThis.name = t.image; }
 449}
 450*/
 451void FormalParameter() #FormalParameter :
 452{ Token t; }
 453{
 454  // added [] to Type for bsh.  Removed [ final ] - is that legal?
 455  LOOKAHEAD(2) Type() t=<IDENTIFIER> { jjtThis.name = t.image; }
 456|
 457  t=<IDENTIFIER> { jjtThis.name = t.image; }
 458}
 459
 460
 461/*
 462	Type, name and expression syntax follows.
 463*/
 464void Type() #Type :
 465{ }
 466{
 467	/* 
 468		The embedded lookahead is (was?) necessary to disambiguate for
 469		PrimaryPrefix.  ( )* is a choice point.  It took me a while to
 470		figure out where to put that.  This stuff is annoying.
 471	*/
 472  ( PrimitiveType() | AmbiguousName() ) 
 473	( LOOKAHEAD(2) "[" "]" { jjtThis.addArrayDimension(); } )* 
 474}
 475
 476/*
 477	Originally called ResultType in the grammar
 478*/
 479void ReturnType() #ReturnType :
 480{ }
 481{
 482  "void" { jjtThis.isVoid = true; }
 483|
 484  Type()
 485}
 486
 487void PrimitiveType() #PrimitiveType :
 488{ } {
 489"boolean" { jjtThis.type = Boolean.TYPE; }
 490| "char" { jjtThis.type =  Character.TYPE; }
 491| "byte" { jjtThis.type =  Byte.TYPE; }
 492| "short" { jjtThis.type =  Short.TYPE; }
 493| "int" { jjtThis.type =  Integer.TYPE; }
 494| "long" { jjtThis.type =  Long.TYPE; }
 495| "float" { jjtThis.type =  Float.TYPE; }
 496| "double" { jjtThis.type =  Double.TYPE; }
 497}
 498
 499void AmbiguousName() #AmbiguousName :
 500/*
 501 * A lookahead of 2 is required below since "Name" can be followed
 502 * by a ".*" when used in the context of an "ImportDeclaration".
 503 */
 504{
 505    Token t;
 506    StringBuffer s;
 507}
 508{
 509  t = <IDENTIFIER> {
 510        s = new StringBuffer(t.image);
 511    }
 512  ( LOOKAHEAD(2) "." t = <IDENTIFIER> {
 513        s.append("."+t.image);
 514    }
 515  )* {
 516        jjtThis.text = s.toString();
 517    }
 518}
 519
 520/*
 521 * Expression syntax follows.
 522 */
 523void Expression() :
 524{ }
 525{
 526	/**
 527		SYNTACTIC_LOOKAHEAD
 528		This is probably expensive.  Can we simplify it somehow?
 529	*/
 530  LOOKAHEAD( LHSPrimaryExpression() AssignmentOperator() )
 531  Assignment()
 532|
 533  ConditionalExpression()
 534}
 535
 536void Assignment() #Assignment :
 537{ int op ; }
 538{
 539  LHSPrimaryExpression()
 540  op = AssignmentOperator() {
 541    jjtThis.operator = op;
 542  }
 543  Expression()
 544}
 545
 546int AssignmentOperator() :
 547{ Token t; }
 548{
 549    ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&=" | "^=" | "|=" |
 550      "<<=" | "@left_shift_assign" | ">>=" | "@right_shift_assign" |
 551      ">>>=" | "@right_unsigned_shift_assign" )
 552    {
 553        t = getToken(0);
 554        return t.kind;
 555    }
 556}
 557
 558void ConditionalExpression() : 
 559{ }
 560{
 561  ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression() 
 562	#TernaryExpression(3) ]
 563}
 564
 565void ConditionalOrExpression() :
 566{ Token t=null; }
 567{
 568  ConditionalAndExpression()
 569  ( ( t = "||" | t = "@or" )
 570    ConditionalAndExpression()
 571    { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 572}
 573
 574void ConditionalAndExpression() :
 575{ Token t=null; }
 576{
 577  InclusiveOrExpression()
 578  ( ( t = "&&" | t = "@and" )
 579    InclusiveOrExpression()
 580    { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 581}
 582
 583void InclusiveOrExpression() :
 584{ Token t=null; }
 585{
 586  ExclusiveOrExpression()
 587  ( ( t = "|" | t = "@bitwise_or" )
 588    ExclusiveOrExpression()
 589    { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 590}
 591
 592void ExclusiveOrExpression() :
 593{ Token t=null; }
 594{
 595  AndExpression() ( t="^" AndExpression()
 596    { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 597}
 598
 599void AndExpression() :
 600{ Token t=null; }
 601{
 602  EqualityExpression()
 603  ( ( t = "&" | t = "@bitwise_and" )
 604    EqualityExpression()
 605    { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 606}
 607
 608void EqualityExpression() :
 609{ Token t = null; }
 610{
 611  InstanceOfExpression() ( ( t= "==" | t= "!=" ) InstanceOfExpression()
 612    { jjtThis.kind = t.kind; } #BinaryExpression(2)
 613  )*
 614}
 615
 616void InstanceOfExpression() :
 617{ Token t = null; }
 618{
 619  RelationalExpression()
 620  [ t = "instanceof" Type() { jjtThis.kind = t.kind; } #BinaryExpression(2) ]
 621}
 622
 623void RelationalExpression() :
 624{ Token t = null; }
 625{
 626  ShiftExpression()
 627  ( ( t = "<" | t = "@lt" | t = ">" | t = "@gt" |
 628      t = "<=" | t = "@lteq" | t = ">=" | t = "@gteq" )
 629  ShiftExpression()
 630  { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 631}
 632
 633void ShiftExpression() :
 634{ Token t = null; }
 635{
 636  AdditiveExpression()
 637  ( ( t = "<<" | t = "@left_shift" | t = ">>" | t = "@right_shift" |
 638      t = ">>>" | t = "@right_unsigned_shift" )
 639  AdditiveExpression()
 640  { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 641}
 642
 643void AdditiveExpression() :
 644{ Token t = null; }
 645{
 646  MultiplicativeExpression()
 647  ( ( t= "+" | t= "-" ) MultiplicativeExpression() { jjtThis.kind = t.kind; }
 648    #BinaryExpression(2)
 649  )*
 650}
 651
 652void MultiplicativeExpression() :
 653{ Token t = null; }
 654{
 655  UnaryExpression() ( ( t= "*" | t= "/" | t= "%" )
 656  UnaryExpression() { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
 657}
 658
 659void UnaryExpression() :
 660{ Token t = null; }
 661{
 662  ( t="+" | t="-" ) UnaryExpression()
 663    { jjtThis.kind = t.kind; } #UnaryExpression(1)
 664|
 665  PreIncrementExpression()
 666|
 667  PreDecrementExpression()
 668|
 669  UnaryExpressionNotPlusMinus()
 670}
 671
 672void PreIncrementExpression() :
 673{ Token t = null; }
 674{
 675  t="++" LHSPrimaryExpression()
 676    { jjtThis.kind = t.kind; } #UnaryExpression(1)
 677}
 678
 679void PreDecrementExpression() :
 680{ Token t = null; }
 681{
 682  t="--" LHSPrimaryExpression()
 683    { jjtThis.kind = t.kind; } #UnaryExpression(1)
 684}
 685
 686void UnaryExpressionNotPlusMinus() :
 687{ Token t = null; }
 688{
 689  ( t="~" | t="!" ) UnaryExpression()
 690    { jjtThis.kind = t.kind; } #UnaryExpression(1)
 691|
 692	// SYNTACTIC_LOOKAHEAD
 693  LOOKAHEAD( CastLookahead() ) CastExpression()
 694|
 695  PostfixExpression()
 696}
 697
 698// This production is to determine lookahead only.
 699void CastLookahead() : { }
 700{
 701  LOOKAHEAD(2) "(" PrimitiveType()
 702|
 703// SYNTACTIC_LOOKAHEAD
 704  LOOKAHEAD( "(" AmbiguousName() "[" ) "(" AmbiguousName() "[" "]"
 705|
 706  "(" AmbiguousName() ")" ( "~" | "!" | "(" | <IDENTIFIER> | /* "this" | "super" | */ "new" | Literal() )
 707}
 708
 709void PostfixExpression() :
 710{ Token t = null; }
 711{
 712// SYNTACTIC_LOOKAHEAD
 713  LOOKAHEAD( LHSPrimaryExpression() ("++"|"--") )
 714  LHSPrimaryExpression()
 715	  ( t="++" | t="--" ) { 
 716		jjtThis.kind = t.kind; jjtThis.postfix = true; } #UnaryExpression(1)
 717|
 718  PrimaryExpression()
 719}
 720
 721void CastExpression() #CastExpression :
 722{ }
 723{
 724// SYNTACTIC_LOOKAHEAD
 725  LOOKAHEAD( "(" PrimitiveType() ) "(" Type() ")" UnaryExpression()
 726|
 727  "(" Type() ")" UnaryExpressionNotPlusMinus()
 728}
 729
 730void PrimaryExpression() #PrimaryExpression : { }
 731{
 732  PrimaryPrefix() ( PrimarySuffix() )*
 733}
 734
 735void MethodInvocation() #MethodInvocation : { }
 736{
 737   AmbiguousName() Arguments() 
 738}
 739
 740void PrimaryPrefix() : { }
 741{
 742  Literal()
 743|
 744  "(" Expression() ")"
 745|
 746  AllocationExpression()
 747|
 748  // Careful about the parens here... they are important
 749  // lookahead must apply to the correct choice points
 750(
 751	/*
 752		The MethodInvocation node here simplifies the prefix/suffix parsing a 
 753		bit by forcing the prefix to an object...  That was the idea anyway... 
 754		should probably just move it to the suffix
 755	*/
 756    // SYNTACTIC_LOOKAHEAD
 757    LOOKAHEAD( MethodInvocation() ) MethodInvocation()
 758  |
 759    (
 760      LOOKAHEAD( Type() "." "class" ) 
 761      Type()
 762    |
 763	  AmbiguousName()
 764	)
 765)
 766
 767/*
 768|
 769  LOOKAHEAD( "void" "." "class" )
 770*/
 771}
 772
 773void PrimarySuffix() #PrimarySuffix :
 774{
 775    Token t = null;
 776}
 777{
 778  LOOKAHEAD(2)
 779  "." "class" {
 780        jjtThis.operation = BSHPrimarySuffix.CLASS;
 781    }
 782|
 783  "[" Expression() "]" {
 784        jjtThis.operation = BSHPrimarySuffix.INDEX;
 785    }
 786|
 787    // Field access or method invocation
 788  "." t = <IDENTIFIER> [ Arguments() ] {
 789        jjtThis.operation = BSHPrimarySuffix.NAME;
 790        jjtThis.field = t.image;
 791    }
 792|
 793  "{" Expression() "}" {
 794        jjtThis.operation = BSHPrimarySuffix.PROPERTY;
 795    }
 796/*
 797    For inner classes
 798|
 799  LOOKAHEAD(2)
 800  "." AllocationExpression()
 801*/
 802}
 803
 804
 805/*
 806	Begin LHS part of the grammar --
 807
 808	The reason this stuff is duplicated (e.g. LHSPrimaryPrefix and 
 809	PrimaryPrefix) is that the whole grammar splits based on whether we 
 810	are preparig to do an assignment or not.  This is an important issue 
 811	to revisit in the future.
 812*/
 813/**
 814	The method invocation is here to force this to an object type in order 
 815	to simplify the suffix processing.  
 816*/
 817void LHSPrimaryPrefix() : { }
 818{
 819  // SYNTACTIC_LOOKAHEAD
 820  LOOKAHEAD( MethodInvocation() )
 821  MethodInvocation()
 822|
 823  AmbiguousName()
 824}
 825
 826void LHSPrimaryExpression() #LHSPrimaryExpression : { }
 827{
 828  LHSPrimaryPrefix() ( LHSPrimarySuffix( ) )*
 829}
 830
 831void LHSPrimarySuffix() #LHSPrimarySuffix :
 832{
 833    Token t=null, t1, t2 = null;
 834}
 835{
 836    // Indexed to a field
 837  "[" Expression() "]" {
 838        jjtThis.operation = BSHLHSPrimarySuffix.INDEX;
 839    }
 840|
 841    // Field access or method invocation followed by field access
 842  "." t1 = <IDENTIFIER> [ Arguments() "." t2 = <IDENTIFIER> ] {
 843        jjtThis.operation = BSHLHSPrimarySuffix.NAME;
 844        if ( t2 == null )
 845            jjtThis.field = t1.image;
 846        else {
 847            jjtThis.method = t1.image;
 848            jjtThis.field = t2.image;
 849        }
 850    }
 851|
 852  "{" Expression() "}" {
 853        jjtThis.operation = BSHLHSPrimarySuffix.PROPERTY;
 854    }
 855}
 856
 857/*
 858	-- End LHS part of the grammar
 859*/
 860
 861void Literal() #Literal :
 862{
 863    Token x;
 864    boolean b;
 865    String literal;
 866    char ch;
 867}
 868{
 869  x = <INTEGER_LITERAL>
 870  {
 871    literal = x.image;
 872    ch = literal.charAt(literal.length()-1);
 873    if(ch == 'l' || ch == 'L')
 874    {
 875        literal = literal.substring(0,literal.length()-1);
 876
 877        // This really should be Long.decode, but there isn't one. As a result,
 878        // hex and octal literals ending in 'l' or 'L' don't work.
 879        jjtThis.value = new Primitive( new Long( literal ) );
 880    }
 881    else
 882        jjtThis.value = new Primitive( Integer.decode( literal ) );
 883  }
 884|
 885  x = <FLOATING_POINT_LITERAL>
 886  {
 887    literal = x.image;
 888    ch = literal.charAt(literal.length()-1);
 889    if(ch == 'f' || ch == 'F')
 890    {
 891        literal = literal.substring(0,literal.length()-1);
 892        jjtThis.value = new Primitive( new Float( literal ) );
 893    }
 894    else
 895    {
 896        if(ch == 'd' || ch == 'D')
 897            literal = literal.substring(0,literal.length()-1);
 898
 899        jjtThis.value = new Primitive( new Double( literal ) );
 900    }
 901  }
 902|
 903  x = <CHARACTER_LITERAL> {
 904		try {
 905    		jjtThis.charSetup( x.image.substring(1, x.image.length() - 1) );
 906		} catch ( Exception e ) {
 907			throw new ParseException("Error parsing character: "+x.image);
 908		}
 909    }
 910|
 911  x = <STRING_LITERAL> {
 912		try {
 913			jjtThis.stringSetup( x.image.substring(1, x.image.length() - 1) );
 914		} catch ( Exception e ) {
 915			throw new ParseException("Error parsing string: "+x.image);
 916		}
 917    }
 918|
 919  b = BooleanLiteral()  {
 920    jjtThis.value = new Primitive( new Boolean(b) ); }
 921|
 922  NullLiteral() {
 923    jjtThis.value = Primitive.NULL; 
 924}
 925|
 926 VoidLiteral() {
 927    jjtThis.value = Primitive.VOID; }
 928}
 929
 930boolean BooleanLiteral() :
 931{}
 932{
 933  "true" { return true; }
 934|
 935  "false" { return false; }
 936}
 937
 938void NullLiteral() :
 939{}
 940{
 941  "null"
 942}
 943
 944void VoidLiteral() :
 945{}
 946{
 947  "void"
 948}
 949
 950void Arguments() #Arguments :
 951{ }
 952{
 953  "(" [ ArgumentList()  ]  ")"
 954}
 955
 956// leave these on the stack for Arguments() to handle
 957void ArgumentList() :
 958{ }
 959{
 960  Expression()
 961  ( "," Expression() )*
 962}
 963
 964void AllocationExpression() #AllocationExpression :
 965{ }
 966{
 967  LOOKAHEAD(2)
 968  "new" PrimitiveType() ArrayDimensions()
 969|
 970  "new" AmbiguousName() 
 971	( 
 972		ArrayDimensions() 
 973	| 
 974		// SYNTACTIC_LOOKAHEAD
 975		Arguments() [ LOOKAHEAD(2) Block() ]
 976	)
 977}
 978
 979void ArrayDimensions() #ArrayDimensions :
 980{}
 981{
 982  LOOKAHEAD(2)
 983  ( LOOKAHEAD(2) "[" Expression() "]" { jjtThis.addArrayDimension(); } )+
 984  // Removed trailing "[]" identifiers.  Specify array dims fully.
 985|
 986  ( "[" "]" { jjtThis.addArrayDimension(); } )+ ArrayInitializer()
 987}
 988
 989
 990/*
 991 * Statement syntax follows.
 992 */
 993
 994void Statement() : { }
 995{
 996  LOOKAHEAD(2)
 997  LabeledStatement()
 998|
 999  Block()
1000|
1001  EmptyStatement()
1002|
1003  StatementExpression() ";"
1004|
1005  SwitchStatement()
1006|
1007  IfStatement()
1008|
1009  WhileStatement()
1010|
1011  DoStatement()
1012|
1013  ForStatement()
1014|
1015  BreakStatement()
1016|
1017  ContinueStatement()
1018|
1019  ReturnStatement()
1020|
1021  ThrowStatement()
1022|
1023  TryStatement()
1024}
1025
1026void LabeledStatement() :
1027{}
1028{
1029  <IDENTIFIER> ":" Statement()
1030}
1031
1032void Block() #Block :
1033{}
1034{
1035  "{" ( BlockStatement() )* "}"
1036}
1037
1038void BlockStatement() :
1039{}
1040{
1041// SYNTACTIC_LOOKAHEAD
1042  LOOKAHEAD( MethodDeclarationLookahead() ) MethodDeclaration()
1043|
1044// SYNTACTIC_LOOKAHEAD
1045  LOOKAHEAD([ "final" ] Type() <IDENTIFIER>)
1046  TypedVariableDeclaration() ";"
1047|
1048  Statement()
1049
1050/* end */
1051
1052|  
1053  // Allow BeanShell imports in any block
1054  ImportDeclaration()
1055}
1056
1057void EmptyStatement() :
1058{}
1059{
1060  ";"
1061}
1062
1063void StatementExpression() :
1064/*
1065 * The last expansion of this production accepts more than the legal
1066 * Java expansions for StatementExpression.
1067 */
1068{ }
1069{
1070  PreIncrementExpression()
1071|
1072  PreDecrementExpression()
1073|
1074// SYNTACTIC_LOOKAHEAD
1075  LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
1076  Assignment() { }
1077|
1078  PostfixExpression()
1079}
1080
1081void SwitchStatement() #SwitchStatement :
1082{}
1083{
1084  "switch" "(" Expression() ")" "{"
1085    ( SwitchLabel() ( BlockStatement() )* )*
1086  "}"
1087}
1088
1089void SwitchLabel() #SwitchLabel :
1090{}
1091{
1092  "case" Expression() ":"
1093|
1094  "default" ":" { jjtThis.isDefault = true; }
1095}
1096
1097void IfStatement() #IfStatement :
1098/*
1099 * The disambiguating algorithm of JavaCC automatically binds dangling
1100 * else's to the innermost if statement.  The LOOKAHEAD specification
1101 * is to tell JavaCC that we know what we are doing.
1102 */
1103{}
1104{
1105  "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]
1106}
1107
1108void WhileStatement() #WhileStatement :
1109{}
1110{
1111  "while" "(" Expression() ")" Statement()
1112}
1113
1114/*
1115	Do statement is just a While statement with a special hook to execute
1116	at least once.
1117*/
1118void DoStatement() #WhileStatement :
1119{}
1120{
1121  "do" Statement() "while" "(" Expression() ")" ";" 
1122	{ jjtThis.isDoStatement=true;  }
1123}
1124
1125void ForStatement() #ForStatement :
1126{}
1127{
1128  "for" "(" [ ForInit() { jjtThis.hasForInit=true; } ]
1129    ";" [ Expression() { jjtThis.hasExpression=true; } ]
1130    ";" [ ForUpdate() { jjtThis.hasForUpdate=true; } ] ")"
1131    Statement()
1132}
1133
1134void ForInit() :
1135{ Token t = null; }
1136{
1137// SYNTACTIC_LOOKAHEAD
1138  LOOKAHEAD( [ t="final" ] Type() <IDENTIFIER> )
1139  TypedVariableDeclaration()
1140|
1141  StatementExpressionList()
1142}
1143
1144/**
1145	Declared a typed variable.
1146	Untyped variables are not declared per-se but are handled by the part
1147	of the grammar that deals with assignments.
1148*/
1149void TypedVariableDeclaration() #TypedVariableDeclaration :
1150{ 
1151	Token t = null; 
1152}
1153{
1154  [ t="final" ] Type() 
1155		VariableDeclarator() ( "," VariableDeclarator() )*  
1156	{
1157        jjtThis.isFinal = (t!=null);
1158    }
1159}
1160
1161void StatementExpressionList() #StatementExpressionList :
1162{}
1163{
1164  StatementExpression() ( "," StatementExpression() )*
1165}
1166
1167void ForUpdate() :
1168{}
1169{
1170  StatementExpressionList()
1171}
1172
1173void BreakStatement() #ReturnStatement :
1174{}
1175{
1176  "break" [ <IDENTIFIER> ] ";" { jjtThis.kind = BREAK; }
1177}
1178
1179void ContinueStatement() #ReturnStatement :
1180{}
1181{
1182  "continue" [ <IDENTIFIER> ] ";" { jjtThis.kind = CONTINUE; }
1183}
1184
1185void ReturnStatement() #ReturnStatement :
1186{}
1187{
1188  "return" [ Expression() ] ";" { jjtThis.kind = RETURN; }
1189}
1190
1191void ThrowStatement() #ThrowStatement :
1192{}
1193{
1194  "throw" Expression() ";"
1195}
1196
1197void TryStatement() #TryStatement:
1198/*
1199 * Semantic check required here to make sure that at least one
1200 * finally/catch is present.
1201 */
1202{}
1203{
1204  "try" Block()
1205  ( "catch" "(" FormalParameter() ")" Block() )*
1206  [ "finally" Block() ]
1207}