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