PageRenderTime 111ms CodeModel.GetById 55ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

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

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