1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16 package javassist.compiler; 17 18 import javassist.compiler.ast.*; 19 20 public final class Parser implements TokenId { 21 private Lex lex; 22 Parser(Lex lex)23 public Parser(Lex lex) { 24 this.lex = lex; 25 } 26 hasMore()27 public boolean hasMore() { return lex.lookAhead() >= 0; } 28 29 /* member.declaration 30 * : method.declaration | field.declaration 31 */ parseMember(SymbolTable tbl)32 public ASTList parseMember(SymbolTable tbl) throws CompileError { 33 ASTList mem = parseMember1(tbl); 34 if (mem instanceof MethodDecl) 35 return parseMethod2(tbl, (MethodDecl)mem); 36 else 37 return mem; 38 } 39 40 /* A method body is not parsed. 41 */ parseMember1(SymbolTable tbl)42 public ASTList parseMember1(SymbolTable tbl) throws CompileError { 43 ASTList mods = parseMemberMods(); 44 Declarator d; 45 boolean isConstructor = false; 46 if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') { 47 d = new Declarator(VOID, 0); 48 isConstructor = true; 49 } 50 else 51 d = parseFormalType(tbl); 52 53 if (lex.get() != Identifier) 54 throw new SyntaxError(lex); 55 56 String name; 57 if (isConstructor) 58 name = MethodDecl.initName; 59 else 60 name = lex.getString(); 61 62 d.setVariable(new Symbol(name)); 63 if (isConstructor || lex.lookAhead() == '(') 64 return parseMethod1(tbl, isConstructor, mods, d); 65 else 66 return parseField(tbl, mods, d); 67 } 68 69 /* field.declaration 70 * : member.modifiers 71 * formal.type Identifier 72 * [ "=" expression ] ";" 73 */ parseField(SymbolTable tbl, ASTList mods, Declarator d)74 private FieldDecl parseField(SymbolTable tbl, ASTList mods, 75 Declarator d) throws CompileError 76 { 77 ASTree expr = null; 78 if (lex.lookAhead() == '=') { 79 lex.get(); 80 expr = parseExpression(tbl); 81 } 82 83 int c = lex.get(); 84 if (c == ';') 85 return new FieldDecl(mods, new ASTList(d, new ASTList(expr))); 86 else if (c == ',') 87 throw new CompileError( 88 "only one field can be declared in one declaration", lex); 89 else 90 throw new SyntaxError(lex); 91 } 92 93 /* method.declaration 94 * : member.modifiers 95 * [ formal.type ] 96 * Identifier "(" [ formal.parameter ( "," formal.parameter )* ] ")" 97 * array.dimension 98 * [ THROWS class.type ( "," class.type ) ] 99 * ( block.statement | ";" ) 100 * 101 * Note that a method body is not parsed. 102 */ parseMethod1(SymbolTable tbl, boolean isConstructor, ASTList mods, Declarator d)103 private MethodDecl parseMethod1(SymbolTable tbl, boolean isConstructor, 104 ASTList mods, Declarator d) 105 throws CompileError 106 { 107 if (lex.get() != '(') 108 throw new SyntaxError(lex); 109 110 ASTList parms = null; 111 if (lex.lookAhead() != ')') 112 while (true) { 113 parms = ASTList.append(parms, parseFormalParam(tbl)); 114 int t = lex.lookAhead(); 115 if (t == ',') 116 lex.get(); 117 else if (t == ')') 118 break; 119 } 120 121 lex.get(); // ')' 122 d.addArrayDim(parseArrayDimension()); 123 if (isConstructor && d.getArrayDim() > 0) 124 throw new SyntaxError(lex); 125 126 ASTList throwsList = null; 127 if (lex.lookAhead() == THROWS) { 128 lex.get(); 129 while (true) { 130 throwsList = ASTList.append(throwsList, parseClassType(tbl)); 131 if (lex.lookAhead() == ',') 132 lex.get(); 133 else 134 break; 135 } 136 } 137 138 return new MethodDecl(mods, new ASTList(d, 139 ASTList.make(parms, throwsList, null))); 140 } 141 142 /* Parses a method body. 143 */ parseMethod2(SymbolTable tbl, MethodDecl md)144 public MethodDecl parseMethod2(SymbolTable tbl, MethodDecl md) 145 throws CompileError 146 { 147 Stmnt body = null; 148 if (lex.lookAhead() == ';') 149 lex.get(); 150 else { 151 body = parseBlock(tbl); 152 if (body == null) 153 body = new Stmnt(BLOCK); 154 } 155 156 md.sublist(4).setHead(body); 157 return md; 158 } 159 160 /* member.modifiers 161 * : ( FINAL | SYNCHRONIZED | ABSTRACT 162 * | PUBLIC | PROTECTED | PRIVATE | STATIC 163 * | VOLATILE | TRANSIENT | STRICT )* 164 */ parseMemberMods()165 private ASTList parseMemberMods() { 166 int t; 167 ASTList list = null; 168 while (true) { 169 t = lex.lookAhead(); 170 if (t == ABSTRACT || t == FINAL || t == PUBLIC || t == PROTECTED 171 || t == PRIVATE || t == SYNCHRONIZED || t == STATIC 172 || t == VOLATILE || t == TRANSIENT || t == STRICT) 173 list = new ASTList(new Keyword(lex.get()), list); 174 else 175 break; 176 } 177 178 return list; 179 } 180 181 /* formal.type : ( build-in-type | class.type ) array.dimension 182 */ parseFormalType(SymbolTable tbl)183 private Declarator parseFormalType(SymbolTable tbl) throws CompileError { 184 int t = lex.lookAhead(); 185 if (isBuiltinType(t) || t == VOID) { 186 lex.get(); // primitive type 187 int dim = parseArrayDimension(); 188 return new Declarator(t, dim); 189 } 190 else { 191 ASTList name = parseClassType(tbl); 192 int dim = parseArrayDimension(); 193 return new Declarator(name, dim); 194 } 195 } 196 isBuiltinType(int t)197 private static boolean isBuiltinType(int t) { 198 return (t == BOOLEAN || t == BYTE || t == CHAR || t == SHORT 199 || t == INT || t == LONG || t == FLOAT || t == DOUBLE); 200 } 201 202 /* formal.parameter : formal.type Identifier array.dimension 203 */ parseFormalParam(SymbolTable tbl)204 private Declarator parseFormalParam(SymbolTable tbl) 205 throws CompileError 206 { 207 Declarator d = parseFormalType(tbl); 208 if (lex.get() != Identifier) 209 throw new SyntaxError(lex); 210 211 String name = lex.getString(); 212 d.setVariable(new Symbol(name)); 213 d.addArrayDim(parseArrayDimension()); 214 tbl.append(name, d); 215 return d; 216 } 217 218 /* statement : [ label ":" ]* labeled.statement 219 * 220 * labeled.statement 221 * : block.statement 222 * | if.statement 223 * | while.statement 224 * | do.statement 225 * | for.statement 226 * | switch.statement 227 * | try.statement 228 * | return.statement 229 * | thorw.statement 230 * | break.statement 231 * | continue.statement 232 * | declaration.or.expression 233 * | ";" 234 * 235 * This method may return null (empty statement). 236 */ parseStatement(SymbolTable tbl)237 public Stmnt parseStatement(SymbolTable tbl) 238 throws CompileError 239 { 240 int t = lex.lookAhead(); 241 if (t == '{') 242 return parseBlock(tbl); 243 else if (t == ';') { 244 lex.get(); 245 return new Stmnt(BLOCK); // empty statement 246 } 247 else if (t == Identifier && lex.lookAhead(1) == ':') { 248 lex.get(); // Identifier 249 String label = lex.getString(); 250 lex.get(); // ':' 251 return Stmnt.make(LABEL, new Symbol(label), parseStatement(tbl)); 252 } 253 else if (t == IF) 254 return parseIf(tbl); 255 else if (t == WHILE) 256 return parseWhile(tbl); 257 else if (t == DO) 258 return parseDo(tbl); 259 else if (t == FOR) 260 return parseFor(tbl); 261 else if (t == TRY) 262 return parseTry(tbl); 263 else if (t == SWITCH) 264 return parseSwitch(tbl); 265 else if (t == SYNCHRONIZED) 266 return parseSynchronized(tbl); 267 else if (t == RETURN) 268 return parseReturn(tbl); 269 else if (t == THROW) 270 return parseThrow(tbl); 271 else if (t == BREAK) 272 return parseBreak(tbl); 273 else if (t == CONTINUE) 274 return parseContinue(tbl); 275 else 276 return parseDeclarationOrExpression(tbl, false); 277 } 278 279 /* block.statement : "{" statement* "}" 280 */ parseBlock(SymbolTable tbl)281 private Stmnt parseBlock(SymbolTable tbl) throws CompileError { 282 if (lex.get() != '{') 283 throw new SyntaxError(lex); 284 285 Stmnt body = null; 286 SymbolTable tbl2 = new SymbolTable(tbl); 287 while (lex.lookAhead() != '}') { 288 Stmnt s = parseStatement(tbl2); 289 if (s != null) 290 body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s)); 291 } 292 293 lex.get(); // '}' 294 if (body == null) 295 return new Stmnt(BLOCK); // empty block 296 else 297 return body; 298 } 299 300 /* if.statement : IF "(" expression ")" statement 301 * [ ELSE statement ] 302 */ parseIf(SymbolTable tbl)303 private Stmnt parseIf(SymbolTable tbl) throws CompileError { 304 int t = lex.get(); // IF 305 ASTree expr = parseParExpression(tbl); 306 Stmnt thenp = parseStatement(tbl); 307 Stmnt elsep; 308 if (lex.lookAhead() == ELSE) { 309 lex.get(); 310 elsep = parseStatement(tbl); 311 } 312 else 313 elsep = null; 314 315 return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep))); 316 } 317 318 /* while.statement : WHILE "(" expression ")" statement 319 */ parseWhile(SymbolTable tbl)320 private Stmnt parseWhile(SymbolTable tbl) 321 throws CompileError 322 { 323 int t = lex.get(); // WHILE 324 ASTree expr = parseParExpression(tbl); 325 Stmnt body = parseStatement(tbl); 326 return new Stmnt(t, expr, body); 327 } 328 329 /* do.statement : DO statement WHILE "(" expression ")" ";" 330 */ parseDo(SymbolTable tbl)331 private Stmnt parseDo(SymbolTable tbl) throws CompileError { 332 int t = lex.get(); // DO 333 Stmnt body = parseStatement(tbl); 334 if (lex.get() != WHILE || lex.get() != '(') 335 throw new SyntaxError(lex); 336 337 ASTree expr = parseExpression(tbl); 338 if (lex.get() != ')' || lex.get() != ';') 339 throw new SyntaxError(lex); 340 341 return new Stmnt(t, expr, body); 342 } 343 344 /* for.statement : FOR "(" decl.or.expr expression ";" expression ")" 345 * statement 346 */ parseFor(SymbolTable tbl)347 private Stmnt parseFor(SymbolTable tbl) throws CompileError { 348 Stmnt expr1, expr3; 349 ASTree expr2; 350 int t = lex.get(); // FOR 351 352 SymbolTable tbl2 = new SymbolTable(tbl); 353 354 if (lex.get() != '(') 355 throw new SyntaxError(lex); 356 357 if (lex.lookAhead() == ';') { 358 lex.get(); 359 expr1 = null; 360 } 361 else 362 expr1 = parseDeclarationOrExpression(tbl2, true); 363 364 if (lex.lookAhead() == ';') 365 expr2 = null; 366 else 367 expr2 = parseExpression(tbl2); 368 369 if (lex.get() != ';') 370 throw new CompileError("; is missing", lex); 371 372 if (lex.lookAhead() == ')') 373 expr3 = null; 374 else 375 expr3 = parseExprList(tbl2); 376 377 if (lex.get() != ')') 378 throw new CompileError(") is missing", lex); 379 380 Stmnt body = parseStatement(tbl2); 381 return new Stmnt(t, expr1, new ASTList(expr2, 382 new ASTList(expr3, body))); 383 } 384 385 /* switch.statement : SWITCH "(" expression ")" "{" switch.block "}" 386 * 387 * swtich.block : ( switch.label statement* )* 388 * 389 * swtich.label : DEFAULT ":" 390 * | CASE const.expression ":" 391 */ parseSwitch(SymbolTable tbl)392 private Stmnt parseSwitch(SymbolTable tbl) throws CompileError { 393 int t = lex.get(); // SWITCH 394 ASTree expr = parseParExpression(tbl); 395 Stmnt body = parseSwitchBlock(tbl); 396 return new Stmnt(t, expr, body); 397 } 398 parseSwitchBlock(SymbolTable tbl)399 private Stmnt parseSwitchBlock(SymbolTable tbl) throws CompileError { 400 if (lex.get() != '{') 401 throw new SyntaxError(lex); 402 403 SymbolTable tbl2 = new SymbolTable(tbl); 404 Stmnt s = parseStmntOrCase(tbl2); 405 if (s == null) 406 throw new CompileError("empty switch block", lex); 407 408 int op = s.getOperator(); 409 if (op != CASE && op != DEFAULT) 410 throw new CompileError("no case or default in a switch block", 411 lex); 412 413 Stmnt body = new Stmnt(BLOCK, s); 414 while (lex.lookAhead() != '}') { 415 Stmnt s2 = parseStmntOrCase(tbl2); 416 if (s2 != null) { 417 int op2 = s2.getOperator(); 418 if (op2 == CASE || op2 == DEFAULT) { 419 body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s2)); 420 s = s2; 421 } 422 else 423 s = (Stmnt)ASTList.concat(s, new Stmnt(BLOCK, s2)); 424 } 425 } 426 427 lex.get(); // '}' 428 return body; 429 } 430 parseStmntOrCase(SymbolTable tbl)431 private Stmnt parseStmntOrCase(SymbolTable tbl) throws CompileError { 432 int t = lex.lookAhead(); 433 if (t != CASE && t != DEFAULT) 434 return parseStatement(tbl); 435 436 lex.get(); 437 Stmnt s; 438 if (t == CASE) 439 s = new Stmnt(t, parseExpression(tbl)); 440 else 441 s = new Stmnt(DEFAULT); 442 443 if (lex.get() != ':') 444 throw new CompileError(": is missing", lex); 445 446 return s; 447 } 448 449 /* synchronized.statement : 450 * SYNCHRONIZED "(" expression ")" block.statement 451 */ parseSynchronized(SymbolTable tbl)452 private Stmnt parseSynchronized(SymbolTable tbl) throws CompileError { 453 int t = lex.get(); // SYNCHRONIZED 454 if (lex.get() != '(') 455 throw new SyntaxError(lex); 456 457 ASTree expr = parseExpression(tbl); 458 if (lex.get() != ')') 459 throw new SyntaxError(lex); 460 461 Stmnt body = parseBlock(tbl); 462 return new Stmnt(t, expr, body); 463 } 464 465 /* try.statement 466 * : TRY block.statement 467 * [ CATCH "(" class.type Identifier ")" block.statement ]* 468 * [ FINALLY block.statement ]* 469 */ parseTry(SymbolTable tbl)470 private Stmnt parseTry(SymbolTable tbl) throws CompileError { 471 lex.get(); // TRY 472 Stmnt block = parseBlock(tbl); 473 ASTList catchList = null; 474 while (lex.lookAhead() == CATCH) { 475 lex.get(); // CATCH 476 if (lex.get() != '(') 477 throw new SyntaxError(lex); 478 479 SymbolTable tbl2 = new SymbolTable(tbl); 480 Declarator d = parseFormalParam(tbl2); 481 if (d.getArrayDim() > 0 || d.getType() != CLASS) 482 throw new SyntaxError(lex); 483 484 if (lex.get() != ')') 485 throw new SyntaxError(lex); 486 487 Stmnt b = parseBlock(tbl2); 488 catchList = ASTList.append(catchList, new Pair(d, b)); 489 } 490 491 Stmnt finallyBlock = null; 492 if (lex.lookAhead() == FINALLY) { 493 lex.get(); // FINALLY 494 finallyBlock = parseBlock(tbl); 495 } 496 497 return Stmnt.make(TRY, block, catchList, finallyBlock); 498 } 499 500 /* return.statement : RETURN [ expression ] ";" 501 */ parseReturn(SymbolTable tbl)502 private Stmnt parseReturn(SymbolTable tbl) throws CompileError { 503 int t = lex.get(); // RETURN 504 Stmnt s = new Stmnt(t); 505 if (lex.lookAhead() != ';') 506 s.setLeft(parseExpression(tbl)); 507 508 if (lex.get() != ';') 509 throw new CompileError("; is missing", lex); 510 511 return s; 512 } 513 514 /* throw.statement : THROW expression ";" 515 */ parseThrow(SymbolTable tbl)516 private Stmnt parseThrow(SymbolTable tbl) throws CompileError { 517 int t = lex.get(); // THROW 518 ASTree expr = parseExpression(tbl); 519 if (lex.get() != ';') 520 throw new CompileError("; is missing", lex); 521 522 return new Stmnt(t, expr); 523 } 524 525 /* break.statement : BREAK [ Identifier ] ";" 526 */ parseBreak(SymbolTable tbl)527 private Stmnt parseBreak(SymbolTable tbl) 528 throws CompileError 529 { 530 return parseContinue(tbl); 531 } 532 533 /* continue.statement : CONTINUE [ Identifier ] ";" 534 */ parseContinue(SymbolTable tbl)535 private Stmnt parseContinue(SymbolTable tbl) 536 throws CompileError 537 { 538 int t = lex.get(); // CONTINUE 539 Stmnt s = new Stmnt(t); 540 int t2 = lex.get(); 541 if (t2 == Identifier) { 542 s.setLeft(new Symbol(lex.getString())); 543 t2 = lex.get(); 544 } 545 546 if (t2 != ';') 547 throw new CompileError("; is missing", lex); 548 549 return s; 550 } 551 552 /* declaration.or.expression 553 * : [ FINAL ] built-in-type array.dimension declarators 554 * | [ FINAL ] class.type array.dimension declarators 555 * | expression ';' 556 * | expr.list ';' if exprList is true 557 * 558 * Note: FINAL is currently ignored. This must be fixed 559 * in future. 560 */ parseDeclarationOrExpression(SymbolTable tbl, boolean exprList)561 private Stmnt parseDeclarationOrExpression(SymbolTable tbl, 562 boolean exprList) 563 throws CompileError 564 { 565 int t = lex.lookAhead(); 566 while (t == FINAL) { 567 lex.get(); 568 t = lex.lookAhead(); 569 } 570 571 if (isBuiltinType(t)) { 572 t = lex.get(); 573 int dim = parseArrayDimension(); 574 return parseDeclarators(tbl, new Declarator(t, dim)); 575 } 576 else if (t == Identifier) { 577 int i = nextIsClassType(0); 578 if (i >= 0) 579 if (lex.lookAhead(i) == Identifier) { 580 ASTList name = parseClassType(tbl); 581 int dim = parseArrayDimension(); 582 return parseDeclarators(tbl, new Declarator(name, dim)); 583 } 584 } 585 586 Stmnt expr; 587 if (exprList) 588 expr = parseExprList(tbl); 589 else 590 expr = new Stmnt(EXPR, parseExpression(tbl)); 591 592 if (lex.get() != ';') 593 throw new CompileError("; is missing", lex); 594 595 return expr; 596 } 597 598 /* expr.list : ( expression ',')* expression 599 */ parseExprList(SymbolTable tbl)600 private Stmnt parseExprList(SymbolTable tbl) throws CompileError { 601 Stmnt expr = null; 602 for (;;) { 603 Stmnt e = new Stmnt(EXPR, parseExpression(tbl)); 604 expr = (Stmnt)ASTList.concat(expr, new Stmnt(BLOCK, e)); 605 if (lex.lookAhead() == ',') 606 lex.get(); 607 else 608 return expr; 609 } 610 } 611 612 /* declarators : declarator [ ',' declarator ]* ';' 613 */ parseDeclarators(SymbolTable tbl, Declarator d)614 private Stmnt parseDeclarators(SymbolTable tbl, Declarator d) 615 throws CompileError 616 { 617 Stmnt decl = null; 618 for (;;) { 619 decl = (Stmnt)ASTList.concat(decl, 620 new Stmnt(DECL, parseDeclarator(tbl, d))); 621 int t = lex.get(); 622 if (t == ';') 623 return decl; 624 else if (t != ',') 625 throw new CompileError("; is missing", lex); 626 } 627 } 628 629 /* declarator : Identifier array.dimension [ '=' initializer ] 630 */ parseDeclarator(SymbolTable tbl, Declarator d)631 private Declarator parseDeclarator(SymbolTable tbl, Declarator d) 632 throws CompileError 633 { 634 if (lex.get() != Identifier || d.getType() == VOID) 635 throw new SyntaxError(lex); 636 637 String name = lex.getString(); 638 Symbol symbol = new Symbol(name); 639 int dim = parseArrayDimension(); 640 ASTree init = null; 641 if (lex.lookAhead() == '=') { 642 lex.get(); 643 init = parseInitializer(tbl); 644 } 645 646 Declarator decl = d.make(symbol, dim, init); 647 tbl.append(name, decl); 648 return decl; 649 } 650 651 /* initializer : expression | array.initializer 652 */ parseInitializer(SymbolTable tbl)653 private ASTree parseInitializer(SymbolTable tbl) throws CompileError { 654 if (lex.lookAhead() == '{') 655 return parseArrayInitializer(tbl); 656 else 657 return parseExpression(tbl); 658 } 659 660 /* array.initializer : 661 * '{' (( array.initializer | expression ) ',')* '}' 662 */ parseArrayInitializer(SymbolTable tbl)663 private ArrayInit parseArrayInitializer(SymbolTable tbl) 664 throws CompileError 665 { 666 lex.get(); // '{' 667 ASTree expr = parseExpression(tbl); 668 ArrayInit init = new ArrayInit(expr); 669 while (lex.lookAhead() == ',') { 670 lex.get(); 671 expr = parseExpression(tbl); 672 ASTList.append(init, expr); 673 } 674 675 if (lex.get() != '}') 676 throw new SyntaxError(lex); 677 678 return init; 679 } 680 681 /* par.expression : '(' expression ')' 682 */ parseParExpression(SymbolTable tbl)683 private ASTree parseParExpression(SymbolTable tbl) throws CompileError { 684 if (lex.get() != '(') 685 throw new SyntaxError(lex); 686 687 ASTree expr = parseExpression(tbl); 688 if (lex.get() != ')') 689 throw new SyntaxError(lex); 690 691 return expr; 692 } 693 694 /* expression : conditional.expr 695 * | conditional.expr assign.op expression (right-to-left) 696 */ parseExpression(SymbolTable tbl)697 public ASTree parseExpression(SymbolTable tbl) throws CompileError { 698 ASTree left = parseConditionalExpr(tbl); 699 if (!isAssignOp(lex.lookAhead())) 700 return left; 701 702 int t = lex.get(); 703 ASTree right = parseExpression(tbl); 704 return AssignExpr.makeAssign(t, left, right); 705 } 706 isAssignOp(int t)707 private static boolean isAssignOp(int t) { 708 return t == '=' || t == MOD_E || t == AND_E 709 || t == MUL_E || t == PLUS_E || t == MINUS_E || t == DIV_E 710 || t == EXOR_E || t == OR_E || t == LSHIFT_E 711 || t == RSHIFT_E || t == ARSHIFT_E; 712 } 713 714 /* conditional.expr (right-to-left) 715 * : logical.or.expr [ '?' expression ':' conditional.expr ] 716 */ parseConditionalExpr(SymbolTable tbl)717 private ASTree parseConditionalExpr(SymbolTable tbl) throws CompileError { 718 ASTree cond = parseBinaryExpr(tbl); 719 if (lex.lookAhead() == '?') { 720 lex.get(); 721 ASTree thenExpr = parseExpression(tbl); 722 if (lex.get() != ':') 723 throw new CompileError(": is missing", lex); 724 725 ASTree elseExpr = parseExpression(tbl); 726 return new CondExpr(cond, thenExpr, elseExpr); 727 } 728 else 729 return cond; 730 } 731 732 /* logical.or.expr 10 (operator precedence) 733 * : logical.and.expr 734 * | logical.or.expr OROR logical.and.expr left-to-right 735 * 736 * logical.and.expr 9 737 * : inclusive.or.expr 738 * | logical.and.expr ANDAND inclusive.or.expr 739 * 740 * inclusive.or.expr 8 741 * : exclusive.or.expr 742 * | inclusive.or.expr "|" exclusive.or.expr 743 * 744 * exclusive.or.expr 7 745 * : and.expr 746 * | exclusive.or.expr "^" and.expr 747 * 748 * and.expr 6 749 * : equality.expr 750 * | and.expr "&" equality.expr 751 * 752 * equality.expr 5 753 * : relational.expr 754 * | equality.expr (EQ | NEQ) relational.expr 755 * 756 * relational.expr 4 757 * : shift.expr 758 * | relational.expr (LE | GE | "<" | ">") shift.expr 759 * | relational.expr INSTANCEOF class.type ("[" "]")* 760 * 761 * shift.expr 3 762 * : additive.expr 763 * | shift.expr (LSHIFT | RSHIFT | ARSHIFT) additive.expr 764 * 765 * additive.expr 2 766 * : multiply.expr 767 * | additive.expr ("+" | "-") multiply.expr 768 * 769 * multiply.expr 1 770 * : unary.expr 771 * | multiply.expr ("*" | "/" | "%") unary.expr 772 */ parseBinaryExpr(SymbolTable tbl)773 private ASTree parseBinaryExpr(SymbolTable tbl) throws CompileError { 774 ASTree expr = parseUnaryExpr(tbl); 775 for (;;) { 776 int t = lex.lookAhead(); 777 int p = getOpPrecedence(t); 778 if (p == 0) 779 return expr; 780 else 781 expr = binaryExpr2(tbl, expr, p); 782 } 783 } 784 parseInstanceOf(SymbolTable tbl, ASTree expr)785 private ASTree parseInstanceOf(SymbolTable tbl, ASTree expr) 786 throws CompileError 787 { 788 int t = lex.lookAhead(); 789 if (isBuiltinType(t)) { 790 lex.get(); // primitive type 791 int dim = parseArrayDimension(); 792 return new InstanceOfExpr(t, dim, expr); 793 } 794 else { 795 ASTList name = parseClassType(tbl); 796 int dim = parseArrayDimension(); 797 return new InstanceOfExpr(name, dim, expr); 798 } 799 } 800 binaryExpr2(SymbolTable tbl, ASTree expr, int prec)801 private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec) 802 throws CompileError 803 { 804 int t = lex.get(); 805 if (t == INSTANCEOF) 806 return parseInstanceOf(tbl, expr); 807 808 ASTree expr2 = parseUnaryExpr(tbl); 809 for (;;) { 810 int t2 = lex.lookAhead(); 811 int p2 = getOpPrecedence(t2); 812 if (p2 != 0 && prec > p2) 813 expr2 = binaryExpr2(tbl, expr2, p2); 814 else 815 return BinExpr.makeBin(t, expr, expr2); 816 } 817 } 818 819 // !"#$%&'( )*+,-./0 12345678 9:;<=>? 820 private static final int[] binaryOpPrecedence 821 = { 0, 0, 0, 0, 1, 6, 0, 0, 822 0, 1, 2, 0, 2, 0, 1, 0, 823 0, 0, 0, 0, 0, 0, 0, 0, 824 0, 0, 0, 4, 0, 4, 0 }; 825 getOpPrecedence(int c)826 private int getOpPrecedence(int c) { 827 if ('!' <= c && c <= '?') 828 return binaryOpPrecedence[c - '!']; 829 else if (c == '^') 830 return 7; 831 else if (c == '|') 832 return 8; 833 else if (c == ANDAND) 834 return 9; 835 else if (c == OROR) 836 return 10; 837 else if (c == EQ || c == NEQ) 838 return 5; 839 else if (c == LE || c == GE || c == INSTANCEOF) 840 return 4; 841 else if (c == LSHIFT || c == RSHIFT || c == ARSHIFT) 842 return 3; 843 else 844 return 0; // not a binary operator 845 } 846 847 /* unary.expr : "++"|"--" unary.expr 848 | "+"|"-" unary.expr 849 | "!"|"~" unary.expr 850 | cast.expr 851 | postfix.expr 852 853 unary.expr.not.plus.minus is a unary expression starting without 854 "+", "-", "++", or "--". 855 */ parseUnaryExpr(SymbolTable tbl)856 private ASTree parseUnaryExpr(SymbolTable tbl) throws CompileError { 857 int t; 858 switch (lex.lookAhead()) { 859 case '+' : 860 case '-' : 861 case PLUSPLUS : 862 case MINUSMINUS : 863 case '!' : 864 case '~' : 865 t = lex.get(); 866 if (t == '-') { 867 int t2 = lex.lookAhead(); 868 switch (t2) { 869 case LongConstant : 870 case IntConstant : 871 case CharConstant : 872 lex.get(); 873 return new IntConst(-lex.getLong(), t2); 874 case DoubleConstant : 875 case FloatConstant : 876 lex.get(); 877 return new DoubleConst(-lex.getDouble(), t2); 878 default : 879 break; 880 } 881 } 882 883 return Expr.make(t, parseUnaryExpr(tbl)); 884 case '(' : 885 return parseCast(tbl); 886 default : 887 return parsePostfix(tbl); 888 } 889 } 890 891 /* cast.expr : "(" builtin.type ("[" "]")* ")" unary.expr 892 | "(" class.type ("[" "]")* ")" unary.expr2 893 894 unary.expr2 is a unary.expr beginning with "(", NULL, StringL, 895 Identifier, THIS, SUPER, or NEW. 896 897 Either "(int.class)" or "(String[].class)" is a not cast expression. 898 */ parseCast(SymbolTable tbl)899 private ASTree parseCast(SymbolTable tbl) throws CompileError { 900 int t = lex.lookAhead(1); 901 if (isBuiltinType(t) && nextIsBuiltinCast()) { 902 lex.get(); // '(' 903 lex.get(); // primitive type 904 int dim = parseArrayDimension(); 905 if (lex.get() != ')') 906 throw new CompileError(") is missing", lex); 907 908 return new CastExpr(t, dim, parseUnaryExpr(tbl)); 909 } 910 else if (t == Identifier && nextIsClassCast()) { 911 lex.get(); // '(' 912 ASTList name = parseClassType(tbl); 913 int dim = parseArrayDimension(); 914 if (lex.get() != ')') 915 throw new CompileError(") is missing", lex); 916 917 return new CastExpr(name, dim, parseUnaryExpr(tbl)); 918 } 919 else 920 return parsePostfix(tbl); 921 } 922 nextIsBuiltinCast()923 private boolean nextIsBuiltinCast() { 924 int t; 925 int i = 2; 926 while ((t = lex.lookAhead(i++)) == '[') 927 if (lex.lookAhead(i++) != ']') 928 return false; 929 930 return lex.lookAhead(i - 1) == ')'; 931 } 932 nextIsClassCast()933 private boolean nextIsClassCast() { 934 int i = nextIsClassType(1); 935 if (i < 0) 936 return false; 937 938 int t = lex.lookAhead(i); 939 if (t != ')') 940 return false; 941 942 t = lex.lookAhead(i + 1); 943 return t == '(' || t == NULL || t == StringL 944 || t == Identifier || t == THIS || t == SUPER || t == NEW 945 || t == TRUE || t == FALSE || t == LongConstant 946 || t == IntConstant || t == CharConstant 947 || t == DoubleConstant || t == FloatConstant; 948 } 949 nextIsClassType(int i)950 private int nextIsClassType(int i) { 951 int t; 952 while (lex.lookAhead(++i) == '.') 953 if (lex.lookAhead(++i) != Identifier) 954 return -1; 955 956 while ((t = lex.lookAhead(i++)) == '[') 957 if (lex.lookAhead(i++) != ']') 958 return -1; 959 960 return i - 1; 961 } 962 963 /* array.dimension : [ "[" "]" ]* 964 */ parseArrayDimension()965 private int parseArrayDimension() throws CompileError { 966 int arrayDim = 0; 967 while (lex.lookAhead() == '[') { 968 ++arrayDim; 969 lex.get(); 970 if (lex.get() != ']') 971 throw new CompileError("] is missing", lex); 972 } 973 974 return arrayDim; 975 } 976 977 /* class.type : Identifier ( "." Identifier )* 978 */ parseClassType(SymbolTable tbl)979 private ASTList parseClassType(SymbolTable tbl) throws CompileError { 980 ASTList list = null; 981 for (;;) { 982 if (lex.get() != Identifier) 983 throw new SyntaxError(lex); 984 985 list = ASTList.append(list, new Symbol(lex.getString())); 986 if (lex.lookAhead() == '.') 987 lex.get(); 988 else 989 break; 990 } 991 992 return list; 993 } 994 995 /* postfix.expr : number.literal 996 * | primary.expr 997 * | method.expr 998 * | postfix.expr "++" | "--" 999 * | postfix.expr "[" array.size "]" 1000 * | postfix.expr "." Identifier 1001 * | postfix.expr ( "[" "]" )* "." CLASS 1002 * | postfix.expr "#" Identifier 1003 * 1004 * "#" is not an operator of regular Java. It separates 1005 * a class name and a member name in an expression for static member 1006 * access. For example, 1007 * java.lang.Integer.toString(3) in regular Java 1008 * can be written like this: 1009 * java.lang.Integer#toString(3) for this compiler. 1010 */ parsePostfix(SymbolTable tbl)1011 private ASTree parsePostfix(SymbolTable tbl) throws CompileError { 1012 int token = lex.lookAhead(); 1013 switch (token) { // see also parseUnaryExpr() 1014 case LongConstant : 1015 case IntConstant : 1016 case CharConstant : 1017 lex.get(); 1018 return new IntConst(lex.getLong(), token); 1019 case DoubleConstant : 1020 case FloatConstant : 1021 lex.get(); 1022 return new DoubleConst(lex.getDouble(), token); 1023 default : 1024 break; 1025 } 1026 1027 String str; 1028 ASTree index; 1029 ASTree expr = parsePrimaryExpr(tbl); 1030 int t; 1031 while (true) { 1032 switch (lex.lookAhead()) { 1033 case '(' : 1034 expr = parseMethodCall(tbl, expr); 1035 break; 1036 case '[' : 1037 if (lex.lookAhead(1) == ']') { 1038 int dim = parseArrayDimension(); 1039 if (lex.get() != '.' || lex.get() != CLASS) 1040 throw new SyntaxError(lex); 1041 1042 expr = parseDotClass(expr, dim); 1043 } 1044 else { 1045 index = parseArrayIndex(tbl); 1046 if (index == null) 1047 throw new SyntaxError(lex); 1048 1049 expr = Expr.make(ARRAY, expr, index); 1050 } 1051 break; 1052 case PLUSPLUS : 1053 case MINUSMINUS : 1054 t = lex.get(); 1055 expr = Expr.make(t, null, expr); 1056 break; 1057 case '.' : 1058 lex.get(); 1059 t = lex.get(); 1060 if (t == CLASS) { 1061 expr = parseDotClass(expr, 0); 1062 } 1063 else if (t == Identifier) { 1064 str = lex.getString(); 1065 expr = Expr.make('.', expr, new Member(str)); 1066 } 1067 else 1068 throw new CompileError("missing member name", lex); 1069 break; 1070 case '#' : 1071 lex.get(); 1072 t = lex.get(); 1073 if (t != Identifier) 1074 throw new CompileError("missing static member name", lex); 1075 1076 str = lex.getString(); 1077 expr = Expr.make(MEMBER, new Symbol(toClassName(expr)), 1078 new Member(str)); 1079 break; 1080 default : 1081 return expr; 1082 } 1083 } 1084 } 1085 1086 /* Parse a .class expression on a class type. For example, 1087 * String.class => ('.' "String" "class") 1088 * String[].class => ('.' "[LString;" "class") 1089 */ parseDotClass(ASTree className, int dim)1090 private ASTree parseDotClass(ASTree className, int dim) 1091 throws CompileError 1092 { 1093 String cname = toClassName(className); 1094 if (dim > 0) { 1095 StringBuffer sbuf = new StringBuffer(); 1096 while (dim-- > 0) 1097 sbuf.append('['); 1098 1099 sbuf.append('L').append(cname.replace('.', '/')).append(';'); 1100 cname = sbuf.toString(); 1101 } 1102 1103 return Expr.make('.', new Symbol(cname), new Member("class")); 1104 } 1105 1106 /* Parses a .class expression on a built-in type. For example, 1107 * int.class => ('#' "java.lang.Integer" "TYPE") 1108 * int[].class => ('.' "[I", "class") 1109 */ parseDotClass(int builtinType, int dim)1110 private ASTree parseDotClass(int builtinType, int dim) 1111 throws CompileError 1112 { 1113 if (dim > 0) { 1114 String cname = CodeGen.toJvmTypeName(builtinType, dim); 1115 return Expr.make('.', new Symbol(cname), new Member("class")); 1116 } 1117 else { 1118 String cname; 1119 switch(builtinType) { 1120 case BOOLEAN : 1121 cname = "java.lang.Boolean"; 1122 break; 1123 case BYTE : 1124 cname = "java.lang.Byte"; 1125 break; 1126 case CHAR : 1127 cname = "java.lang.Character"; 1128 break; 1129 case SHORT : 1130 cname = "java.lang.Short"; 1131 break; 1132 case INT : 1133 cname = "java.lang.Integer"; 1134 break; 1135 case LONG : 1136 cname = "java.lang.Long"; 1137 break; 1138 case FLOAT : 1139 cname = "java.lang.Float"; 1140 break; 1141 case DOUBLE : 1142 cname = "java.lang.Double"; 1143 break; 1144 case VOID : 1145 cname = "java.lang.Void"; 1146 break; 1147 default : 1148 throw new CompileError("invalid builtin type: " 1149 + builtinType); 1150 } 1151 1152 return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE")); 1153 } 1154 } 1155 1156 /* method.call : method.expr "(" argument.list ")" 1157 * method.expr : THIS | SUPER | Identifier 1158 * | postfix.expr "." Identifier 1159 * | postfix.expr "#" Identifier 1160 */ parseMethodCall(SymbolTable tbl, ASTree expr)1161 private ASTree parseMethodCall(SymbolTable tbl, ASTree expr) 1162 throws CompileError 1163 { 1164 if (expr instanceof Keyword) { 1165 int token = ((Keyword)expr).get(); 1166 if (token != THIS && token != SUPER) 1167 throw new SyntaxError(lex); 1168 } 1169 else if (expr instanceof Symbol) // Identifier 1170 ; 1171 else if (expr instanceof Expr) { 1172 int op = ((Expr)expr).getOperator(); 1173 if (op != '.' && op != MEMBER) 1174 throw new SyntaxError(lex); 1175 } 1176 1177 return CallExpr.makeCall(expr, parseArgumentList(tbl)); 1178 } 1179 toClassName(ASTree name)1180 private String toClassName(ASTree name) 1181 throws CompileError 1182 { 1183 StringBuffer sbuf = new StringBuffer(); 1184 toClassName(name, sbuf); 1185 return sbuf.toString(); 1186 } 1187 toClassName(ASTree name, StringBuffer sbuf)1188 private void toClassName(ASTree name, StringBuffer sbuf) 1189 throws CompileError 1190 { 1191 if (name instanceof Symbol) { 1192 sbuf.append(((Symbol)name).get()); 1193 return; 1194 } 1195 else if (name instanceof Expr) { 1196 Expr expr = (Expr)name; 1197 if (expr.getOperator() == '.') { 1198 toClassName(expr.oprand1(), sbuf); 1199 sbuf.append('.'); 1200 toClassName(expr.oprand2(), sbuf); 1201 return; 1202 } 1203 } 1204 1205 throw new CompileError("bad static member access", lex); 1206 } 1207 1208 /* primary.expr : THIS | SUPER | TRUE | FALSE | NULL 1209 * | StringL 1210 * | Identifier 1211 * | NEW new.expr 1212 * | "(" expression ")" 1213 * | builtin.type ( "[" "]" )* "." CLASS 1214 * 1215 * Identifier represents either a local variable name, a member name, 1216 * or a class name. 1217 */ parsePrimaryExpr(SymbolTable tbl)1218 private ASTree parsePrimaryExpr(SymbolTable tbl) throws CompileError { 1219 int t; 1220 String name; 1221 Declarator decl; 1222 ASTree expr; 1223 1224 switch (t = lex.get()) { 1225 case THIS : 1226 case SUPER : 1227 case TRUE : 1228 case FALSE : 1229 case NULL : 1230 return new Keyword(t); 1231 case Identifier : 1232 name = lex.getString(); 1233 decl = tbl.lookup(name); 1234 if (decl == null) 1235 return new Member(name); // this or static member 1236 else 1237 return new Variable(name, decl); // local variable 1238 case StringL : 1239 return new StringL(lex.getString()); 1240 case NEW : 1241 return parseNew(tbl); 1242 case '(' : 1243 expr = parseExpression(tbl); 1244 if (lex.get() == ')') 1245 return expr; 1246 else 1247 throw new CompileError(") is missing", lex); 1248 default : 1249 if (isBuiltinType(t) || t == VOID) { 1250 int dim = parseArrayDimension(); 1251 if (lex.get() == '.' && lex.get() == CLASS) 1252 return parseDotClass(t, dim); 1253 } 1254 1255 throw new SyntaxError(lex); 1256 } 1257 } 1258 1259 /* new.expr : class.type "(" argument.list ")" 1260 * | class.type array.size [ array.initializer ] 1261 * | primitive.type array.size [ array.initializer ] 1262 */ parseNew(SymbolTable tbl)1263 private NewExpr parseNew(SymbolTable tbl) throws CompileError { 1264 ArrayInit init = null; 1265 int t = lex.lookAhead(); 1266 if (isBuiltinType(t)) { 1267 lex.get(); 1268 ASTList size = parseArraySize(tbl); 1269 if (lex.lookAhead() == '{') 1270 init = parseArrayInitializer(tbl); 1271 1272 return new NewExpr(t, size, init); 1273 } 1274 else if (t == Identifier) { 1275 ASTList name = parseClassType(tbl); 1276 t = lex.lookAhead(); 1277 if (t == '(') { 1278 ASTList args = parseArgumentList(tbl); 1279 return new NewExpr(name, args); 1280 } 1281 else if (t == '[') { 1282 ASTList size = parseArraySize(tbl); 1283 if (lex.lookAhead() == '{') 1284 init = parseArrayInitializer(tbl); 1285 1286 return NewExpr.makeObjectArray(name, size, init); 1287 } 1288 } 1289 1290 throw new SyntaxError(lex); 1291 } 1292 1293 /* array.size : [ array.index ]* 1294 */ parseArraySize(SymbolTable tbl)1295 private ASTList parseArraySize(SymbolTable tbl) throws CompileError { 1296 ASTList list = null; 1297 while (lex.lookAhead() == '[') 1298 list = ASTList.append(list, parseArrayIndex(tbl)); 1299 1300 return list; 1301 } 1302 1303 /* array.index : "[" [ expression ] "]" 1304 */ parseArrayIndex(SymbolTable tbl)1305 private ASTree parseArrayIndex(SymbolTable tbl) throws CompileError { 1306 lex.get(); // '[' 1307 if (lex.lookAhead() == ']') { 1308 lex.get(); 1309 return null; 1310 } 1311 else { 1312 ASTree index = parseExpression(tbl); 1313 if (lex.get() != ']') 1314 throw new CompileError("] is missing", lex); 1315 1316 return index; 1317 } 1318 } 1319 1320 /* argument.list : "(" [ expression [ "," expression ]* ] ")" 1321 */ parseArgumentList(SymbolTable tbl)1322 private ASTList parseArgumentList(SymbolTable tbl) throws CompileError { 1323 if (lex.get() != '(') 1324 throw new CompileError("( is missing", lex); 1325 1326 ASTList list = null; 1327 if (lex.lookAhead() != ')') 1328 for (;;) { 1329 list = ASTList.append(list, parseExpression(tbl)); 1330 if (lex.lookAhead() == ',') 1331 lex.get(); 1332 else 1333 break; 1334 } 1335 1336 if (lex.get() != ')') 1337 throw new CompileError(") is missing", lex); 1338 1339 return list; 1340 } 1341 } 1342 1343