1 24 25 package org.aspectj.compiler.base.parser; 26 27 import org.aspectj.compiler.base.ast.*; 28 import org.aspectj.compiler.base.cst.*; 29 import org.aspectj.compiler.base.*; 30 31 32 import java.util.*; 33 import java.io.*; 34 import java.util.Stack ; 35 36 public class JavaParser extends CompilerObject implements JavaConstants { 37 public boolean parseInterfaceOnly = false; 38 39 public JavaParser(JavaCompiler compiler) { 40 super(compiler); 41 if (compiler.getOptions().source.equals("1.4")) { 42 stmtParsers.put("assert", new AssertStmtParser()); 43 keywords.add("assert"); 44 } 45 } 46 47 public CompilationUnit interfaceParse(CompilationUnit cu) throws IOException { 48 tokenSource.setSourceInfo(cu.getSourceInfo()); 49 currentCompilationUnit = cu; 50 currentIndex = 0; 51 lastValidIndex = -1; 52 53 parseCompilationUnit(); 54 currentCompilationUnit.setScanned(true); 55 return currentCompilationUnit; 56 } 57 58 59 protected boolean inInterface; 60 61 private JavaTokenizer tokenSource = new JavaTokenizer(getCompiler()); 62 private static final int LOOKAHEAD_BUFFER_SIZE = 256; 64 private static final int LOOKAHEAD_MASK = LOOKAHEAD_BUFFER_SIZE-1; 65 private Token[] lookaheadBuffer = new Token[LOOKAHEAD_BUFFER_SIZE]; 66 public int currentIndex = 0; 67 private int lastValidIndex = -1; 68 69 private final void initTokenSource(int offset) { 70 currentIndex = 0; 71 lastValidIndex = -1; 72 tokenSource.setOffset(offset); 73 } 74 75 public void cleanup(boolean fully) { 76 tokenSource.cleanup(fully); 77 for (int i=0; i < LOOKAHEAD_BUFFER_SIZE; i++) { 78 lookaheadBuffer[i] = null; 79 } 80 lastValidIndex = -1; 81 } 82 83 private final Token getToken(int index) { 84 while (index > lastValidIndex) { 85 lastValidIndex++; 86 Token newToken = tokenSource.getNextToken(); 87 lookaheadBuffer[lastValidIndex&LOOKAHEAD_MASK] = newToken; 89 } 90 return lookaheadBuffer[index&LOOKAHEAD_MASK]; 91 } 92 93 private int savedIndex = -1; 94 protected final void pushCurrentIndex() { 96 savedIndex = currentIndex; 97 } 98 99 protected final void popCurrentIndex() { 100 currentIndex = savedIndex; 101 } 102 103 public final void eatTopToken(int kind) { 104 if (peekToken().kind != kind) { 105 throwError(peekToken(), "expected "+JavaConstants.tokenImage[kind]+", found "+peekToken().image); 106 } 107 currentIndex++; 108 } 109 110 public final boolean maybeEatToken(int kind) { 111 if (peekToken().kind == kind) { 112 currentIndex++; 113 return true; 114 } else { 115 return false; 116 } 117 } 118 119 public final void eatTopToken() { 120 currentIndex++; 121 } 122 123 public final Token popToken(int kind) { 124 return getToken(currentIndex++); 125 } 126 127 public final Token popToken() { 128 return getToken(currentIndex++); 129 } 130 131 public final Token peekToken() { 132 return getToken(currentIndex); 133 } 134 135 public final Token peekToken(int i) { 136 return getToken(currentIndex+i); 137 } 138 139 public int scanTillMatched() { 140 Token beginToken = peekToken(); 141 int kind = RBRACE; 142 if (beginToken.kind != LBRACE) 143 throwError(beginToken,"internal error: expected '{'"); 144 145 if (currentIndex != lastValidIndex) 149 throwError(beginToken,"internal error: lookahead of '{'"); 150 151 eatTopToken(); 153 154 try { 156 Token endToken = tokenSource.scanTillMatched(kind); 157 lastValidIndex++; 158 lookaheadBuffer[lastValidIndex&LOOKAHEAD_MASK] = endToken; 159 eatTopToken(); 161 return endToken.endPosition; 162 } catch (Exception e) { 163 showError(beginToken,"Unexpected end of file while looking matched close brace"); 164 } 165 return beginToken.endPosition; 166 } 167 168 private Stack enclosingTypeDecs = new Stack (); 169 170 public void pushEnclosingTypeDec(TypeDec dec) { 171 enclosingTypeDecs.push(dec); 172 } 174 175 public void popEnclosingTypeDec() { 176 enclosingTypeDecs.pop(); 177 } 178 179 public TypeDec peekEnclosingTypeDec() { 180 if (enclosingTypeDecs.size() == 0) return null; 181 return (TypeDec)enclosingTypeDecs.peek(); 182 } 183 184 protected void parseIdMatchingEnclosingTypeName(String where) { 185 Token beginToken = peekToken(); 186 String id; 187 if (beginToken.kind == NEW) { 188 id = "new"; 189 popToken(); 190 } else { 191 id = parseId(); 192 } 193 if ( id.equals(peekEnclosingTypeDec().getId())) return; 194 195 throwError(beginToken, where + " \"" + id + 196 "\" doesn't match enclosing type name \"" + 197 peekEnclosingTypeDec().getId()+"\""); 198 } 199 200 201 202 203 204 205 protected Set keywords = new HashSet(Arrays.asList(new String [] 207 { "abstract", "boolean", "break", "byte", "case", "catch", 208 "char", "class", "const", "continue", 209 "default", "do", "double", "else", "extends", 210 "final", "finally", "float", "for", "goto", 211 "if", "implements", "import", "intstanceof", "int", 212 "interface", "long", "native", "new", "package", 213 "private", "protected", "public", "return", "short", 214 "static", "strictfp", "super", "switch", "synchronized", 215 "this", "throw", "throws", "transient", "try", 216 "void", "volatile", "while", 217 "true", "false", "null", "instanceof" })); 219 220 private Map primitiveTypeNames = new HashMap(); 221 { 222 primitiveTypeNames.put("int", getTypeManager().intType); 223 primitiveTypeNames.put("byte", getTypeManager().byteType); 224 primitiveTypeNames.put("short", getTypeManager().shortType); 225 primitiveTypeNames.put("long", getTypeManager().longType); 226 primitiveTypeNames.put("double", getTypeManager().doubleType); 227 primitiveTypeNames.put("float", getTypeManager().floatType); 228 primitiveTypeNames.put("char", getTypeManager().charType); 229 primitiveTypeNames.put("boolean", getTypeManager().booleanType); 230 primitiveTypeNames.put("void", getTypeManager().voidType); 231 } 232 public TypeD lookupPrimitiveTypeD(String name) { 233 Type type = (Type)primitiveTypeNames.get(name); 234 if (type == null) return null; 235 return type.makeTypeD(); 236 } 237 238 protected static Map modifiers = new HashMap(); 239 static { 240 modifiers.put("public", new Integer (Modifiers.PUBLIC)); 241 modifiers.put("protected", new Integer (Modifiers.PROTECTED)); 242 modifiers.put("private", new Integer (Modifiers.PRIVATE)); 243 modifiers.put("static", new Integer (Modifiers.STATIC)); 244 modifiers.put("final", new Integer (Modifiers.FINAL)); 245 modifiers.put("abstract", new Integer (Modifiers.ABSTRACT)); 246 modifiers.put("native", new Integer (Modifiers.NATIVE)); 247 modifiers.put("synchronized", new Integer (Modifiers.SYNCHRONIZED)); 248 modifiers.put("transient", new Integer (Modifiers.TRANSIENT)); 249 modifiers.put("volatile", new Integer (Modifiers.VOLATILE)); 250 modifiers.put("strictfp", new Integer (Modifiers.STRICT)); 251 } 252 public final boolean isModifier(Token token) { 253 return getModifier(token) != null; 254 } 255 256 public final Integer getModifier(Token token) { 257 if (!isIdentifier(token)) return null; 258 return (Integer )modifiers.get(token.image); 259 } 260 261 protected Map decParsers = new HashMap(); 262 { 263 decParsers.put("class", new ClassDecParser()); 264 decParsers.put("interface", new InterfaceDecParser()); 265 } 266 267 protected Map stmtDecParsers = new HashMap(); 268 { 269 stmtDecParsers.put("class", new ClassDecParser()); 270 stmtDecParsers.put("interface", new InterfaceDecParser()); 271 } 272 273 274 protected Map stmtParsers = new HashMap(); 275 { 276 277 278 stmtParsers.put("if", new IfStmtParser()); 279 stmtParsers.put("while", new WhileStmtParser()); 280 stmtParsers.put("do", new DoStmtParser()); 281 stmtParsers.put("for", new ForStmtParser()); 282 283 stmtParsers.put("synchronized", new SynchronizedStmtParser()); 284 stmtParsers.put("try", new TryStmtParser()); 285 stmtParsers.put("switch", new SwitchStmtParser()); 286 287 stmtParsers.put("break", new BreakStmtParser()); 288 stmtParsers.put("continue", new ContinueStmtParser()); 289 stmtParsers.put("return", new ReturnStmtParser()); 290 stmtParsers.put("throw", new ThrowStmtParser()); 291 292 stmtParsers.put("goto", new GotoStmtParser()); 293 } 294 295 protected SourceLocation dummySource = new DummySourceLocation(getCompiler()); 296 297 protected class NewOperator extends PrefixOperator { 298 public NewOperator(int precedence) { 299 super("new", precedence); 300 } 301 302 private NewArrayExpr parseNewArrayExprWithInitializer(ArrayTypeD typeD) { 303 ArrayInitializer init = null; 304 if (peekToken().kind == LBRACE) { 305 init = parseArrayInitializer(); 306 } else { 307 showError(peekToken(), "'{' expected"); 308 } 309 return new NewArrayExpr(dummySource, typeD, init, null); 311 } 312 313 private NewArrayExpr parseNewArrayExpr(TypeD typeD) { 314 Exprs dimExprs = null; 315 if (peekToken().kind == LBRACKET) { 316 dimExprs = parseArrayDimExprs(); 317 for(int i=0; i<dimExprs.size(); i++) { 318 typeD = new ArrayTypeD(dummySource,typeD); 319 } 320 } 321 return new NewArrayExpr(dummySource,(ArrayTypeD)typeD, null, dimExprs); 322 } 323 324 public Expr parse() { 325 Token beginToken = peekToken(); 326 327 eatTopToken(); TypeD typeD = parseTypeD(); 329 if (typeD == null) { 330 throwError(peekToken(), "type expected"); 331 } 332 333 if (maybeEatToken(LPAREN)) { 334 Exprs args = parseExprs(RPAREN); 335 eatTopToken(RPAREN); 336 337 TypeDec typeDec = maybeParseClassBody(typeD); 338 return new NewInstanceExpr(dummySource, null, (TypeD)typeD, args, typeDec, null); 339 } else if (typeD instanceof ArrayTypeD) { 340 return parseNewArrayExprWithInitializer((ArrayTypeD)typeD); 342 } else if (peekToken().kind == LBRACKET) { 343 return parseNewArrayExpr(typeD); 345 } else { 346 throwError(peekToken(), "( or [ expected"); 347 return null; 348 } 349 } 350 } 351 352 TypeDec maybeParseClassBody(TypeD superTypeD) { 353 if (peekToken().kind == LBRACE) { 354 Token beginToken = peekToken(); 355 Modifiers mods = new Modifiers(makeSourceLocation(beginToken), 0); 356 if (superTypeD != null) superTypeD = (TypeD)superTypeD.copy(); 357 ClassDec classDec = 358 new ClassDec(dummySource, mods, 359 "ANONYMOUS", superTypeD, 360 null, null); 361 classDec.setIsAnonymous(); 362 classDec.setLocal(); 363 Decs body = null; 364 boolean oldInInterface = inInterface; 365 try { 366 inInterface = false; 367 pushEnclosingTypeDec(classDec); 368 body = parseDecs(); 369 } finally { 370 inInterface = oldInInterface; 371 popEnclosingTypeDec(); } 373 classDec.setBody(body); 374 375 classDec.setEnclosingTypeDec(peekEnclosingTypeDec()); 376 addContext(classDec, beginToken); 377 return classDec; 378 } else { 379 return null; 380 } 381 } 382 383 384 protected class ParenOperator extends PrefixOperator { 385 protected boolean allowCasts = false; 386 387 public ParenOperator(int precedence, boolean allowCasts) { 388 super("(", precedence); 389 this.allowCasts = allowCasts; 390 } 391 public ParenOperator(int precedence) { 392 this(precedence, false); 393 } 394 395 private boolean notPlusMinus(int kind) { 396 switch (kind) { 397 case PLUS: 398 case MINUS: 399 case INCR: 400 case DECR: 401 case HOOK: 403 case SEMICOLON: 404 return false; 405 default: 406 return true; 407 } 408 } 409 410 public Expr parse() { 412 eatTopToken(); 414 if (!allowCasts) return basicParse(); 415 416 int savedIndex = currentIndex; Token nextToken = peekToken(); 422 423 425 if ((nextToken.isIdentifier() && primitiveTypeNames.get(nextToken.image) != null)) { 426 TypeD typeD = parseTypeD(); 427 eatTopToken(RPAREN); 428 return new CastExpr(dummySource,typeD, exprParser.parse(1500)); 429 } else if (eatTypeD() && popToken().kind == RPAREN && 430 notPlusMinus(popToken().kind)) { 431 currentIndex = savedIndex; 432 TypeD typeD = parseTypeD(); 433 eatTopToken(RPAREN); 434 Expr expr = exprParser.parse(1500); if (expr != null) return new CastExpr(dummySource,typeD, expr); 436 } 437 438 currentIndex = savedIndex; 439 return basicParse(); 440 } 441 442 protected Expr basicParse() { 443 Expr expr = parentParse(); 444 eatTopToken(RPAREN); 445 return new ParenExpr(dummySource,expr); 446 } 447 448 } 449 450 451 abstract protected class Operator { 452 protected int precedence; 453 protected String image; 454 protected int tokenKind; 455 456 private ExprParser parent; 457 458 protected Operator(int tokenKind, int precedence) { 459 this.precedence = precedence; 460 this.tokenKind = tokenKind; 461 this.image = tokenImage[tokenKind]; 462 } 463 464 protected Operator(String image, int precedence) { 465 int tokenKind = 0; 466 String testImage = "\"" + image + "\""; 467 468 for(;tokenKind < tokenImage.length; tokenKind++) { 469 String maybeImage = tokenImage[tokenKind]; 470 if (maybeImage != null && maybeImage.equals(testImage)) { 471 break; 472 } 473 } 474 475 if (tokenKind == tokenImage.length) { 476 tokenKind = tokenSource.addOperator(image); 477 } 478 479 this.tokenKind = tokenKind; 480 this.image = image; 481 this.precedence = precedence; 482 } 483 484 public int getTokenKind() { 485 return tokenKind; 486 } 487 488 public void setParent(ExprParser parent) { 489 this.parent = parent; 490 } 491 492 public Expr parentParse() { 493 Expr ret = parent.parse(); 494 if (ret == null) throwError(null, "expression expected"); 495 return ret; 496 } 497 498 public Expr parentParse(int precedence) { 499 Expr ret = parent.parse(precedence); 500 if (ret == null) throwError(null, "expression expected"); 501 return ret; 502 } 503 } 504 505 protected class MinusOperator extends PrefixOperator { 506 public MinusOperator(int precedence) { 507 super("-", precedence); 508 } 509 510 public Expr parse() { 511 eatTopToken(); 512 if (peekToken().kind == INTEGER_LITERAL) { 514 Token t = popToken(); 515 return t.getNegativeExpr(makeSourceLocation(peekToken(-1))); 516 } else { 517 return new MinusOpExpr(makeSourceLocation(peekToken(-1)), 518 image, parentParse(precedence)); 519 } 520 } 521 } 522 523 protected class PrefixOperator extends Operator { 524 protected PrefixOperator(int tokenKind, int precedence) { 525 super(tokenKind, precedence); 526 } 527 528 public PrefixOperator(String image, int precedence) { 529 super(image, precedence); 530 } 531 532 public Expr parse() { 533 eatTopToken(); 534 return UnopExpr.build(dummySource, image, parentParse(precedence)); 536 } 537 } 538 539 540 protected abstract class LiteralOp extends PrefixOperator { 541 public LiteralOp(int tokenKind) { 542 super(tokenKind, -1); 543 } 544 545 public LiteralOp(String image) { 546 super(image, -1); 547 } 548 549 public Expr parse() { 550 Token token = peekToken(); 551 Expr expr = parse(token.image); 552 return expr; 553 } 554 555 public abstract Expr parse(String image); 556 } 557 558 559 protected class TrueLiteral extends LiteralOp { 560 public TrueLiteral() { super("true"); } 561 562 public Expr parse(String image) { 563 eatTopToken(); 564 return new BooleanLiteralExpr(dummySource,true); 565 } 566 } 567 568 protected class FalseLiteral extends LiteralOp { 569 public FalseLiteral() { super("false"); } 570 571 public Expr parse(String image) { 572 eatTopToken(); 573 return new BooleanLiteralExpr(dummySource,false); 574 } 575 } 576 577 protected class NullLiteral extends LiteralOp { 578 public NullLiteral() { super("null"); } 579 580 public Expr parse(String image) { 581 eatTopToken(); 582 return new NullExpr(dummySource); 583 } 584 } 585 586 protected class ThisLiteral extends LiteralOp { 587 public ThisLiteral() { super("this"); } 588 589 public Expr parse(String image) { 590 eatTopToken(); 591 return new ThisExpr(dummySource); 592 } 593 } 594 595 protected class SuperLiteral extends LiteralOp { 596 public SuperLiteral() { super("super"); } 597 598 public Expr parse(String image) { 599 eatTopToken(); 600 return new SuperExpr(dummySource); 601 } 602 } 603 604 public Expr parseCallExpr(Name name) { 605 607 String id = name.getId(); 608 Name parentName = name.getParentName(); 609 Exprs args = parseExprs(RPAREN); 610 eatTopToken(RPAREN); 611 Expr expr = null; 612 if (parentName != null) { 613 parentName.clearParent(); 614 expr = new UnresolvedExpr(dummySource,parentName); 615 expr.setSource(parentName); 616 } 617 618 if (id.equals("this")) { 619 if (parentName != null) throwError(null, "bad this"); 620 return new ConstructorCallExpr(dummySource, null, false, args, null); 621 } else if (id.equals("super")) { 622 if (parentName != null) throwError(null, "bad super"); 623 return new ConstructorCallExpr(dummySource, null, true, args, null); 624 } 625 626 return new CallExpr(dummySource,expr, id, args); 627 } 628 629 630 protected class IdentifierOp extends LiteralOp { 631 public IdentifierOp() { super(IDENTIFIER); } 632 633 public Expr parse(String image) { 634 TypeD typeD = lookupPrimitiveTypeD(image); 635 if (typeD != null) { 636 eatTopToken(); 637 return new TypeExpr(dummySource, typeD); 638 } 639 640 Name name = parseExtendedName(); 641 642 if (maybeEatToken(LPAREN)) { 643 return parseCallExpr(name); 644 } 645 return new UnresolvedExpr(dummySource,name); 646 } 647 } 648 649 protected class InfixOperator extends Operator { 650 protected InfixOperator(int tokenKind, int precedence) { 651 super(tokenKind, precedence); 652 } 653 654 public InfixOperator(String image, int precedence) { 655 super(image, precedence); 656 } 657 658 public Expr parse(Expr lhs, int minimumPrecedence) { 659 if (precedence <= minimumPrecedence) return lhs; 660 eatTopToken(); 661 662 return parse(lhs); 663 } 664 665 public Expr parse(Expr lhs) { 666 return BinopExpr.build(dummySource,this.image, lhs, parentParse(precedence)); 668 } 669 } 670 671 private Name buildName(Expr expr) { 672 if (expr instanceof UnresolvedExpr) { 673 return ((UnresolvedExpr)expr).getName(); 674 } else { 675 return null; 676 } 677 } 678 679 private TypeD exprToTypeD(Expr lhs) { 680 if (lhs instanceof TypeExpr) { 681 return ((TypeExpr)lhs).getTypeD(); 682 } 683 684 Name id = buildName(lhs); 685 TypeD ret = null; 686 if (id == null) return null; 687 if (id.getParentName() == null) { 688 TypeD primTypeD = lookupPrimitiveTypeD(id.getId()); 689 if (primTypeD != null) ret = primTypeD; 690 } 691 id.clearParent(); 692 if (ret == null) ret = new UnresolvedNameTypeD(dummySource,id); 693 ret.setSource(lhs); 694 return ret; 695 } 696 697 private TypeD exprToTypeD(Expr lhs, String name) { 698 TypeD ret = exprToTypeD(lhs); 699 if (ret == null) { 700 throwError(peekToken(-2), "type required before "+name); 701 } 702 703 addContext(ret, lhs); 704 return ret; 705 } 706 707 protected class DotOperator extends InfixOperator { 708 public DotOperator(int precedence) { 709 super(".", precedence); 710 } 711 712 public Expr parse(Expr lhs) { 713 if (maybeEatKeyword("new")) { 715 String innerName = parseId(); 716 eatTopToken(LPAREN); 717 Exprs args = parseExprs(RPAREN); 718 eatTopToken(RPAREN); 719 TypeDec typeDec = maybeParseClassBody(null); 720 return new NewInnerInstanceExpr(dummySource, 721 lhs, null, args, typeDec, 722 null, innerName); 723 } 724 725 String id = parseIdOrKeywords_this_super_class(); 726 if (id.equals("this")) { 727 return new QualifiedThisExpr(dummySource,exprToTypeD(lhs, ".this")); 728 } else if (id.equals("super")) { 729 if (inConstructor() && maybeEatToken(LPAREN)) { 730 Exprs args = parseExprs(RPAREN); 731 eatTopToken(RPAREN); 732 return new ConstructorCallExpr(dummySource, lhs, true, args, null); 733 } else { 734 return new QualifiedSuperExpr(dummySource,exprToTypeD(lhs, ".super")); 735 } 736 } else if (id.equals("class")) { 737 return new ClassExpr(dummySource,exprToTypeD(lhs, ".class")); 738 } else if (maybeEatToken(LPAREN)) { 739 Exprs args = parseExprs(RPAREN); 740 eatTopToken(RPAREN); 741 return new CallExpr(dummySource,lhs, id, args); 742 } else { 743 return new UnresolvedFieldAccessExpr(dummySource,lhs, id); 744 } 745 } 746 } 747 748 protected class AssignOperator extends InfixOperator { 749 public AssignOperator(String image, int precedence) { 750 super(image, precedence); 751 } 752 753 public Expr parse(Expr lhs) { 754 Expr rhs = parentParse(precedence-1); 755 String s = this.image; 756 return AssignExpr.build(dummySource,checkAssignable(lhs), 757 s.substring(0, s.length() - 1), 758 rhs); 759 } 760 } 761 762 protected class ArrayOperator extends InfixOperator { 763 public ArrayOperator(int precedence) { 764 super("[", precedence); 765 } 766 767 public Expr parse(Expr lhs) { 768 if (peekToken().kind == RBRACKET) { 770 TypeD typeD = exprToTypeD(lhs, ".class"); 772 currentIndex--; 774 typeD = addBracketsToTypeD(typeD); 775 eatTopToken(DOT); 776 eatKeyword("class"); 777 return new ClassExpr(dummySource,typeD); 778 } 779 780 Expr index = parseExpr(); 781 eatTopToken(RBRACKET); 782 return new ArrayExpr(dummySource,lhs, index); 783 } 784 } 785 786 protected class QuestionOperator extends InfixOperator { 787 public QuestionOperator(int precedence) { 788 super("?", precedence); 789 } 790 791 public Expr parse(Expr lhs) { 792 Expr trueExpr = parentParse(0); 794 eatTopToken(COLON); 795 Expr falseExpr = parseExpr(); 796 return new TriTestExpr(dummySource,lhs, trueExpr, falseExpr); 797 } 798 } 799 800 protected class InstanceOfOperator extends InfixOperator { 801 public InstanceOfOperator(int precedence) { 802 super("instanceof", precedence); 803 } 804 805 public Expr parse(Expr lhs) { 806 TypeD typeD = parseTypeD(); 807 return new InstanceofExpr(dummySource,lhs, typeD); 808 } 809 } 810 811 820 AssignableExpr checkAssignable(Expr expr) { 821 if (expr instanceof AssignableExpr) return (AssignableExpr)expr; 822 if (expr instanceof ParenExpr) { 823 return checkAssignable( ((ParenExpr)expr).getExpr() ); 824 } 825 expr.showError("invalid lhs for assign: "+expr.getClass().getName()); 826 return null; 827 } 828 829 protected class PreOperator extends PrefixOperator { 830 public PreOperator(String image, int precedence) { 831 super(image, precedence); 832 } 833 834 public Expr parse() { 835 eatTopToken(); return new PrefixExpr(dummySource,checkAssignable(parentParse(precedence)), image); 837 } 838 } 839 840 protected class PostOperator extends InfixOperator { 841 public PostOperator(String image, int precedence) { 842 super(image, precedence); 843 } 844 845 public Expr parse(Expr lhs) { 846 return new PostfixExpr(dummySource,checkAssignable(lhs), image); 847 } 848 } 849 850 private static final int MAX_TOKEN_KINDS = 512; 851 852 protected class ExprParser { 853 protected PrefixOperator[] prefixOps; 855 protected InfixOperator[] infixOps; 856 857 private boolean allowLiterals = true; 858 859 public ExprParser() { 860 int tokenTypes = tokenImage.length; 861 862 prefixOps = new PrefixOperator[MAX_TOKEN_KINDS]; 863 infixOps = new InfixOperator[MAX_TOKEN_KINDS]; 864 } 866 867 private final void fillOps(Operator[] ops, Operator[] toArray) { 868 for(int i=0; i<ops.length; i++) { 869 Operator op = ops[i]; 870 toArray[op.getTokenKind()] = op; 871 op.setParent(this); 872 } 873 } 874 875 public ExprParser(PrefixOperator[] prefixes, InfixOperator[] infixes, 876 boolean allowLiterals) 877 { 878 this(prefixes, infixes); 879 this.allowLiterals = allowLiterals; 880 } 881 882 public ExprParser(PrefixOperator[] prefixes, InfixOperator[] infixes) { 883 this(); 884 885 fillOps(prefixes, prefixOps); 886 fillOps(infixes, infixOps); 887 } 888 889 public void addInfixOperator(InfixOperator op) { 890 infixOps[op.getTokenKind()] = op; 891 op.setParent(this); 892 } 893 894 public void addPrefixOperator(PrefixOperator op) { 895 prefixOps[op.getTokenKind()] = op; 896 op.setParent(this); 897 } 898 899 904 905 public Expr parseTerminal() { 906 Token token = peekToken(); 907 int kind = token.kind; 908 909 Expr literalExpr = token.getExpr(makeSourceLocation(token)); 910 if (literalExpr != null && allowLiterals) { 911 eatTopToken(); 912 return literalExpr; 913 } 914 915 PrefixOperator op = prefixOps[kind]; 916 if (op == null && token.isIdentifier()) { 917 op = prefixOps[IDENTIFIER]; 918 } 919 920 if (op != null) { 921 return op.parse(); 922 } 923 924 return null; 925 } 926 927 public Expr parseOperator(Expr lhs, int minimumPrecedence) { 928 Token token = peekToken(); 929 int kind = token.kind; 930 931 InfixOperator op = infixOps[kind]; 932 if (op != null) { 933 return op.parse(lhs, minimumPrecedence); 934 } 935 return lhs; 936 } 937 938 public Expr parseAll(Expr lhs, int minimumPrecedence, Token beginToken) { 939 Expr ret; 940 while ((ret = parseOperator(lhs, minimumPrecedence)) != lhs && ret != null) { 943 addContext(ret, beginToken); 944 beginToken = peekToken(); 945 lhs = ret; 946 } 947 return ret; 948 } 949 950 protected Expr parse(int minimumPrecedence) { 951 Token beginToken = peekToken(); 952 Expr lhs = parseTerminal(); 953 if (lhs == null) return null; 954 addContext(lhs, beginToken); 955 return parseAll(lhs, minimumPrecedence, beginToken); 956 } 957 958 public Expr parse() { 959 return parse(0); 960 } 961 } 962 963 private InfixOperator[] infixOperators = { 964 new QuestionOperator(200), 965 966 new InfixOperator("||", 300), 967 new InfixOperator("&&", 400), 968 969 new InfixOperator("|", 500), 970 new InfixOperator("^", 600), 971 new InfixOperator("&", 700), 972 973 new InfixOperator("==", 800), 974 new InfixOperator("!=", 800), 975 976 new InstanceOfOperator(900), 977 978 new InfixOperator(">", 1000), 979 new InfixOperator("<", 1000), 980 new InfixOperator("<=", 1000), 981 new InfixOperator(">=", 1000), 982 983 new InfixOperator("<<", 1100), 984 new InfixOperator(">>", 1100), 985 new InfixOperator(">>>", 1100), 986 987 new InfixOperator("+", 1200), 988 new InfixOperator("-", 1200), 989 990 new InfixOperator("*", 1300), 991 new InfixOperator("/", 1300), 992 new InfixOperator("%", 1300), 993 994 new PostOperator("++", 4000), new PostOperator("--", 4000), 996 997 new ArrayOperator(5000), 999 new DotOperator(5000), 1000 1001 new AssignOperator("=", 100), 1003 new AssignOperator("+=", 100), 1004 new AssignOperator("-=", 100), 1005 new AssignOperator("*=", 100), 1006 new AssignOperator("/=", 100), 1007 new AssignOperator("&=", 100), 1008 new AssignOperator("|=", 100), 1009 new AssignOperator("^=", 100), 1010 new AssignOperator("%=", 100), 1011 new AssignOperator("<<=", 100), 1012 new AssignOperator(">>=", 100), 1013 new AssignOperator(">>>=", 100), 1014 }; 1015 1016 private PrefixOperator[] prefixOperators = { 1017 new PrefixOperator("+", 2000), 1018 new MinusOperator(2000), 1019 new PrefixOperator("!", 3000), 1020 new PrefixOperator("~", 3000), 1021 1022 new PreOperator("++", 2500), 1023 new PreOperator("--", 2500), 1024 1025 new ParenOperator(1, true), 1026 new NewOperator(1), 1027 1028 new TrueLiteral(), 1029 new FalseLiteral(), 1030 new NullLiteral(), 1031 new ThisLiteral(), 1032 new SuperLiteral(), 1033 1034 new IdentifierOp() 1035 }; 1036 1037 1038 protected ExprParser exprParser = new ExprParser(prefixOperators, infixOperators); 1039 1040 1041 public final boolean eatKeyword(String keyword, boolean isMaybe) { 1042 Token topToken = peekToken(); 1043 if (topToken.isIdentifier() && topToken.image.equals(keyword)) { 1044 eatTopToken(); 1045 return true; 1046 } else { 1047 if (!isMaybe) { 1048 throwError(topToken, "expected keyword: '"+keyword+"'"); 1049 } 1050 return false; 1051 } 1052 } 1053 1054 public final boolean peekKeyword(String keyword) { 1055 Token topToken = peekToken(); 1056 if (topToken.isIdentifier() && topToken.image.equals(keyword)) { 1057 return true; 1058 } else { 1059 return false; 1060 } 1061 } 1062 1063 public final boolean eatKeyword(String keyword) { 1064 return eatKeyword(keyword, false); 1065 } 1066 1067 public final boolean maybeEatKeyword(String keyword) { 1068 return eatKeyword(keyword, true); 1069 } 1070 1071 public final boolean isIdentifier(Token token) { 1072 return token.isIdentifier() && !token.image.equals("new"); 1074 } 1075 1076 public final boolean isIdentifierOrNew(Token token) { 1077 return token.isIdentifier(); 1078 } 1079 1080 public final boolean isKeyword(Token token) { 1081 return keywords.contains(token.image); 1082 } 1083 1084 1085 protected CompilationUnit currentCompilationUnit; 1086 1087 private CompilationUnit parseCompilationUnit() { 1088 Token beginToken0 = peekToken(); 1089 1090 Decs decs = new Decs(dummySource); 1091 currentCompilationUnit.setDecs(decs); 1092 1093 if (maybeEatKeyword("package")) { 1095 String name = parseExtendedString(false); 1096 if (name != null) { 1097 currentCompilationUnit.setPackageName(name); 1098 } else { 1099 showError(peekToken(), "package name expected"); 1100 } 1101 1102 eatTopToken(SEMICOLON); 1103 } 1104 1105 Token beginImportsToken = peekToken(); 1106 Imports imports = new Imports(dummySource); 1107 while (peekKeyword("import")) { 1108 imports.add(parseImport()); 1109 } 1110 addContext(imports, beginImportsToken); 1111 1112 while (peekToken().kind != EOF) { 1113 if (peekToken().kind == SEMICOLON) { 1114 eatTopToken(); continue; 1115 } 1116 Token beginToken = peekToken(); 1117 Dec dec = (Dec)parseTopDec(null); 1118 addContext(dec, beginToken); 1119 1120 if (dec instanceof TypeDec) { 1121 decs.add(dec); 1122 } else { 1123 throwError(null, "expected import, package, type or aspect declaration"); 1124 } 1125 } 1126 1127 addContext(decs, beginToken0); 1128 1129 currentCompilationUnit.setImports(imports); 1130 addContext(currentCompilationUnit, beginToken0); 1131 return currentCompilationUnit; 1132 } 1133 1134 public Import parseImport() { 1135 Token beginToken = peekToken(); 1136 eatKeyword("import"); 1137 Name name = parseExtendedName(); 1138 1139 boolean star = false; 1140 if (peekToken(0).kind == DOT && peekToken(1).kind == STAR) { 1141 eatTopToken(); eatTopToken(); 1142 star = true; 1143 } 1144 eatTopToken(SEMICOLON); 1145 return new Import(makeSourceLocation(beginToken), name, star); 1146 } 1147 1148 1149 protected boolean eatModifiers() { 1150 Token token; 1151 while (isModifier(token=peekToken())) { 1152 eatTopToken(); 1153 } 1154 return true; 1155 } 1156 1157 public void parseNoModifiers() { 1158 parseModifiers(0); 1159 } 1160 1161 public Modifiers parseModifiers(int legalModifiers) { 1162 Token beginToken = peekToken(); 1163 int modifierValue = 0; 1164 while (true) { 1165 Integer ivalue = getModifier(peekToken()); 1166 if (ivalue == null) break; 1167 1168 int value = ivalue.intValue(); 1169 if ((legalModifiers & value) != value) { 1170 showError(peekToken(), "modifier " + peekToken().image + " not allowed here"); 1171 } else if ((modifierValue & value) != 0) { 1172 showError(peekToken(), "repeated modifier"); 1173 } else { 1174 modifierValue |= value; 1175 } 1176 eatTopToken(); 1177 } 1178 return new Modifiers(makeSourceLocation(beginToken), modifierValue); 1179 } 1180 1181 public TypeDs parseTypeDs() { 1182 Token beginToken = peekToken(); 1183 TypeD nameTypeD; 1184 List names = null; 1185 while ((nameTypeD = parseTypeD()) != null) { 1186 if (names == null) names = new ArrayList(); 1187 names.add(nameTypeD); 1188 if (peekToken().kind != COMMA) break; 1189 eatTopToken(); 1190 } 1191 if (names == null) { 1192 return null; 1193 } else { 1194 TypeDs ret = new TypeDs(dummySource,(TypeD[])names.toArray(new TypeD[0])); 1195 addContext(ret, beginToken); 1196 return ret; 1197 } 1198 } 1199 1200 public String parseIdPattern() { 1201 if (maybeEatToken(STAR)) { 1202 return "*"; 1203 } else { 1204 return parseId(); 1205 } 1206 } 1207 1208 protected boolean eatIdentifier(boolean onlyDec) { 1209 if (!isIdentifier(peekToken())) return false; 1210 eatTopToken(); 1211 return true; 1212 } 1213 1214 public boolean lookaheadVarDes() { 1215 pushCurrentIndex(); 1216 eatModifiers(); 1217 boolean isVarDes = (eatModifiers() && eatTypeD() && eatIdentifier(true)); 1218 popCurrentIndex(); 1219 return isVarDes; 1220 } 1221 1222 public Name parseExtendedName() { 1223 if (!isSimpleIdentifier(peekToken())) return null; 1224 return parseExtendedName(null); 1225 } 1226 1227 1228 public boolean isSimpleIdentifier(Token t) { 1229 return t.isIdentifier() && 1231 (lookupPrimitiveTypeD(t.image) != null || !isKeyword(t)); 1232 } 1233 1234 private boolean inConstructor = false; 1236 public boolean inConstructor() { 1237 return inConstructor; 1238 } 1239 1240 1241 public Name parseExtendedName(Name parentName) { 1242 Token beginToken = peekToken(); 1243 Name name = new Name(dummySource, parentName, parseId()); 1244 addContext(name, beginToken); 1245 if (peekToken(0).kind == DOT && isSimpleIdentifier(peekToken(1))) { 1246 eatTopToken(); 1247 return parseExtendedName(name); 1248 } else { 1249 return name; 1250 } 1251 } 1252 1253 public String parseExtendedString(boolean allowStar) { 1254 if (!isIdentifier(peekToken())) return null; 1255 StringBuffer buf = new StringBuffer (parseId()); 1256 while (peekToken().kind == DOT) { 1257 eatTopToken(); 1258 buf.append("."); 1259 if (allowStar && peekToken().kind == STAR) { 1260 eatTopToken(); 1261 buf.append("*"); 1262 } else { 1263 buf.append(parseId()); 1264 } 1265 } 1266 return buf.toString(); 1267 } 1268 1269 1270 public TypeD parseNameTypeD() { 1271 Token beginToken = peekToken(); 1272 Name name = parseExtendedName(); 1273 if (name == null) { 1274 throwError(null, "name expected"); 1275 } 1276 TypeD ret = new UnresolvedNameTypeD(dummySource,name); 1277 addContext(ret, beginToken); 1278 return ret; 1279 } 1280 1281 public TypeD addBracketsToTypeD(TypeD typeD) { 1282 while (peekToken().kind == LBRACKET && peekToken(1).kind == RBRACKET) { 1283 eatTopToken(); eatTopToken(); 1284 TypeD oldTypeD = typeD; 1285 typeD = new ArrayTypeD(dummySource,typeD); 1286 addContext(typeD, oldTypeD); 1287 } 1288 return typeD; 1289 } 1290 1291 1292 public TypeD parseTypeD() { 1293 Token beginToken = peekToken(); 1294 TypeD typeD = lookupPrimitiveTypeD(beginToken.image); 1295 if (typeD != null) { 1296 eatTopToken(); 1297 } else { 1298 typeD = parseNameTypeD(); 1299 } 1300 1301 addContext(typeD, beginToken); 1302 typeD = addBracketsToTypeD(typeD); 1303 return typeD; 1304 } 1305 1306 protected boolean eatTypeD() { 1307 if (!isSimpleIdentifier(peekToken())) return false; 1308 eatTopToken(); 1309 while (peekToken().kind == DOT) { 1310 eatTopToken(); 1311 if (peekToken().kind == DOT) continue; 1312 if (!isSimpleIdentifier(peekToken())) { 1313 currentIndex -= 1; 1314 return true; 1315 } 1316 eatTopToken(); 1317 } 1318 1319 while (peekToken().kind == LBRACKET && peekToken(1).kind == RBRACKET) { 1320 eatTopToken(); eatTopToken(); 1321 } 1322 return true; 1323 } 1324 1325 public FormalDec parseFormal() { 1326 Token beginToken = peekToken(); 1327 Modifiers modifiers = parseModifiers(Modifiers.FINAL); 1328 TypeD typeD = parseTypeD(); 1329 String id = parseId(); 1330 typeD = addBracketsToTypeD(typeD); 1332 FormalDec ret = new FormalDec(dummySource,modifiers, typeD, id, null); 1333 addContext(ret, beginToken); 1334 return ret; 1335 } 1336 1337 public Formals parseFormals() { 1338 Token beginToken = peekToken(); 1339 eatTopToken(LPAREN); 1340 1341 Formals ret=new Formals(dummySource); 1342 if (peekToken().kind == RPAREN) { 1343 eatTopToken(); 1344 addContext(ret, beginToken); 1345 return ret; 1346 } 1347 1348 while (true) { 1349 FormalDec formal = parseFormal(); 1350 ret.add(formal); 1351 1352 Token t = popToken(); 1353 if (t.kind == RPAREN) break; 1354 else if (t.kind == COMMA) continue; 1355 throwError(t, "parsing formals"); 1356 } 1357 addContext(ret, beginToken); 1358 return ret; 1359 } 1360 1361 public BlockStmt parseOptionalBlockStmt() { 1362 if (peekToken().kind == SEMICOLON) { 1363 eatTopToken(); 1364 return null; 1365 } else { 1366 return parseBlockStmt(); 1367 } 1368 } 1369 1370 public Stmts parseStmts(int endToken) { 1371 Token beginToken = peekToken(); 1372 Stmts stmts = new Stmts(dummySource); 1373 while (peekToken().kind != endToken) { 1374 stmts.add(parseStmt()); 1375 } 1376 addContext(stmts, beginToken); 1377 eatTopToken(endToken); 1378 return stmts; 1379 } 1380 1381 public BlockStmt parseBlockStmt() { 1382 Token beginToken = peekToken(); 1383 eatTopToken(LBRACE); 1384 1385 Stmts stmts = parseStmts(RBRACE); 1386 BlockStmt ret = new BlockStmt(dummySource,stmts); 1387 addContext(ret, beginToken); 1388 return ret; 1389 } 1390 1391 1392 1393 public CodeBody parseOptionalCodeBody() { 1394 Token beginToken = peekToken(); 1395 if (maybeEatToken(SEMICOLON)) return null; 1396 1397 return parseCodeBody(); 1398 } 1399 1400 public CodeBody parseCodeBodyFully() { 1401 boolean oldParseInterfaceOnly = parseInterfaceOnly; 1402 parseInterfaceOnly = false; 1403 CodeBody body = null; 1404 try { 1405 body = parseCodeBody(); 1406 } finally { 1407 parseInterfaceOnly = oldParseInterfaceOnly; 1408 } 1409 return body; 1410 } 1411 1412 public CodeBody parseCodeBody() { 1413 Token beginToken = peekToken(); 1414 1415 CodeBody ret; 1416 eatTopToken(LBRACE); 1426 Stmts stmts = parseStmts(RBRACE); 1427 ret = new CodeBody(dummySource,stmts,true); 1428 ret.setParsed(true); 1429 addContext(ret, beginToken); 1430 return ret; 1432 } 1433 1434 public ConstructorBody parseConstructorBody() { 1435 Token beginToken = peekToken(); 1436 if (maybeEatToken(SEMICOLON)) { 1437 showError(beginToken, "constructor must have a body"); 1438 return null; 1439 } 1440 1441 ConstructorBody ret; 1442 eatTopToken(LBRACE); 1452 1453 ConstructorCallExpr constructorCall = null; 1454 1455 Token firstToken = peekToken(); 1456 if (firstToken.image.equals("this") || firstToken.image.equals("super")) { 1457 boolean isSuper = firstToken.image.equals("super"); 1458 if (peekToken(1).kind == LPAREN) { 1459 eatTopToken(); 1460 constructorCall = new ConstructorCallExpr(dummySource, null, isSuper, parseParenExprs(), null); 1461 addContext(constructorCall, firstToken); 1462 } 1463 } 1464 1465 inConstructor = true; 1466 Stmts stmts = parseStmts(RBRACE); 1467 inConstructor = false; 1468 if (constructorCall == null && stmts.size() > 0) { 1469 Stmt stmt = stmts.get(0); 1470 if (stmt instanceof ExprStmt && ((ExprStmt)stmt).getExpr() instanceof ConstructorCallExpr) { 1471 constructorCall = (ConstructorCallExpr) ((ExprStmt)stmt).getExpr(); 1472 stmts.remove(0); 1473 } 1474 } 1475 ret = new ConstructorBody(dummySource,stmts, constructorCall, true); 1476 ret.setParsed(true); 1477 addContext(ret, beginToken); 1478 return ret; 1480 } 1481 1482 1483 1484 1485 public Decs parseDecs() { 1487 return parseDecs(null); 1488 } 1489 1490 public Decs parseDecs(Map extraDecParsers) { 1491 Token beginToken = peekToken(); 1492 eatTopToken(LBRACE); 1493 1494 Decs decs = new Decs(dummySource); 1495 while (peekToken().kind != RBRACE) { 1496 if (peekToken().kind == SEMICOLON) { 1497 eatTopToken(); continue; 1498 } 1499 Token decBeginToken = peekToken(); 1500 Stmt dec = parseStmt(extraDecParsers, true, true); 1501 addContext(dec, decBeginToken); 1502 if (dec instanceof Dec) { 1503 decs.add((Dec)dec); 1504 } else if (dec instanceof Decs) { 1505 decs.addAll((Decs)dec); 1506 } else { 1507 throwError(decBeginToken, "expected declaration"); 1508 return null; 1509 } 1510 } 1511 1512 eatTopToken(RBRACE); 1513 addContext(decs, beginToken); 1514 return decs; 1515 } 1516 1517 public TypeDs parseThrows() { 1518 if (maybeEatKeyword("throws")) { 1519 return parseTypeDs(); 1520 } else { 1521 return null; 1522 } 1523 } 1524 1525 public InitializerDec parseInitializerDec() { 1526 int legalModifiers = Modifiers.STATIC; 1527 Token beginToken = peekToken(); 1528 Modifiers modifiers = parseModifiers(legalModifiers); 1529 Formals formals = new Formals(dummySource); 1530 addContext(formals, beginToken); 1531 TypeDs _throws = new TypeDs(dummySource); 1532 addContext(_throws, beginToken); 1533 return new InitializerDec(dummySource, modifiers, formals, _throws, parseOptionalCodeBody()); 1534 } 1535 1536 public Dec parseConstructorDec() { 1537 int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE; 1538 1539 Token beginToken = peekToken(); 1540 1541 if (inInterface) { showError(beginToken, "constructor not allowed in interface"); } 1542 1543 Modifiers modifiers = parseModifiers(legalModifiers); 1544 parseIdMatchingEnclosingTypeName("constructor name"); 1545 Formals formals = parseFormals(); 1546 TypeDs _throws = parseThrows(); 1547 1548 return new ConstructorDec(dummySource,modifiers, formals, _throws, parseConstructorBody()); 1549 } 1550 1551 public Dec parseMethodDec() { 1552 int legalModifiers; 1553 if (inInterface) { 1554 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT; 1555 } else { 1556 legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE | 1557 Modifiers.ABSTRACT | Modifiers.STATIC | Modifiers.FINAL | 1558 Modifiers.SYNCHRONIZED | Modifiers.NATIVE | Modifiers.STRICT; 1559 } 1560 1561 Modifiers modifiers = parseModifiers(legalModifiers); 1562 if (inInterface) { 1563 modifiers.setAbstract(true); 1564 modifiers.setPublic(true); 1565 } 1566 1567 1568 TypeD typeD = parseTypeD(); 1569 String id = parseId(); 1570 1571 Formals formals = parseFormals(); 1572 1573 typeD = addBracketsToTypeD(typeD); 1575 1576 TypeDs _throws = parseThrows(); 1577 1578 return new MethodDec(dummySource,modifiers, typeD, id, formals, _throws, 1579 parseOptionalCodeBody()); 1580 } 1581 1582 public Stmt parseVarDec() { return parseVarDec(false); } 1583 public Stmt parseFieldDec() { return parseVarDec(true); } 1584 1585 1586 public Stmt parseVarDec(boolean isField) { 1588 int legalModifiers; 1589 1590 if (isField) { 1591 if (inInterface) { 1592 legalModifiers = Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.FINAL; 1593 } else { 1594 legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE | 1595 Modifiers.STATIC | Modifiers.FINAL | 1596 Modifiers.TRANSIENT | Modifiers.VOLATILE; 1597 } 1598 } else { 1599 legalModifiers = Modifiers.FINAL; 1600 } 1601 1602 Token beginToken = peekToken(); 1603 Modifiers modifiers = parseModifiers(legalModifiers); 1604 1605 if (inInterface) { 1606 modifiers.setPublic(true); 1607 modifiers.setStatic(true); 1608 } 1609 1610 TypeD baseTypeD = parseTypeD(); 1611 1612 Decs decs = null; 1613 VarDec dec = null; 1614 1615 while (true) { 1616 String id = parseId(); 1617 TypeD typeD = baseTypeD; 1618 1619 Expr initializer = null; 1620 typeD = addBracketsToTypeD(typeD); 1621 1625 Token endToken = popToken(); 1626 if (endToken.kind == ASSIGN) { 1627 if (typeD instanceof ArrayTypeD && peekToken().kind == LBRACE) { 1628 initializer = parseArrayInitializer(); 1629 } else { 1630 initializer = parseExpr(); 1631 } 1632 endToken = popToken(); 1633 } 1634 1635 if (isField) { 1636 dec = new FieldDec(dummySource,(Modifiers)modifiers.copy(), typeD, id, initializer); 1637 } else { 1638 dec = new VarDec(dummySource,(Modifiers)modifiers.copy(), typeD, id, initializer); 1639 } 1640 addContext(dec, beginToken); 1641 1642 if (endToken.kind == SEMICOLON) { 1643 if (decs != null) decs.add(dec); 1644 break; 1645 } else if (endToken.kind == COMMA) { 1646 if (decs == null) decs = new Decs(dummySource,dec); 1647 else decs.add(dec); 1648 1649 baseTypeD = (TypeD)baseTypeD.copy(); 1651 continue; 1652 } else { 1653 throwError(endToken, "expected ',' or ';'"); 1654 } 1655 } 1656 1657 if (decs != null) return decs; 1658 else return dec; 1659 } 1660 1661 public String parseAnyId() { 1662 Token token = popToken(); 1663 if (!isIdentifier(token)) { 1664 throwError(token, "identifier expected"); 1665 } 1666 return token.image; 1667 } 1668 1669 public String parseId() { 1670 Token token = popToken(); 1671 if (!isIdentifier(token) || isKeyword(token)) { 1672 throwError(token, "identifier expected"); 1673 } 1674 return token.image; 1675 } 1676 1677 public String parseIdOrKeywords_this_super_class() { 1678 Token token = popToken(); 1679 if (!isIdentifier(token) || isKeyword(token)) { 1680 if (!( token.image.equals("this") 1681 || token.image.equals("super") 1682 || token.image.equals("class") 1683 )) 1684 throwError(token, "identifier expected"); 1685 } 1686 return token.image; 1687 } 1688 1689 1690 public FormalDec parseParenFormal() { 1691 eatTopToken(LPAREN); 1692 FormalDec formal = parseFormal(); 1693 eatTopToken(RPAREN); 1694 1695 return formal; 1696 } 1697 1698 public Exprs parseExprs(int stopKind) { 1699 Token beginToken = peekToken(); 1700 Exprs exprs = new Exprs(dummySource); 1701 1702 if (beginToken.kind != stopKind) { 1703 while (true) { 1704 Expr expr = parseExpr(); 1705 exprs.add(expr); 1706 if (peekToken().kind != COMMA) break; 1707 eatTopToken(); 1708 } 1709 } 1710 addContext(exprs, beginToken); 1711 return exprs; 1712 } 1713 1714 1718 public Exprs parseParenExprs() { 1719 eatTopToken(LPAREN); 1720 Exprs exprs = parseExprs(RPAREN); 1721 eatTopToken(RPAREN); 1722 return exprs; 1723 } 1724 1725 1726 public ArrayInitializer parseArrayInitializer() { 1727 ArrayInitializer ret; 1728 eatTopToken(LBRACE); 1729 1730 Exprs exprs = new Exprs(dummySource); 1731 1732 if (maybeEatToken(RBRACE)) { 1733 return new ArrayInitializer(dummySource,exprs); 1734 } 1735 1736 while (true) { 1737 Expr expr; 1738 if (peekToken().kind == LBRACE) { 1739 expr = parseArrayInitializer(); 1740 } else if (maybeEatToken(COMMA)) { 1741 if (exprs.size() > 0 || !getCompiler().getOptions().lenient) { 1742 showError(peekToken(-1), "too many commas"); 1743 } 1744 break; 1745 } else { 1746 expr = parseExpr(); 1747 } 1748 exprs.add(expr); 1749 if (!maybeEatToken(COMMA)) break; 1750 if (peekToken().kind == RBRACE) break; 1751 } 1752 eatTopToken(RBRACE); 1753 return new ArrayInitializer(dummySource,exprs); 1754 } 1755 1756 public Exprs parseArrayDimExprs() { 1757 Exprs exprs = new Exprs(dummySource); 1759 while (peekToken().kind == LBRACKET) { 1760 eatTopToken(); 1761 if (peekToken().kind == RBRACKET) { 1762 exprs.add(new EmptyExpr(dummySource)); 1763 } else { 1764 exprs.add(parseExpr()); 1765 } 1766 eatTopToken(RBRACKET); 1767 } 1768 return exprs; 1769 } 1770 1771 public Expr parseParenExpr() { 1772 eatTopToken(LPAREN); 1773 Expr expr = parseExpr(); 1774 eatTopToken(RPAREN); 1775 1776 return expr; 1777 } 1778 1779 public Expr parseExpr() { 1780 return parseExpr(false); 1781 } 1782 1783 public Expr parseExpr(boolean allowNulls) { 1784 Expr ret = exprParser.parse(); 1785 if (!allowNulls && ret == null) { 1786 throwError(null, "expression required"); 1787 } 1788 return ret; 1789 } 1790 1791 protected String grabFormalComment(Token token) { 1792 while ((token = token.specialToken) != null) { 1793 if (token.kind == FORMAL_COMMENT) { 1794 return token.image; 1795 } 1796 } 1797 return null; 1798 } 1799 1800 protected void addComments(ASTObject ast, Token beginToken) { 1801 1803 if (ast instanceof Dec) { 1805 String comment = grabFormalComment(beginToken); 1806 if (comment != null) ast.setFormalComment(comment); 1807 } 1808 } 1809 1810 protected SourceLocation makeSourceLocation(Token beginToken) { 1811 Token endToken = peekToken(-1); 1812 if (endToken == null) endToken = beginToken; 1813 SourceLocation ret = new TextSourceLocation(currentCompilationUnit, 1814 beginToken.startPosition, 1815 endToken.endPosition); 1816 return ret; 1817 } 1818 1819 protected SourceLocation makeSourceLocation(SourceLocation beginSourceLoc) { 1820 Token endToken = peekToken(-1); 1821 int startPosition = -1; 1822 if (beginSourceLoc != null) startPosition = beginSourceLoc.getStartPosition(); 1823 SourceLocation ret = new TextSourceLocation(currentCompilationUnit, 1824 startPosition, 1825 endToken.endPosition); 1826 return ret; 1827 } 1828 1829 protected void addContext(ASTObject ast, ASTObject beginAST) { 1830 if (ast == null) return; 1831 ast.setSourceLocation(makeSourceLocation(beginAST.getSourceLocation())); 1832 } 1833 1834 protected void addContext(ASTObject ast, Token beginToken) { 1835 if (ast == null) return; 1836 ast.setSourceLocation(makeSourceLocation(beginToken)); 1837 addComments(ast, beginToken); 1838 } 1839 1840 public Stmt parseStmt() { 1841 Token beginToken = peekToken(); 1842 Stmt ret = parseStmt(null, false, false); 1843 addContext(ret, beginToken); 1844 return ret; 1845 } 1846 1847 public boolean lookaheadFormals() { 1848 if (peekToken().kind != LPAREN) return false; 1849 if (peekToken(1).kind == RPAREN) return true; 1850 1851 int start = currentIndex; 1852 eatTopToken(); 1853 1854 if (eatModifiers() && eatTypeD() && isIdentifier(peekToken())) { 1855 currentIndex = start; 1856 return true; 1857 } 1858 currentIndex = start; 1859 return false; 1860 } 1861 1862 1863 private Stmt parseStmt(Map extraDecParsers, 1864 boolean allowConstructors, boolean onlyDec) { 1865 Token topToken = peekToken(); 1866 1867 if (!onlyDec && isIdentifier(topToken)) { 1869 String keyword = topToken.image; 1870 StmtParser stmtParser = (StmtParser)stmtParsers.get(keyword); 1871 if (stmtParser != null) { 1872 eatTopToken(); 1873 return stmtParser.parse(); 1874 } else if (peekToken(1).kind == COLON) { 1875 if (isKeyword(popToken())) { showError(peekToken(-1), "keyword not allowed as label"); 1877 } 1878 eatTopToken(); Stmt stmt = parseStmt(extraDecParsers, allowConstructors, onlyDec); 1880 return new LabeledStmt(dummySource,keyword, stmt); 1881 } 1882 } 1883 1884 1891 pushCurrentIndex(); 1892 eatModifiers(); 1893 topToken = peekToken(); 1894 1895 if (isIdentifier(topToken)) { 1897 String keyword = topToken.image; 1898 1899 DecParser decParser; 1900 if (allowConstructors) { 1901 decParser = (DecParser)decParsers.get(keyword); 1902 } else { 1903 decParser = (DecParser)stmtDecParsers.get(keyword); 1904 } 1905 1906 if (extraDecParsers != null && decParser == null) { 1907 decParser = (DecParser)extraDecParsers.get(keyword); 1908 } 1909 if (decParser != null) { 1910 popCurrentIndex(); 1911 return decParser.parse(onlyDec); 1912 } 1913 } 1914 1915 if (allowConstructors) { 1916 if (isIdentifierOrNew(topToken)) { 1918 eatTopToken(); 1919 if (lookaheadFormals()) { 1920 popCurrentIndex(); 1921 return parseConstructorDec(); 1922 } else { 1923 currentIndex -= 1; 1924 } 1925 } 1926 if (topToken.kind == LBRACE) { 1927 popCurrentIndex(); 1928 return parseInitializerDec(); 1929 } 1932 } 1933 1934 if (eatTypeD() && eatIdentifier(onlyDec)) { 1935 if (peekToken().kind == LPAREN) { 1936 popCurrentIndex(); 1937 return parseMethodDec(); 1938 } else { 1939 popCurrentIndex(); 1940 if (onlyDec) { 1941 return parseFieldDec(); 1942 } else { 1943 return parseVarDec(); 1944 } 1945 } 1946 } 1947 1948 popCurrentIndex(); 1950 if (onlyDec) { 1951 return noDecFound(); 1952 } 1953 1954 if (topToken.kind == SEMICOLON) { 1956 eatTopToken(); 1957 return new EmptyStmt(dummySource); 1958 } 1959 1960 if (topToken.kind == LBRACE) { 1961 return parseBlockStmt(); 1962 } 1963 1964 Expr expr = parseExpr(); 1965 eatTopToken(SEMICOLON); 1966 return new ExprStmt(dummySource,expr); 1967 } 1968 1969 protected Dec noDecFound() { 1970 throwError(peekToken(), "declaration or '}' expected"); 1971 return null; 1972 } 1973 1974 1975 private Stmt parseTopDec(Map extraDecParsers) { 1976 Token topToken = peekToken(); 1977 1978 pushCurrentIndex(); 1979 eatModifiers(); 1980 topToken = peekToken(); 1981 1982 if (isIdentifier(topToken)) { 1984 String keyword = topToken.image; 1985 DecParser decParser = (DecParser)decParsers.get(keyword); 1986 if (extraDecParsers != null && decParser == null) { 1987 decParser = (DecParser)extraDecParsers.get(keyword); 1988 } 1989 if (decParser != null) { 1990 popCurrentIndex(); 1991 return decParser.parse(true); 1992 } 1993 } 1994 1995 popCurrentIndex(); 1997 throwError(topToken, "type declaration expected"); 1998 return null; 1999 } 2000 2001 2002 2003 public void throwError(Token t, String message) { 2004 if (t == null) t = peekToken(); 2005 throw new ParseException(t, tokenSource.sourceInfo, message); 2008 } 2009 2010 2011 public void warnVersion(String version, Token t, String message) { 2012 getCompiler().warnVersion(version, tokenToASTObject(t), message); 2013 } 2014 2015 public void showError(Token t, String message) { 2016 getCompiler().showError(tokenToASTObject(t), message); 2017 } 2018 2019 static class FakeASTObject extends ASTObject { 2021 public FakeASTObject(SourceLocation loc) { 2022 super(loc); 2023 } 2028 public ASTObject copy() { return null; } 2029 public int getChildCount() { return 0; } 2030 } 2031 2032 public ASTObject tokenToASTObject(Token t) { 2033 ASTObject fake = new FakeASTObject(makeSourceLocation(t)); return fake; 2035 } 2036 2037 2038 public static abstract class DecParser { 2040 public Dec parse(boolean isNotMethodLocal) { 2041 return parse(); 2044 } 2045 abstract public Dec parse(); 2046 } 2047 2048 class InterfaceDecParser extends DecParser { 2049 public Dec parse() { 2050 throw new RuntimeException (); 2052 } 2053 public Dec parse(boolean isNotMethodLocal) { 2054 int legalModifiers; 2055 if (!isNotMethodLocal) { 2056 legalModifiers = Modifiers.ABSTRACT | Modifiers.STRICT; 2057 } else if (peekEnclosingTypeDec() == null) { 2058 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.STRICT; 2059 } else if (inInterface) { 2060 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | 2061 Modifiers.STRICT | Modifiers.STATIC; 2062 } else { 2063 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.STRICT | 2064 Modifiers.PRIVATE | Modifiers.PROTECTED | Modifiers.STATIC; 2065 } 2066 2067 Modifiers modifiers = parseModifiers(legalModifiers); 2068 if (inInterface) { 2069 modifiers.setPublic(true); 2070 } 2071 eatKeyword("interface"); 2072 String id = parseId(); 2073 2074 TypeDs _extends = null; 2075 if (maybeEatKeyword("extends")) { 2076 _extends = parseTypeDs(); 2077 } 2078 2079 TypeDec ret = new InterfaceDec(dummySource, modifiers, id, _extends, null); 2080 ret.setEnclosingTypeDec(peekEnclosingTypeDec()); 2081 2082 pushEnclosingTypeDec(ret); 2083 Decs body = null; 2084 boolean oldInInterface = inInterface; 2085 try { 2086 inInterface = true; 2087 body = parseDecs(); 2088 } finally { 2089 inInterface = oldInInterface; 2090 } 2091 popEnclosingTypeDec(); 2092 ret.setBody(body); 2093 2094 if (peekEnclosingTypeDec() == null) currentCompilationUnit.addDefinedType(ret); 2095 return ret; 2096 } 2097 } 2098 2099 class ClassDecParser extends DecParser { 2100 public Dec parse() { 2101 throw new RuntimeException (); 2103 } 2104 public Dec parse(boolean isNotMethodLocal) { 2105 int legalModifiers; 2106 if (!isNotMethodLocal) { 2107 legalModifiers = Modifiers.ABSTRACT | Modifiers.FINAL | Modifiers.STRICT; 2108 } else if (peekEnclosingTypeDec() == null) { 2109 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL | 2110 Modifiers.STRICT; 2111 } else if (inInterface) { 2112 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL | 2113 Modifiers.STRICT | Modifiers.STATIC; 2114 } else { 2115 legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL | 2116 Modifiers.STRICT | 2117 Modifiers.PRIVATE | Modifiers.PROTECTED | Modifiers.STATIC; 2118 } 2119 2120 Modifiers modifiers = parseModifiers(legalModifiers); 2121 if (inInterface) { 2122 modifiers.setPublic(true); 2123 } 2124 2125 eatKeyword("class"); 2126 String id = parseId(); 2127 2128 TypeD superClass = null; 2129 if (maybeEatKeyword("extends")) { 2130 superClass = parseTypeD(); 2131 } 2132 TypeDs _implements = null; 2133 if (maybeEatKeyword("implements")) { 2134 _implements = parseTypeDs(); 2135 } 2136 2137 TypeDec ret = 2138 new ClassDec(dummySource, modifiers, id, superClass, _implements, null); 2139 if(!isNotMethodLocal) ret.setLocal(); 2140 ret.setEnclosingTypeDec(peekEnclosingTypeDec()); 2141 2142 pushEnclosingTypeDec(ret); 2143 2144 Decs body = null; 2145 boolean oldInInterface = inInterface; 2146 try { 2147 inInterface = false; 2148 body = parseDecs(); 2149 } finally { 2150 inInterface = oldInInterface; 2151 } 2152 popEnclosingTypeDec(); 2153 2154 ret.setBody(body); 2155 if (peekEnclosingTypeDec() == null) currentCompilationUnit.addDefinedType(ret); 2156 return ret; 2157 } 2158 } 2159 2160 2161 public static abstract class StmtParser { 2163 abstract public Stmt parse(); 2164 } 2165 2166 class BreakStmtParser extends StmtParser { 2167 public Stmt parse() { 2168 String label = null; 2169 if (peekToken().kind != SEMICOLON) { 2170 label = parseId(); 2171 } 2172 eatTopToken(SEMICOLON); 2173 return new BreakStmt(dummySource,label); 2174 } 2175 } 2176 2177 class ContinueStmtParser extends StmtParser { 2178 public Stmt parse() { 2179 String label = null; 2180 if (peekToken().kind != SEMICOLON) { 2181 label = parseId(); 2182 } 2183 eatTopToken(SEMICOLON); 2184 return new ContinueStmt(dummySource,label); 2185 } 2186 } 2187 2188 class DoStmtParser extends StmtParser { 2189 public Stmt parse() { 2190 Stmt body = parseStmt(); 2191 2192 eatKeyword("while"); 2193 Expr test = parseParenExpr(); 2194 eatTopToken(SEMICOLON); 2195 2196 return new DoStmt(dummySource, body, test); 2197 } 2198 } 2199 2200 class AssertStmtParser extends StmtParser { 2201 public Stmt parse() { 2202 Expr test = parseExpr(); 2203 Expr message = null; 2204 if (maybeEatToken(COLON)) { 2205 message = parseExpr(); 2206 } 2207 eatTopToken(SEMICOLON); 2208 2209 return new AssertStmt(dummySource, test, message); 2210 } 2211 } 2212 2213 class ForStmtParser extends StmtParser { 2214 public Stmt parse() { 2215 eatTopToken(LPAREN); 2216 ASTObject init; 2217 Expr test; 2218 Exprs update; 2219 2220 if (lookaheadVarDes()) { 2222 init = parseVarDec(); 2223 } else { 2224 init = parseExprs(SEMICOLON); 2225 eatTopToken(SEMICOLON); 2226 } 2227 2228 test = parseExpr(true); 2229 eatTopToken(SEMICOLON); 2230 update = parseExprs(RPAREN); 2231 eatTopToken(RPAREN); 2232 Stmt body = parseStmt(); 2233 2234 ForStmt forStmt = new ForStmt(dummySource,init, test, update, body); 2235 if (test == null) { 2236 forStmt.setTest((Expr) 2237 new BooleanLiteralExpr(dummySource, true) 2238 .setSyntheticSource(forStmt)); 2239 } 2240 return forStmt; 2241 } 2242 } 2243 2244 class IfStmtParser extends StmtParser { 2245 public Stmt parse() { 2246 Expr test = parseParenExpr(); 2247 Stmt _then = parseStmt(); 2248 Stmt _else = null; 2249 if (maybeEatKeyword("else")) { 2250 _else = parseStmt(); 2251 } 2252 IfStmt ifStmt = new IfStmt(dummySource,test, _then, _else); 2253 if (_else == null) { 2254 ifStmt.setElse((Stmt) 2255 new EmptyStmt(dummySource).setSyntheticSource(ifStmt)); 2256 } 2257 return ifStmt; 2258 } 2259 } 2260 2261 class ReturnStmtParser extends StmtParser { 2262 public Stmt parse() { 2263 Expr expr = null; 2264 if (peekToken().kind != SEMICOLON) { 2265 expr = parseExpr(); 2266 } 2267 eatTopToken(SEMICOLON); 2268 return new ReturnStmt(dummySource,expr); 2269 } 2270 } 2271 2272 class SwitchStmtParser extends StmtParser { 2273 public Stmt parse() { 2274 Expr expr = parseParenExpr(); 2275 2276 eatTopToken(LBRACE); 2277 SwitchClauses clauses = new SwitchClauses(dummySource); 2278 Expr label = null; 2279 Stmts stmts = null; 2280 SwitchClause switchClause=null; 2281 2282 while (true) { 2283 if (maybeEatKeyword("case")) { 2284 label = parseExpr(); 2285 eatTopToken(COLON); 2286 if (switchClause != null) clauses.add(switchClause); 2287 stmts = new Stmts(dummySource); 2288 switchClause = new SwitchClause(dummySource,label, stmts); 2289 } else if (maybeEatKeyword("default")) { 2290 eatTopToken(COLON); 2291 if (switchClause != null) clauses.add(switchClause); 2292 stmts = new Stmts(dummySource); 2293 switchClause = new SwitchClause(dummySource,null, stmts); 2294 } else if (peekToken().kind == RBRACE) { 2295 if (switchClause != null) clauses.add(switchClause); 2296 eatTopToken(); 2297 break; 2298 } else { 2299 if (stmts == null) { 2300 throwError(peekToken(), "'case', 'default' or '}' expected"); 2301 break; 2302 } 2303 stmts.add(parseStmt()); 2304 } 2305 } 2306 2307 return new SwitchStmt(dummySource,expr, clauses); 2308 } 2309 } 2310 2311 class SynchronizedStmtParser extends StmtParser { 2312 public Stmt parse() { 2313 Expr expr = parseParenExpr(); 2314 Stmt body = parseStmt(); 2315 2316 return new SynchronizedStmt(dummySource,expr, body); 2317 } 2318 } 2319 2320 class ThrowStmtParser extends StmtParser { 2321 public Stmt parse() { 2322 Expr expr = parseExpr(); 2323 eatTopToken(SEMICOLON); 2324 return new ThrowStmt(dummySource,expr); 2325 } 2326 } 2327 2328 class GotoStmtParser extends StmtParser { 2329 public Stmt parse() { 2330 showError(peekToken(),"'goto' is java reserved keyword"); 2331 return null; 2332 } 2333 } 2334 2335 class TryStmtParser extends StmtParser { 2336 public Stmt parse() { 2337 Stmt body = parseStmt(); 2338 2339 CatchClauses catches = new CatchClauses(dummySource); 2340 Token beginToken = peekToken(); 2341 while (maybeEatKeyword("catch")) { 2342 FormalDec formal = parseParenFormal(); 2343 Stmt catchBody = parseStmt(); 2344 CatchClause clause = new CatchClause(dummySource,formal, catchBody); 2345 addContext(clause, beginToken); 2346 catches.add(clause); 2347 beginToken = peekToken(); 2348 } 2349 2350 Stmt _finally = null; 2351 if (maybeEatKeyword("finally")) { 2352 _finally = parseStmt(); 2353 } 2354 2355 if (catches.size() == 0) { 2356 return new TryFinallyStmt(dummySource, body, _finally); 2357 } else if (_finally == null) { 2358 return new TryCatchStmt(dummySource, body, catches); 2359 } else { 2360 TryFinallyStmt s = new TryFinallyStmt(dummySource, null, _finally); 2361 TryCatchStmt b = new TryCatchStmt(dummySource, body, catches); 2362 b.setSyntheticSource(s); 2363 s.setBody(b); 2364 return s; 2365 } 2366 } 2367 } 2368 2369 class WhileStmtParser extends StmtParser { 2370 public Stmt parse() { 2371 Expr test = parseParenExpr(); 2372 Stmt body = parseStmt(); 2373 return new WhileStmt(dummySource,test, body); 2374 } 2375 } 2376 2377} 2378 2379 2380 2406 | Popular Tags |