1 /*
   2  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.parser;
  27 
  28 import java.util.*;
  29 
  30 import com.sun.tools.javac.tree.*;
  31 import com.sun.tools.javac.code.*;
  32 import com.sun.tools.javac.util.*;
  33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  34 import com.sun.tools.javac.util.List;
  35 import static com.sun.tools.javac.util.ListBuffer.lb;
  36 
  37 import com.sun.tools.javac.tree.JCTree.*;
  38 
  39 import static com.sun.tools.javac.parser.Token.*;
  40 
  41 /** The parser maps a token sequence into an abstract syntax
  42  *  tree. It operates by recursive descent, with code derived
  43  *  systematically from an LL(1) grammar. For efficiency reasons, an
  44  *  operator precedence scheme is used for parsing binary operation
  45  *  expressions.
  46  *
  47  *  <p><b>This is NOT part of any supported API.
  48  *  If you write code that depends on this, you do so at your own risk.
  49  *  This code and its internal interfaces are subject to change or
  50  *  deletion without notice.</b>
  51  */
  52 public class JavacParser implements Parser {
  53 
  54     /** The number of precedence levels of infix operators.
  55      */
  56     private static final int infixPrecedenceLevels = 10;
  57 
  58     /** The scanner used for lexical analysis.
  59      */
  60     private Lexer S;
  61 
  62     /** The factory to be used for abstract syntax tree construction.
  63      */
  64     protected TreeMaker F;
  65 
  66     /** The log to be used for error diagnostics.
  67      */
  68     private Log log;
  69 
  70     /** The keyword table. */
  71     private Keywords keywords;
  72 
  73     /** The Source language setting. */
  74     private Source source;
  75 
  76     /** The name table. */
  77     private Names names;
  78 
  79     /** Construct a parser from a given scanner, tree factory and log.
  80      */
  81     protected JavacParser(ParserFactory fac,
  82                      Lexer S,
  83                      boolean keepDocComments,
  84                      boolean keepLineMap) {
  85         this.S = S;
  86         S.nextToken(); // prime the pump
  87         this.F = fac.F;
  88         this.log = fac.log;
  89         this.names = fac.names;
  90         this.keywords = fac.keywords;
  91         this.source = fac.source;
  92         this.allowGenerics = source.allowGenerics();
  93         this.allowVarargs = source.allowVarargs();
  94         this.allowAsserts = source.allowAsserts();
  95         this.allowEnums = source.allowEnums();
  96         this.allowForeach = source.allowForeach();
  97         this.allowStaticImport = source.allowStaticImport();
  98         this.allowAnnotations = source.allowAnnotations();
  99         this.allowTWR = source.allowTryWithResources();
 100         this.allowDiamond = source.allowDiamond();
 101         this.allowMulticatch = source.allowMulticatch();
 102         this.keepDocComments = keepDocComments;
 103         if (keepDocComments)
 104             docComments = new HashMap<JCTree,String>();
 105         this.keepLineMap = keepLineMap;
 106         this.errorTree = F.Erroneous();
 107     }
 108 
 109     /** Switch: Should generics be recognized?
 110      */
 111     boolean allowGenerics;
 112 
 113     /** Switch: Should diamond operator be recognized?
 114      */
 115     boolean allowDiamond;
 116 
 117     /** Switch: Should multicatch clause be accepted?
 118      */
 119     boolean allowMulticatch;
 120 
 121     /** Switch: Should varargs be recognized?
 122      */
 123     boolean allowVarargs;
 124 
 125     /** Switch: should we recognize assert statements, or just give a warning?
 126      */
 127     boolean allowAsserts;
 128 
 129     /** Switch: should we recognize enums, or just give a warning?
 130      */
 131     boolean allowEnums;
 132 
 133     /** Switch: should we recognize foreach?
 134      */
 135     boolean allowForeach;
 136 
 137     /** Switch: should we recognize foreach?
 138      */
 139     boolean allowStaticImport;
 140 
 141     /** Switch: should we recognize annotations?
 142      */
 143     boolean allowAnnotations;
 144 
 145     /** Switch: should we recognize automatic resource management?
 146      */
 147     boolean allowTWR;
 148 
 149     /** Switch: should we keep docComments?
 150      */
 151     boolean keepDocComments;
 152 
 153     /** Switch: should we keep line table?
 154      */
 155     boolean keepLineMap;
 156 
 157     /** When terms are parsed, the mode determines which is expected:
 158      *     mode = EXPR        : an expression
 159      *     mode = TYPE        : a type
 160      *     mode = NOPARAMS    : no parameters allowed for type
 161      *     mode = TYPEARG     : type argument
 162      */
 163     static final int EXPR = 0x1;
 164     static final int TYPE = 0x2;
 165     static final int NOPARAMS = 0x4;
 166     static final int TYPEARG = 0x8;
 167     static final int DIAMOND = 0x10;
 168 
 169     /** The current mode.
 170      */
 171     private int mode = 0;
 172 
 173     /** The mode of the term that was parsed last.
 174      */
 175     private int lastmode = 0;
 176 
 177 /* ---------- error recovery -------------- */
 178 
 179     private JCErroneous errorTree;
 180 
 181     /** Skip forward until a suitable stop token is found.
 182      */
 183     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
 184          while (true) {
 185              switch (S.token()) {
 186                 case SEMI:
 187                     S.nextToken();
 188                     return;
 189                 case PUBLIC:
 190                 case FINAL:
 191                 case ABSTRACT:
 192                 case MONKEYS_AT:
 193                 case EOF:
 194                 case CLASS:
 195                 case INTERFACE:
 196                 case ENUM:
 197                     return;
 198                 case IMPORT:
 199                     if (stopAtImport)
 200                         return;
 201                     break;
 202                 case LBRACE:
 203                 case RBRACE:
 204                 case PRIVATE:
 205                 case PROTECTED:
 206                 case STATIC:
 207                 case TRANSIENT:
 208                 case NATIVE:
 209                 case VOLATILE:
 210                 case SYNCHRONIZED:
 211                 case STRICTFP:
 212                 case LT:
 213                 case BYTE:
 214                 case SHORT:
 215                 case CHAR:
 216                 case INT:
 217                 case LONG:
 218                 case FLOAT:
 219                 case DOUBLE:
 220                 case BOOLEAN:
 221                 case VOID:
 222                     if (stopAtMemberDecl)
 223                         return;
 224                     break;
 225                 case IDENTIFIER:
 226                    if (stopAtIdentifier)
 227                         return;
 228                     break;
 229                 case CASE:
 230                 case DEFAULT:
 231                 case IF:
 232                 case FOR:
 233                 case WHILE:
 234                 case DO:
 235                 case TRY:
 236                 case SWITCH:
 237                 case RETURN:
 238                 case THROW:
 239                 case BREAK:
 240                 case CONTINUE:
 241                 case ELSE:
 242                 case FINALLY:
 243                 case CATCH:
 244                     if (stopAtStatement)
 245                         return;
 246                     break;
 247             }
 248             S.nextToken();
 249         }
 250     }
 251 
 252     private JCErroneous syntaxError(int pos, String key, Token... args) {
 253         return syntaxError(pos, null, key, args);
 254     }
 255 
 256     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
 257         setErrorEndPos(pos);
 258         reportSyntaxError(pos, key, (Object[])args);
 259         return toP(F.at(pos).Erroneous(errs));
 260     }
 261 
 262     private int errorPos = Position.NOPOS;
 263     /**
 264      * Report a syntax error at given position using the given
 265      * argument unless one was already reported at the same position.
 266      */
 267     private void reportSyntaxError(int pos, String key, Object... args) {
 268         if (pos > S.errPos() || pos == Position.NOPOS) {
 269             if (S.token() == EOF)
 270                 error(pos, "premature.eof");
 271             else
 272                 error(pos, key, args);
 273         }
 274         S.errPos(pos);
 275         if (S.pos() == errorPos)
 276             S.nextToken(); // guarantee progress
 277         errorPos = S.pos();
 278     }
 279 
 280 
 281     /** Generate a syntax error at current position unless one was already
 282      *  reported at the same position.
 283      */
 284     private JCErroneous syntaxError(String key) {
 285         return syntaxError(S.pos(), key);
 286     }
 287 
 288     /** Generate a syntax error at current position unless one was
 289      *  already reported at the same position.
 290      */
 291     private JCErroneous syntaxError(String key, Token arg) {
 292         return syntaxError(S.pos(), key, arg);
 293     }
 294 
 295     /** If next input token matches given token, skip it, otherwise report
 296      *  an error.
 297      */
 298     public void accept(Token token) {
 299         if (S.token() == token) {
 300             S.nextToken();
 301         } else {
 302             setErrorEndPos(S.pos());
 303             reportSyntaxError(S.prevEndPos(), "expected", token);
 304         }
 305     }
 306 
 307     /** Report an illegal start of expression/type error at given position.
 308      */
 309     JCExpression illegal(int pos) {
 310         setErrorEndPos(S.pos());
 311         if ((mode & EXPR) != 0)
 312             return syntaxError(pos, "illegal.start.of.expr");
 313         else
 314             return syntaxError(pos, "illegal.start.of.type");
 315 
 316     }
 317 
 318     /** Report an illegal start of expression/type error at current position.
 319      */
 320     JCExpression illegal() {
 321         return illegal(S.pos());
 322     }
 323 
 324     /** Diagnose a modifier flag from the set, if any. */
 325     void checkNoMods(long mods) {
 326         if (mods != 0) {
 327             long lowestMod = mods & -mods;
 328             error(S.pos(), "mod.not.allowed.here",
 329                       Flags.asFlagSet(lowestMod));
 330         }
 331     }
 332 
 333 /* ---------- doc comments --------- */
 334 
 335     /** A hashtable to store all documentation comments
 336      *  indexed by the tree nodes they refer to.
 337      *  defined only if option flag keepDocComment is set.
 338      */
 339     Map<JCTree, String> docComments;
 340 
 341     /** Make an entry into docComments hashtable,
 342      *  provided flag keepDocComments is set and given doc comment is non-null.
 343      *  @param tree   The tree to be used as index in the hashtable
 344      *  @param dc     The doc comment to associate with the tree, or null.
 345      */
 346     void attach(JCTree tree, String dc) {
 347         if (keepDocComments && dc != null) {
 348 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
 349             docComments.put(tree, dc);
 350         }
 351     }
 352 
 353 /* -------- source positions ------- */
 354 
 355     private int errorEndPos = -1;
 356 
 357     private void setErrorEndPos(int errPos) {
 358         if (errPos > errorEndPos)
 359             errorEndPos = errPos;
 360     }
 361 
 362     protected int getErrorEndPos() {
 363         return errorEndPos;
 364     }
 365 
 366     /**
 367      * Store ending position for a tree.
 368      * @param tree   The tree.
 369      * @param endpos The ending position to associate with the tree.
 370      */
 371     protected void storeEnd(JCTree tree, int endpos) {}
 372 
 373     /**
 374      * Store ending position for a tree.  The ending position should
 375      * be the ending position of the current token.
 376      * @param t The tree.
 377      */
 378     protected <T extends JCTree> T to(T t) { return t; }
 379 
 380     /**
 381      * Store ending position for a tree.  The ending position should
 382      * be greater of the ending position of the previous token and errorEndPos.
 383      * @param t The tree.
 384      */
 385     protected <T extends JCTree> T toP(T t) { return t; }
 386 
 387     /** Get the start position for a tree node.  The start position is
 388      * defined to be the position of the first character of the first
 389      * token of the node's source text.
 390      * @param tree  The tree node
 391      */
 392     public int getStartPos(JCTree tree) {
 393         return TreeInfo.getStartPos(tree);
 394     }
 395 
 396     /**
 397      * Get the end position for a tree node.  The end position is
 398      * defined to be the position of the last character of the last
 399      * token of the node's source text.  Returns Position.NOPOS if end
 400      * positions are not generated or the position is otherwise not
 401      * found.
 402      * @param tree  The tree node
 403      */
 404     public int getEndPos(JCTree tree) {
 405         return Position.NOPOS;
 406     }
 407 
 408 
 409 
 410 /* ---------- parsing -------------- */
 411 
 412     /**
 413      * Ident = IDENTIFIER
 414      */
 415     Name ident() {
 416         if (S.token() == IDENTIFIER) {
 417             Name name = S.name();
 418             S.nextToken();
 419             return name;
 420         } else if (S.token() == ASSERT) {
 421             if (allowAsserts) {
 422                 error(S.pos(), "assert.as.identifier");
 423                 S.nextToken();
 424                 return names.error;
 425             } else {
 426                 warning(S.pos(), "assert.as.identifier");
 427                 Name name = S.name();
 428                 S.nextToken();
 429                 return name;
 430             }
 431         } else if (S.token() == ENUM) {
 432             if (allowEnums) {
 433                 error(S.pos(), "enum.as.identifier");
 434                 S.nextToken();
 435                 return names.error;
 436             } else {
 437                 warning(S.pos(), "enum.as.identifier");
 438                 Name name = S.name();
 439                 S.nextToken();
 440                 return name;
 441             }
 442         } else {
 443             accept(IDENTIFIER);
 444             return names.error;
 445         }
 446 }
 447 
 448     /**
 449      * Qualident = Ident { DOT Ident }
 450      */
 451     public JCExpression qualident() {
 452         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
 453         while (S.token() == DOT) {
 454             int pos = S.pos();
 455             S.nextToken();
 456             t = toP(F.at(pos).Select(t, ident()));
 457         }
 458         return t;
 459     }
 460 
 461     /**
 462      * Literal =
 463      *     INTLITERAL
 464      *   | LONGLITERAL
 465      *   | FLOATLITERAL
 466      *   | DOUBLELITERAL
 467      *   | CHARLITERAL
 468      *   | STRINGLITERAL
 469      *   | TRUE
 470      *   | FALSE
 471      *   | NULL
 472      */
 473     JCExpression literal(Name prefix) {
 474         int pos = S.pos();
 475         JCExpression t = errorTree;
 476         switch (S.token()) {
 477         case INTLITERAL:
 478             try {
 479                 t = F.at(pos).Literal(
 480                     TypeTags.INT,
 481                     Convert.string2int(strval(prefix), S.radix()));
 482             } catch (NumberFormatException ex) {
 483                 error(S.pos(), "int.number.too.large", strval(prefix));
 484             }
 485             break;
 486         case LONGLITERAL:
 487             try {
 488                 t = F.at(pos).Literal(
 489                     TypeTags.LONG,
 490                     new Long(Convert.string2long(strval(prefix), S.radix())));
 491             } catch (NumberFormatException ex) {
 492                 error(S.pos(), "int.number.too.large", strval(prefix));
 493             }
 494             break;
 495         case FLOATLITERAL: {
 496             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
 497             Float n;
 498             try {
 499                 n = Float.valueOf(proper);
 500             } catch (NumberFormatException ex) {
 501                 // error already reported in scanner
 502                 n = Float.NaN;
 503             }
 504             if (n.floatValue() == 0.0f && !isZero(proper))
 505                 error(S.pos(), "fp.number.too.small");
 506             else if (n.floatValue() == Float.POSITIVE_INFINITY)
 507                 error(S.pos(), "fp.number.too.large");
 508             else
 509                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
 510             break;
 511         }
 512         case DOUBLELITERAL: {
 513             String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
 514             Double n;
 515             try {
 516                 n = Double.valueOf(proper);
 517             } catch (NumberFormatException ex) {
 518                 // error already reported in scanner
 519                 n = Double.NaN;
 520             }
 521             if (n.doubleValue() == 0.0d && !isZero(proper))
 522                 error(S.pos(), "fp.number.too.small");
 523             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
 524                 error(S.pos(), "fp.number.too.large");
 525             else
 526                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
 527             break;
 528         }
 529         case CHARLITERAL:
 530             t = F.at(pos).Literal(
 531                 TypeTags.CHAR,
 532                 S.stringVal().charAt(0) + 0);
 533             break;
 534         case STRINGLITERAL:
 535             t = F.at(pos).Literal(
 536                 TypeTags.CLASS,
 537                 S.stringVal());
 538             break;
 539         case TRUE: case FALSE:
 540             t = F.at(pos).Literal(
 541                 TypeTags.BOOLEAN,
 542                 (S.token() == TRUE ? 1 : 0));
 543             break;
 544         case NULL:
 545             t = F.at(pos).Literal(
 546                 TypeTags.BOT,
 547                 null);
 548             break;
 549         default:
 550             Assert.error();
 551         }
 552         if (t == errorTree)
 553             t = F.at(pos).Erroneous();
 554         storeEnd(t, S.endPos());
 555         S.nextToken();
 556         return t;
 557     }
 558 //where
 559         boolean isZero(String s) {
 560             char[] cs = s.toCharArray();
 561             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
 562             int i = ((base==16) ? 2 : 0);
 563             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
 564             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
 565         }
 566 
 567         String strval(Name prefix) {
 568             String s = S.stringVal();
 569             return prefix.isEmpty() ? s : prefix + s;
 570         }
 571 
 572     /** terms can be either expressions or types.
 573      */
 574     public JCExpression parseExpression() {
 575         return term(EXPR);
 576     }
 577 
 578     public JCExpression parseType() {
 579         return term(TYPE);
 580     }
 581 
 582     JCExpression term(int newmode) {
 583         int prevmode = mode;
 584         mode = newmode;
 585         JCExpression t = term();
 586         lastmode = mode;
 587         mode = prevmode;
 588         return t;
 589     }
 590 
 591     /**
 592      *  Expression = Expression1 [ExpressionRest]
 593      *  ExpressionRest = [AssignmentOperator Expression1]
 594      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
 595      *                       "&=" | "|=" | "^=" |
 596      *                       "%=" | "<<=" | ">>=" | ">>>="
 597      *  Type = Type1
 598      *  TypeNoParams = TypeNoParams1
 599      *  StatementExpression = Expression
 600      *  ConstantExpression = Expression
 601      */
 602     JCExpression term() {
 603         JCExpression t = term1();
 604         if ((mode & EXPR) != 0 &&
 605             S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
 606             return termRest(t);
 607         else
 608             return t;
 609     }
 610 
 611     JCExpression termRest(JCExpression t) {
 612         switch (S.token()) {
 613         case EQ: {
 614             int pos = S.pos();
 615             S.nextToken();
 616             mode = EXPR;
 617             JCExpression t1 = term();
 618             return toP(F.at(pos).Assign(t, t1));
 619         }
 620         case PLUSEQ:
 621         case SUBEQ:
 622         case STAREQ:
 623         case SLASHEQ:
 624         case PERCENTEQ:
 625         case AMPEQ:
 626         case BAREQ:
 627         case CARETEQ:
 628         case LTLTEQ:
 629         case GTGTEQ:
 630         case GTGTGTEQ:
 631             int pos = S.pos();
 632             Token token = S.token();
 633             S.nextToken();
 634             mode = EXPR;
 635             JCExpression t1 = term();
 636             return F.at(pos).Assignop(optag(token), t, t1);
 637         default:
 638             return t;
 639         }
 640     }
 641 
 642     /** Expression1   = Expression2 [Expression1Rest]
 643      *  Type1         = Type2
 644      *  TypeNoParams1 = TypeNoParams2
 645      */
 646     JCExpression term1() {
 647         JCExpression t = term2();
 648         if ((mode & EXPR) != 0 && S.token() == QUES) {
 649             mode = EXPR;
 650             return term1Rest(t);
 651         } else {
 652             return t;
 653         }
 654     }
 655 
 656     /** Expression1Rest = ["?" Expression ":" Expression1]
 657      */
 658     JCExpression term1Rest(JCExpression t) {
 659         if (S.token() == QUES) {
 660             int pos = S.pos();
 661             S.nextToken();
 662             JCExpression t1 = term();
 663             accept(COLON);
 664             JCExpression t2 = term1();
 665             return F.at(pos).Conditional(t, t1, t2);
 666         } else {
 667             return t;
 668         }
 669     }
 670 
 671     /** Expression2   = Expression3 [Expression2Rest]
 672      *  Type2         = Type3
 673      *  TypeNoParams2 = TypeNoParams3
 674      */
 675     JCExpression term2() {
 676         JCExpression t = term3();
 677         if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
 678             mode = EXPR;
 679             return term2Rest(t, TreeInfo.orPrec);
 680         } else {
 681             return t;
 682         }
 683     }
 684 
 685     /*  Expression2Rest = {infixop Expression3}
 686      *                  | Expression3 instanceof Type
 687      *  infixop         = "||"
 688      *                  | "&&"
 689      *                  | "|"
 690      *                  | "^"
 691      *                  | "&"
 692      *                  | "==" | "!="
 693      *                  | "<" | ">" | "<=" | ">="
 694      *                  | "<<" | ">>" | ">>>"
 695      *                  | "+" | "-"
 696      *                  | "*" | "/" | "%"
 697      */
 698     JCExpression term2Rest(JCExpression t, int minprec) {
 699         List<JCExpression[]> savedOd = odStackSupply.elems;
 700         JCExpression[] odStack = newOdStack();
 701         List<Token[]> savedOp = opStackSupply.elems;
 702         Token[] opStack = newOpStack();
 703         List<int[]> savedPos = posStackSupply.elems;
 704         int[] posStack = newPosStack();
 705         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
 706         int top = 0;
 707         odStack[0] = t;
 708         int startPos = S.pos();
 709         Token topOp = ERROR;
 710         int topOpPos = Position.NOPOS;
 711         while (prec(S.token()) >= minprec) {
 712             posStack[top] = topOpPos;
 713             opStack[top] = topOp;
 714             top++;
 715             topOp = S.token();
 716             topOpPos = S.pos();
 717             S.nextToken();
 718             odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
 719             while (top > 0 && prec(topOp) >= prec(S.token())) {
 720                 odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
 721                                         odStack[top]);
 722                 top--;
 723                 topOp = opStack[top];
 724                 topOpPos = posStack[top];
 725             }
 726         }
 727         Assert.check(top == 0);
 728         t = odStack[0];
 729 
 730         if (t.getTag() == JCTree.PLUS) {
 731             StringBuffer buf = foldStrings(t);
 732             if (buf != null) {
 733                 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
 734             }
 735         }
 736 
 737         odStackSupply.elems = savedOd; // optimization
 738         opStackSupply.elems = savedOp; // optimization
 739         posStackSupply.elems = savedPos; // optimization
 740         return t;
 741     }
 742 //where
 743         /** Construct a binary or type test node.
 744          */
 745         private JCExpression makeOp(int pos,
 746                                     Token topOp,
 747                                     JCExpression od1,
 748                                     JCExpression od2)
 749         {
 750             if (topOp == INSTANCEOF) {
 751                 return F.at(pos).TypeTest(od1, od2);
 752             } else {
 753                 return F.at(pos).Binary(optag(topOp), od1, od2);
 754             }
 755         }
 756         /** If tree is a concatenation of string literals, replace it
 757          *  by a single literal representing the concatenated string.
 758          */
 759         protected StringBuffer foldStrings(JCTree tree) {
 760             List<String> buf = List.nil();
 761             while (true) {
 762                 if (tree.getTag() == JCTree.LITERAL) {
 763                     JCLiteral lit = (JCLiteral) tree;
 764                     if (lit.typetag == TypeTags.CLASS) {
 765                         StringBuffer sbuf =
 766                             new StringBuffer((String)lit.value);
 767                         while (buf.nonEmpty()) {
 768                             sbuf.append(buf.head);
 769                             buf = buf.tail;
 770                         }
 771                         return sbuf;
 772                     }
 773                 } else if (tree.getTag() == JCTree.PLUS) {
 774                     JCBinary op = (JCBinary)tree;
 775                     if (op.rhs.getTag() == JCTree.LITERAL) {
 776                         JCLiteral lit = (JCLiteral) op.rhs;
 777                         if (lit.typetag == TypeTags.CLASS) {
 778                             buf = buf.prepend((String) lit.value);
 779                             tree = op.lhs;
 780                             continue;
 781                         }
 782                     }
 783                 }
 784                 return null;
 785             }
 786         }
 787 
 788         /** optimization: To save allocating a new operand/operator stack
 789          *  for every binary operation, we use supplys.
 790          */
 791         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
 792         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
 793         ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
 794 
 795         private JCExpression[] newOdStack() {
 796             if (odStackSupply.elems == odStackSupply.last)
 797                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
 798             JCExpression[] odStack = odStackSupply.elems.head;
 799             odStackSupply.elems = odStackSupply.elems.tail;
 800             return odStack;
 801         }
 802 
 803         private Token[] newOpStack() {
 804             if (opStackSupply.elems == opStackSupply.last)
 805                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
 806             Token[] opStack = opStackSupply.elems.head;
 807             opStackSupply.elems = opStackSupply.elems.tail;
 808             return opStack;
 809         }
 810 
 811         private int[] newPosStack() {
 812             if (posStackSupply.elems == posStackSupply.last)
 813                 posStackSupply.append(new int[infixPrecedenceLevels + 1]);
 814             int[] posStack = posStackSupply.elems.head;
 815             posStackSupply.elems = posStackSupply.elems.tail;
 816             return posStack;
 817         }
 818 
 819     /** Expression3    = PrefixOp Expression3
 820      *                 | "(" Expr | TypeNoParams ")" Expression3
 821      *                 | Primary {Selector} {PostfixOp}
 822      *  Primary        = "(" Expression ")"
 823      *                 | Literal
 824      *                 | [TypeArguments] THIS [Arguments]
 825      *                 | [TypeArguments] SUPER SuperSuffix
 826      *                 | NEW [TypeArguments] Creator
 827      *                 | Ident { "." Ident }
 828      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
 829      *                   | Arguments
 830      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
 831      *                   ]
 832      *                 | BasicType BracketsOpt "." CLASS
 833      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
 834      *  PostfixOp      = "++" | "--"
 835      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
 836      *                 | BasicType
 837      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
 838      *  Selector       = "." [TypeArguments] Ident [Arguments]
 839      *                 | "." THIS
 840      *                 | "." [TypeArguments] SUPER SuperSuffix
 841      *                 | "." NEW [TypeArguments] InnerCreator
 842      *                 | "[" Expression "]"
 843      *  TypeSelector   = "." Ident [TypeArguments]
 844      *  SuperSuffix    = Arguments | "." Ident [Arguments]
 845      */
 846     protected JCExpression term3() {
 847         int pos = S.pos();
 848         JCExpression t;
 849         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
 850         switch (S.token()) {
 851         case QUES:
 852             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
 853                 mode = TYPE;
 854                 return typeArgument();
 855             } else
 856                 return illegal();
 857         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
 858             if (typeArgs == null && (mode & EXPR) != 0) {
 859                 Token token = S.token();
 860                 S.nextToken();
 861                 mode = EXPR;
 862                 if (token == SUB &&
 863                     (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
 864                     S.radix() == 10) {
 865                     mode = EXPR;
 866                     t = literal(names.hyphen);
 867                 } else {
 868                     t = term3();
 869                     return F.at(pos).Unary(unoptag(token), t);
 870                 }
 871             } else return illegal();
 872             break;
 873         case LPAREN:
 874             if (typeArgs == null && (mode & EXPR) != 0) {
 875                 S.nextToken();
 876                 mode = EXPR | TYPE | NOPARAMS;
 877                 t = term3();
 878                 if ((mode & TYPE) != 0 && S.token() == LT) {
 879                     // Could be a cast to a parameterized type
 880                     int op = JCTree.LT;
 881                     int pos1 = S.pos();
 882                     S.nextToken();
 883                     mode &= (EXPR | TYPE);
 884                     mode |= TYPEARG;
 885                     JCExpression t1 = term3();
 886                     if ((mode & TYPE) != 0 &&
 887                         (S.token() == COMMA || S.token() == GT)) {
 888                         mode = TYPE;
 889                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
 890                         args.append(t1);
 891                         while (S.token() == COMMA) {
 892                             S.nextToken();
 893                             args.append(typeArgument());
 894                         }
 895                         accept(GT);
 896                         t = toP(F.at(pos1).TypeApply(t, args.toList()));
 897                         checkGenerics();
 898                         while (S.token() == DOT) {
 899                             S.nextToken();
 900                             mode = TYPE;
 901                             t = toP(F.at(S.pos()).Select(t, ident()));
 902                             t = typeArgumentsOpt(t);
 903                         }
 904                         t = bracketsOpt(toP(t));
 905                     } else if ((mode & EXPR) != 0) {
 906                         mode = EXPR;
 907                         JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
 908                         t = F.at(pos1).Binary(op, t, e);
 909                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
 910                     } else {
 911                         accept(GT);
 912                     }
 913                 }
 914                 else {
 915                     t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
 916                 }
 917                 accept(RPAREN);
 918                 lastmode = mode;
 919                 mode = EXPR;
 920                 if ((lastmode & EXPR) == 0) {
 921                     JCExpression t1 = term3();
 922                     return F.at(pos).TypeCast(t, t1);
 923                 } else if ((lastmode & TYPE) != 0) {
 924                     switch (S.token()) {
 925                     /*case PLUSPLUS: case SUBSUB: */
 926                     case BANG: case TILDE:
 927                     case LPAREN: case THIS: case SUPER:
 928                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
 929                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
 930                     case TRUE: case FALSE: case NULL:
 931                     case NEW: case IDENTIFIER: case ASSERT: case ENUM:
 932                     case BYTE: case SHORT: case CHAR: case INT:
 933                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
 934                         JCExpression t1 = term3();
 935                         return F.at(pos).TypeCast(t, t1);
 936                     }
 937                 }
 938             } else return illegal();
 939             t = toP(F.at(pos).Parens(t));
 940             break;
 941         case THIS:
 942             if ((mode & EXPR) != 0) {
 943                 mode = EXPR;
 944                 t = to(F.at(pos).Ident(names._this));
 945                 S.nextToken();
 946                 if (typeArgs == null)
 947                     t = argumentsOpt(null, t);
 948                 else
 949                     t = arguments(typeArgs, t);
 950                 typeArgs = null;
 951             } else return illegal();
 952             break;
 953         case SUPER:
 954             if ((mode & EXPR) != 0) {
 955                 mode = EXPR;
 956                 t = to(F.at(pos).Ident(names._super));
 957                 t = superSuffix(typeArgs, t);
 958                 typeArgs = null;
 959             } else return illegal();
 960             break;
 961         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
 962         case CHARLITERAL: case STRINGLITERAL:
 963         case TRUE: case FALSE: case NULL:
 964             if (typeArgs == null && (mode & EXPR) != 0) {
 965                 mode = EXPR;
 966                 t = literal(names.empty);
 967             } else return illegal();
 968             break;
 969         case NEW:
 970             if (typeArgs != null) return illegal();
 971             if ((mode & EXPR) != 0) {
 972                 mode = EXPR;
 973                 S.nextToken();
 974                 if (S.token() == LT) typeArgs = typeArguments();
 975                 t = creator(pos, typeArgs);
 976                 typeArgs = null;
 977             } else return illegal();
 978             break;
 979         case IDENTIFIER: case ASSERT: case ENUM:
 980             if (typeArgs != null) return illegal();
 981             t = toP(F.at(S.pos()).Ident(ident()));
 982             loop: while (true) {
 983                 pos = S.pos();
 984                 switch (S.token()) {
 985                 case LBRACKET:
 986                     S.nextToken();
 987                     if (S.token() == RBRACKET) {
 988                         S.nextToken();
 989                         t = bracketsOpt(t);
 990                         t = toP(F.at(pos).TypeArray(t));
 991                         t = bracketsSuffix(t);
 992                     } else {
 993                         if ((mode & EXPR) != 0) {
 994                             mode = EXPR;
 995                             JCExpression t1 = term();
 996                             t = to(F.at(pos).Indexed(t, t1));
 997                         }
 998                         accept(RBRACKET);
 999                     }
1000                     break loop;
1001                 case LPAREN:
1002                     if ((mode & EXPR) != 0) {
1003                         mode = EXPR;
1004                         t = arguments(typeArgs, t);
1005                         typeArgs = null;
1006                     }
1007                     break loop;
1008                 case DOT:
1009                     S.nextToken();
1010                     int oldmode = mode;
1011                     mode &= ~NOPARAMS;
1012                     typeArgs = typeArgumentsOpt(EXPR);
1013                     mode = oldmode;
1014                     if ((mode & EXPR) != 0) {
1015                         switch (S.token()) {
1016                         case CLASS:
1017                             if (typeArgs != null) return illegal();
1018                             mode = EXPR;
1019                             t = to(F.at(pos).Select(t, names._class));
1020                             S.nextToken();
1021                             break loop;
1022                         case THIS:
1023                             if (typeArgs != null) return illegal();
1024                             mode = EXPR;
1025                             t = to(F.at(pos).Select(t, names._this));
1026                             S.nextToken();
1027                             break loop;
1028                         case SUPER:
1029                             mode = EXPR;
1030                             t = to(F.at(pos).Select(t, names._super));
1031                             t = superSuffix(typeArgs, t);
1032                             typeArgs = null;
1033                             break loop;
1034                         case NEW:
1035                             if (typeArgs != null) return illegal();
1036                             mode = EXPR;
1037                             int pos1 = S.pos();
1038                             S.nextToken();
1039                             if (S.token() == LT) typeArgs = typeArguments();
1040                             t = innerCreator(pos1, typeArgs, t);
1041                             typeArgs = null;
1042                             break loop;
1043                         }
1044                     }
1045                     // typeArgs saved for next loop iteration.
1046                     t = toP(F.at(pos).Select(t, ident()));
1047                     break;
1048                 default:
1049                     break loop;
1050                 }
1051             }
1052             if (typeArgs != null) illegal();
1053             t = typeArgumentsOpt(t);
1054             break;
1055         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1056         case DOUBLE: case BOOLEAN:
1057             if (typeArgs != null) illegal();
1058             t = bracketsSuffix(bracketsOpt(basicType()));
1059             break;
1060         case VOID:
1061             if (typeArgs != null) illegal();
1062             if ((mode & EXPR) != 0) {
1063                 S.nextToken();
1064                 if (S.token() == DOT) {
1065                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
1066                     t = bracketsSuffix(ti);
1067                 } else {
1068                     return illegal(pos);
1069                 }
1070             } else {
1071                 // Support the corner case of myMethodHandle.<void>invoke() by passing
1072                 // a void type (like other primitive types) to the next phase.
1073                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1074                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
1075                 S.nextToken();
1076                 return ti;
1077                 //return illegal();
1078             }
1079             break;
1080         default:
1081             return illegal();
1082         }
1083         if (typeArgs != null) illegal();
1084         while (true) {
1085             int pos1 = S.pos();
1086             if (S.token() == LBRACKET) {
1087                 S.nextToken();
1088                 if ((mode & TYPE) != 0) {
1089                     int oldmode = mode;
1090                     mode = TYPE;
1091                     if (S.token() == RBRACKET) {
1092                         S.nextToken();
1093                         t = bracketsOpt(t);
1094                         t = toP(F.at(pos1).TypeArray(t));
1095                         return t;
1096                     }
1097                     mode = oldmode;
1098                 }
1099                 if ((mode & EXPR) != 0) {
1100                     mode = EXPR;
1101                     JCExpression t1 = term();
1102                     t = to(F.at(pos1).Indexed(t, t1));
1103                 }
1104                 accept(RBRACKET);
1105             } else if (S.token() == DOT) {
1106                 S.nextToken();
1107                 typeArgs = typeArgumentsOpt(EXPR);
1108                 if (S.token() == SUPER && (mode & EXPR) != 0) {
1109                     mode = EXPR;
1110                     t = to(F.at(pos1).Select(t, names._super));
1111                     S.nextToken();
1112                     t = arguments(typeArgs, t);
1113                     typeArgs = null;
1114                 } else if (S.token() == NEW && (mode & EXPR) != 0) {
1115                     if (typeArgs != null) return illegal();
1116                     mode = EXPR;
1117                     int pos2 = S.pos();
1118                     S.nextToken();
1119                     if (S.token() == LT) typeArgs = typeArguments();
1120                     t = innerCreator(pos2, typeArgs, t);
1121                     typeArgs = null;
1122                 } else {
1123                     t = toP(F.at(pos1).Select(t, ident()));
1124                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1125                     typeArgs = null;
1126                 }
1127             } else {
1128                 break;
1129             }
1130         }
1131         while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
1132             mode = EXPR;
1133             t = to(F.at(S.pos()).Unary(
1134                   S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
1135             S.nextToken();
1136         }
1137         return toP(t);
1138     }
1139 
1140     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1141      */
1142     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1143         S.nextToken();
1144         if (S.token() == LPAREN || typeArgs != null) {
1145             t = arguments(typeArgs, t);
1146         } else {
1147             int pos = S.pos();
1148             accept(DOT);
1149             typeArgs = (S.token() == LT) ? typeArguments() : null;
1150             t = toP(F.at(pos).Select(t, ident()));
1151             t = argumentsOpt(typeArgs, t);
1152         }
1153         return t;
1154     }
1155 
1156     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1157      */
1158     JCPrimitiveTypeTree basicType() {
1159         JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
1160         S.nextToken();
1161         return t;
1162     }
1163 
1164     /** ArgumentsOpt = [ Arguments ]
1165      */
1166     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1167         if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
1168             mode = EXPR;
1169             return arguments(typeArgs, t);
1170         } else {
1171             return t;
1172         }
1173     }
1174 
1175     /** Arguments = "(" [Expression { COMMA Expression }] ")"
1176      */
1177     List<JCExpression> arguments() {
1178         ListBuffer<JCExpression> args = lb();
1179         if (S.token() == LPAREN) {
1180             S.nextToken();
1181             if (S.token() != RPAREN) {
1182                 args.append(parseExpression());
1183                 while (S.token() == COMMA) {
1184                     S.nextToken();
1185                     args.append(parseExpression());
1186                 }
1187             }
1188             accept(RPAREN);
1189         } else {
1190             syntaxError(S.pos(), "expected", LPAREN);
1191         }
1192         return args.toList();
1193     }
1194 
1195     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1196         int pos = S.pos();
1197         List<JCExpression> args = arguments();
1198         return toP(F.at(pos).Apply(typeArgs, t, args));
1199     }
1200 
1201     /**  TypeArgumentsOpt = [ TypeArguments ]
1202      */
1203     JCExpression typeArgumentsOpt(JCExpression t) {
1204         if (S.token() == LT &&
1205             (mode & TYPE) != 0 &&
1206             (mode & NOPARAMS) == 0) {
1207             mode = TYPE;
1208             checkGenerics();
1209             return typeArguments(t);
1210         } else {
1211             return t;
1212         }
1213     }
1214     List<JCExpression> typeArgumentsOpt() {
1215         return typeArgumentsOpt(TYPE);
1216     }
1217 
1218     List<JCExpression> typeArgumentsOpt(int useMode) {
1219         if (S.token() == LT) {
1220             checkGenerics();
1221             if ((mode & useMode) == 0 ||
1222                 (mode & NOPARAMS) != 0) {
1223                 illegal();
1224             }
1225             mode = useMode;
1226             return typeArguments();
1227         }
1228         return null;
1229     }
1230 
1231     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
1232      */
1233     List<JCExpression> typeArguments() {
1234         ListBuffer<JCExpression> args = lb();
1235         if (S.token() == LT) {
1236             S.nextToken();
1237             if (S.token() == GT && (mode & DIAMOND) != 0) {
1238                 checkDiamond();
1239                 S.nextToken();
1240                 return List.nil();
1241             }
1242             args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1243             while (S.token() == COMMA) {
1244                 S.nextToken();
1245                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
1246             }
1247             switch (S.token()) {
1248             case GTGTGTEQ:
1249                 S.token(GTGTEQ);
1250                 break;
1251             case GTGTEQ:
1252                 S.token(GTEQ);
1253                 break;
1254             case GTEQ:
1255                 S.token(EQ);
1256                 break;
1257             case GTGTGT:
1258                 S.token(GTGT);
1259                 break;
1260             case GTGT:
1261                 S.token(GT);
1262                 break;
1263             default:
1264                 accept(GT);
1265                 break;
1266             }
1267         } else {
1268             syntaxError(S.pos(), "expected", LT);
1269         }
1270         return args.toList();
1271     }
1272 
1273     /** TypeArgument = Type
1274      *               | "?"
1275      *               | "?" EXTENDS Type {"&" Type}
1276      *               | "?" SUPER Type
1277      */
1278     JCExpression typeArgument() {
1279         if (S.token() != QUES) return parseType();
1280         int pos = S.pos();
1281         S.nextToken();
1282         if (S.token() == EXTENDS) {
1283             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
1284             S.nextToken();
1285             JCExpression bound = parseType();
1286             return F.at(pos).Wildcard(t, bound);
1287         } else if (S.token() == SUPER) {
1288             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
1289             S.nextToken();
1290             JCExpression bound = parseType();
1291             return F.at(pos).Wildcard(t, bound);
1292         } else if (S.token() == IDENTIFIER) {
1293             //error recovery
1294             reportSyntaxError(S.prevEndPos(), "expected3",
1295                     GT, EXTENDS, SUPER);
1296             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1297             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1298             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
1299             return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1300         } else {
1301             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
1302             return toP(F.at(pos).Wildcard(t, null));
1303         }
1304     }
1305 
1306     JCTypeApply typeArguments(JCExpression t) {
1307         int pos = S.pos();
1308         List<JCExpression> args = typeArguments();
1309         return toP(F.at(pos).TypeApply(t, args));
1310     }
1311 
1312     /** BracketsOpt = {"[" "]"}
1313      */
1314     private JCExpression bracketsOpt(JCExpression t) {
1315         if (S.token() == LBRACKET) {
1316             int pos = S.pos();
1317             S.nextToken();
1318             t = bracketsOptCont(t, pos);
1319             F.at(pos);
1320         }
1321         return t;
1322     }
1323 
1324     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
1325         accept(RBRACKET);
1326         t = bracketsOpt(t);
1327         return toP(F.at(pos).TypeArray(t));
1328     }
1329 
1330     /** BracketsSuffixExpr = "." CLASS
1331      *  BracketsSuffixType =
1332      */
1333     JCExpression bracketsSuffix(JCExpression t) {
1334         if ((mode & EXPR) != 0 && S.token() == DOT) {
1335             mode = EXPR;
1336             int pos = S.pos();
1337             S.nextToken();
1338             accept(CLASS);
1339             if (S.pos() == errorEndPos) {
1340                 // error recovery
1341                 Name name = null;
1342                 if (S.token() == IDENTIFIER) {
1343                     name = S.name();
1344                     S.nextToken();
1345                 } else {
1346                     name = names.error;
1347                 }
1348                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1349             } else {
1350                 t = toP(F.at(pos).Select(t, names._class));
1351             }
1352         } else if ((mode & TYPE) != 0) {
1353             mode = TYPE;
1354         } else {
1355             syntaxError(S.pos(), "dot.class.expected");
1356         }
1357         return t;
1358     }
1359 
1360     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1361      */
1362     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1363         switch (S.token()) {
1364         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1365         case DOUBLE: case BOOLEAN:
1366             if (typeArgs == null)
1367                 return arrayCreatorRest(newpos, basicType());
1368             break;
1369         default:
1370         }
1371         JCExpression t = qualident();
1372         int oldmode = mode;
1373         mode = TYPE | DIAMOND;
1374         if (S.token() == LT) {
1375             checkGenerics();
1376             t = typeArguments(t);
1377         }
1378         while (S.token() == DOT) {
1379             int pos = S.pos();
1380             S.nextToken();
1381             t = toP(F.at(pos).Select(t, ident()));
1382             if (S.token() == LT) {
1383                 checkGenerics();
1384                 t = typeArguments(t);
1385             }
1386         }
1387         mode = oldmode;
1388         if (S.token() == LBRACKET) {
1389             JCExpression e = arrayCreatorRest(newpos, t);
1390             if (typeArgs != null) {
1391                 int pos = newpos;
1392                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
1393                     // note: this should always happen but we should
1394                     // not rely on this as the parser is continuously
1395                     // modified to improve error recovery.
1396                     pos = typeArgs.head.pos;
1397                 }
1398                 setErrorEndPos(S.prevEndPos());
1399                 reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
1400                 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
1401             }
1402             return e;
1403         } else if (S.token() == LPAREN) {
1404             return classCreatorRest(newpos, null, typeArgs, t);
1405         } else {
1406             reportSyntaxError(S.pos(), "expected2",
1407                                LPAREN, LBRACKET);
1408             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
1409             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
1410         }
1411     }
1412 
1413     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1414      */
1415     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
1416         JCExpression t = toP(F.at(S.pos()).Ident(ident()));
1417         if (S.token() == LT) {
1418             int oldmode = mode;
1419             mode |= DIAMOND;
1420             checkGenerics();
1421             t = typeArguments(t);
1422             mode = oldmode;
1423         }
1424         return classCreatorRest(newpos, encl, typeArgs, t);
1425     }
1426 
1427     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
1428      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
1429      */
1430     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1431         accept(LBRACKET);
1432         if (S.token() == RBRACKET) {
1433             accept(RBRACKET);
1434             elemtype = bracketsOpt(elemtype);
1435             if (S.token() == LBRACE) {
1436                 return arrayInitializer(newpos, elemtype);
1437             } else {
1438                 return syntaxError(S.pos(), "array.dimension.missing");
1439             }
1440         } else {
1441             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1442             dims.append(parseExpression());
1443             accept(RBRACKET);
1444             while (S.token() == LBRACKET) {
1445                 int pos = S.pos();
1446                 S.nextToken();
1447                 if (S.token() == RBRACKET) {
1448                     elemtype = bracketsOptCont(elemtype, pos);
1449                 } else {
1450                     dims.append(parseExpression());
1451                     accept(RBRACKET);
1452                 }
1453             }
1454             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
1455         }
1456     }
1457 
1458     /** ClassCreatorRest = Arguments [ClassBody]
1459      */
1460     JCNewClass classCreatorRest(int newpos,
1461                                   JCExpression encl,
1462                                   List<JCExpression> typeArgs,
1463                                   JCExpression t)
1464     {
1465         List<JCExpression> args = arguments();
1466         JCClassDecl body = null;
1467         if (S.token() == LBRACE) {
1468             int pos = S.pos();
1469             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1470             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1471             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1472         }
1473         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1474     }
1475 
1476     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1477      */
1478     JCExpression arrayInitializer(int newpos, JCExpression t) {
1479         accept(LBRACE);
1480         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1481         if (S.token() == COMMA) {
1482             S.nextToken();
1483         } else if (S.token() != RBRACE) {
1484             elems.append(variableInitializer());
1485             while (S.token() == COMMA) {
1486                 S.nextToken();
1487                 if (S.token() == RBRACE) break;
1488                 elems.append(variableInitializer());
1489             }
1490         }
1491         accept(RBRACE);
1492         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
1493     }
1494 
1495     /** VariableInitializer = ArrayInitializer | Expression
1496      */
1497     public JCExpression variableInitializer() {
1498         return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
1499     }
1500 
1501     /** ParExpression = "(" Expression ")"
1502      */
1503     JCExpression parExpression() {
1504         accept(LPAREN);
1505         JCExpression t = parseExpression();
1506         accept(RPAREN);
1507         return t;
1508     }
1509 
1510     /** Block = "{" BlockStatements "}"
1511      */
1512     JCBlock block(int pos, long flags) {
1513         accept(LBRACE);
1514         List<JCStatement> stats = blockStatements();
1515         JCBlock t = F.at(pos).Block(flags, stats);
1516         while (S.token() == CASE || S.token() == DEFAULT) {
1517             syntaxError("orphaned", S.token());
1518             switchBlockStatementGroups();
1519         }
1520         // the Block node has a field "endpos" for first char of last token, which is
1521         // usually but not necessarily the last char of the last token.
1522         t.endpos = S.pos();
1523         accept(RBRACE);
1524         return toP(t);
1525     }
1526 
1527     public JCBlock block() {
1528         return block(S.pos(), 0);
1529     }
1530 
1531     /** BlockStatements = { BlockStatement }
1532      *  BlockStatement  = LocalVariableDeclarationStatement
1533      *                  | ClassOrInterfaceOrEnumDeclaration
1534      *                  | [Ident ":"] Statement
1535      *  LocalVariableDeclarationStatement
1536      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1537      */
1538     @SuppressWarnings("fallthrough")
1539     List<JCStatement> blockStatements() {
1540 //todo: skip to anchor on error(?)
1541         int lastErrPos = -1;
1542         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1543         while (true) {
1544             int pos = S.pos();
1545             switch (S.token()) {
1546             case RBRACE: case CASE: case DEFAULT: case EOF:
1547                 return stats.toList();
1548             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
1549             case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
1550             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
1551                 stats.append(parseStatement());
1552                 break;
1553             case MONKEYS_AT:
1554             case FINAL: {
1555                 String dc = S.docComment();
1556                 JCModifiers mods = modifiersOpt();
1557                 if (S.token() == INTERFACE ||
1558                     S.token() == CLASS ||
1559                     allowEnums && S.token() == ENUM) {
1560                     stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1561                 } else {
1562                     JCExpression t = parseType();
1563                     stats.appendList(variableDeclarators(mods, t,
1564                                                          new ListBuffer<JCStatement>()));
1565                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1566                     storeEnd(stats.elems.last(), S.endPos());
1567                     accept(SEMI);
1568                 }
1569                 break;
1570             }
1571             case ABSTRACT: case STRICTFP: {
1572                 String dc = S.docComment();
1573                 JCModifiers mods = modifiersOpt();
1574                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1575                 break;
1576             }
1577             case INTERFACE:
1578             case CLASS:
1579                 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1580                                                                S.docComment()));
1581                 break;
1582             case ENUM:
1583             case ASSERT:
1584                 if (allowEnums && S.token() == ENUM) {
1585                     error(S.pos(), "local.enum");
1586                     stats.
1587                         append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1588                                                                  S.docComment()));
1589                     break;
1590                 } else if (allowAsserts && S.token() == ASSERT) {
1591                     stats.append(parseStatement());
1592                     break;
1593                 }
1594                 /* fall through to default */
1595             default:
1596                 Name name = S.name();
1597                 JCExpression t = term(EXPR | TYPE);
1598                 if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
1599                     S.nextToken();
1600                     JCStatement stat = parseStatement();
1601                     stats.append(F.at(pos).Labelled(name, stat));
1602                 } else if ((lastmode & TYPE) != 0 &&
1603                            (S.token() == IDENTIFIER ||
1604                             S.token() == ASSERT ||
1605                             S.token() == ENUM)) {
1606                     pos = S.pos();
1607                     JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1608                     F.at(pos);
1609                     stats.appendList(variableDeclarators(mods, t,
1610                                                          new ListBuffer<JCStatement>()));
1611                     // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1612                     storeEnd(stats.elems.last(), S.endPos());
1613                     accept(SEMI);
1614                 } else {
1615                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1616                     stats.append(to(F.at(pos).Exec(checkExprStat(t))));
1617                     accept(SEMI);
1618                 }
1619             }
1620 
1621             // error recovery
1622             if (S.pos() == lastErrPos)
1623                 return stats.toList();
1624             if (S.pos() <= errorEndPos) {
1625                 skip(false, true, true, true);
1626                 lastErrPos = S.pos();
1627             }
1628 
1629             // ensure no dangling /** @deprecated */ active
1630             S.resetDeprecatedFlag();
1631         }
1632     }
1633 
1634     /** Statement =
1635      *       Block
1636      *     | IF ParExpression Statement [ELSE Statement]
1637      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1638      *     | FOR "(" FormalParameter : Expression ")" Statement
1639      *     | WHILE ParExpression Statement
1640      *     | DO Statement WHILE ParExpression ";"
1641      *     | TRY Block ( Catches | [Catches] FinallyPart )
1642      *     | TRY "(" ResourceSpecification ")" Block [Catches] [FinallyPart]
1643      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1644      *     | SYNCHRONIZED ParExpression Block
1645      *     | RETURN [Expression] ";"
1646      *     | THROW Expression ";"
1647      *     | BREAK [Ident] ";"
1648      *     | CONTINUE [Ident] ";"
1649      *     | ASSERT Expression [ ":" Expression ] ";"
1650      *     | ";"
1651      *     | ExpressionStatement
1652      *     | Ident ":" Statement
1653      */
1654     @SuppressWarnings("fallthrough")
1655     public JCStatement parseStatement() {
1656         int pos = S.pos();
1657         switch (S.token()) {
1658         case LBRACE:
1659             return block();
1660         case IF: {
1661             S.nextToken();
1662             JCExpression cond = parExpression();
1663             JCStatement thenpart = parseStatement();
1664             JCStatement elsepart = null;
1665             if (S.token() == ELSE) {
1666                 S.nextToken();
1667                 elsepart = parseStatement();
1668             }
1669             return F.at(pos).If(cond, thenpart, elsepart);
1670         }
1671         case FOR: {
1672             S.nextToken();
1673             accept(LPAREN);
1674             List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
1675             if (inits.length() == 1 &&
1676                 inits.head.getTag() == JCTree.VARDEF &&
1677                 ((JCVariableDecl) inits.head).init == null &&
1678                 S.token() == COLON) {
1679                 checkForeach();
1680                 JCVariableDecl var = (JCVariableDecl)inits.head;
1681                 accept(COLON);
1682                 JCExpression expr = parseExpression();
1683                 accept(RPAREN);
1684                 JCStatement body = parseStatement();
1685                 return F.at(pos).ForeachLoop(var, expr, body);
1686             } else {
1687                 accept(SEMI);
1688                 JCExpression cond = S.token() == SEMI ? null : parseExpression();
1689                 accept(SEMI);
1690                 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
1691                 accept(RPAREN);
1692                 JCStatement body = parseStatement();
1693                 return F.at(pos).ForLoop(inits, cond, steps, body);
1694             }
1695         }
1696         case WHILE: {
1697             S.nextToken();
1698             JCExpression cond = parExpression();
1699             JCStatement body = parseStatement();
1700             return F.at(pos).WhileLoop(cond, body);
1701         }
1702         case DO: {
1703             S.nextToken();
1704             JCStatement body = parseStatement();
1705             accept(WHILE);
1706             JCExpression cond = parExpression();
1707             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
1708             accept(SEMI);
1709             return t;
1710         }
1711         case TRY: {
1712             S.nextToken();
1713             List<JCTree> resources = List.<JCTree>nil();
1714             if (S.token() == LPAREN) {
1715                 checkTryWithResources();
1716                 S.nextToken();
1717                 resources = resources();
1718                 accept(RPAREN);
1719             }
1720             JCBlock body = block();
1721             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
1722             JCBlock finalizer = null;
1723             if (S.token() == CATCH || S.token() == FINALLY) {
1724                 while (S.token() == CATCH) catchers.append(catchClause());
1725                 if (S.token() == FINALLY) {
1726                     S.nextToken();
1727                     finalizer = block();
1728                 }
1729             } else {
1730                 if (allowTWR) {
1731                     if (resources.isEmpty())
1732                         error(pos, "try.without.catch.finally.or.resource.decls");
1733                 } else
1734                     error(pos, "try.without.catch.or.finally");
1735             }
1736             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
1737         }
1738         case SWITCH: {
1739             S.nextToken();
1740             JCExpression selector = parExpression();
1741             accept(LBRACE);
1742             List<JCCase> cases = switchBlockStatementGroups();
1743             JCSwitch t = to(F.at(pos).Switch(selector, cases));
1744             accept(RBRACE);
1745             return t;
1746         }
1747         case SYNCHRONIZED: {
1748             S.nextToken();
1749             JCExpression lock = parExpression();
1750             JCBlock body = block();
1751             return F.at(pos).Synchronized(lock, body);
1752         }
1753         case RETURN: {
1754             S.nextToken();
1755             JCExpression result = S.token() == SEMI ? null : parseExpression();
1756             JCReturn t = to(F.at(pos).Return(result));
1757             accept(SEMI);
1758             return t;
1759         }
1760         case THROW: {
1761             S.nextToken();
1762             JCExpression exc = parseExpression();
1763             JCThrow t = to(F.at(pos).Throw(exc));
1764             accept(SEMI);
1765             return t;
1766         }
1767         case BREAK: {
1768             S.nextToken();
1769             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1770             JCBreak t = to(F.at(pos).Break(label));
1771             accept(SEMI);
1772             return t;
1773         }
1774         case CONTINUE: {
1775             S.nextToken();
1776             Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1777             JCContinue t =  to(F.at(pos).Continue(label));
1778             accept(SEMI);
1779             return t;
1780         }
1781         case SEMI:
1782             S.nextToken();
1783             return toP(F.at(pos).Skip());
1784         case ELSE:
1785             return toP(F.Exec(syntaxError("else.without.if")));
1786         case FINALLY:
1787             return toP(F.Exec(syntaxError("finally.without.try")));
1788         case CATCH:
1789             return toP(F.Exec(syntaxError("catch.without.try")));
1790         case ASSERT: {
1791             if (allowAsserts && S.token() == ASSERT) {
1792                 S.nextToken();
1793                 JCExpression assertion = parseExpression();
1794                 JCExpression message = null;
1795                 if (S.token() == COLON) {
1796                     S.nextToken();
1797                     message = parseExpression();
1798                 }
1799                 JCAssert t = to(F.at(pos).Assert(assertion, message));
1800                 accept(SEMI);
1801                 return t;
1802             }
1803             /* else fall through to default case */
1804         }
1805         case ENUM:
1806         default:
1807             Name name = S.name();
1808             JCExpression expr = parseExpression();
1809             if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
1810                 S.nextToken();
1811                 JCStatement stat = parseStatement();
1812                 return F.at(pos).Labelled(name, stat);
1813             } else {
1814                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1815                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
1816                 accept(SEMI);
1817                 return stat;
1818             }
1819         }
1820     }
1821 
1822     /** CatchClause     = CATCH "(" FormalParameter ")" Block
1823      */
1824     JCCatch catchClause() {
1825         int pos = S.pos();
1826         accept(CATCH);
1827         accept(LPAREN);
1828         JCModifiers mods = optFinal(Flags.PARAMETER);
1829         List<JCExpression> catchTypes = catchTypes();
1830         JCExpression paramType = catchTypes.size() > 1 ?
1831                 toP(F.at(catchTypes.head.getStartPosition()).TypeDisjunction(catchTypes)) :
1832                 catchTypes.head;
1833         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
1834         accept(RPAREN);
1835         JCBlock body = block();
1836         return F.at(pos).Catch(formal, body);
1837     }
1838 
1839     List<JCExpression> catchTypes() {
1840         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
1841         catchTypes.add(parseType());
1842         while (S.token() == BAR) {
1843             checkMulticatch();
1844             S.nextToken();
1845             catchTypes.add(qualident());
1846         }
1847         return catchTypes.toList();
1848     }
1849 
1850     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
1851      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
1852      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
1853      */
1854     List<JCCase> switchBlockStatementGroups() {
1855         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
1856         while (true) {
1857             int pos = S.pos();
1858             switch (S.token()) {
1859             case CASE: {
1860                 S.nextToken();
1861                 JCExpression pat = parseExpression();
1862                 accept(COLON);
1863                 List<JCStatement> stats = blockStatements();
1864                 JCCase c = F.at(pos).Case(pat, stats);
1865                 if (stats.isEmpty())
1866                     storeEnd(c, S.prevEndPos());
1867                 cases.append(c);
1868                 break;
1869             }
1870             case DEFAULT: {
1871                 S.nextToken();
1872                 accept(COLON);
1873                 List<JCStatement> stats = blockStatements();
1874                 JCCase c = F.at(pos).Case(null, stats);
1875                 if (stats.isEmpty())
1876                     storeEnd(c, S.prevEndPos());
1877                 cases.append(c);
1878                 break;
1879             }
1880             case RBRACE: case EOF:
1881                 return cases.toList();
1882             default:
1883                 S.nextToken(); // to ensure progress
1884                 syntaxError(pos, "expected3",
1885                     CASE, DEFAULT, RBRACE);
1886             }
1887         }
1888     }
1889 
1890     /** MoreStatementExpressions = { COMMA StatementExpression }
1891      */
1892     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
1893                                                                     JCExpression first,
1894                                                                     T stats) {
1895         // This Exec is a "StatementExpression"; it subsumes no terminating token
1896         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
1897         while (S.token() == COMMA) {
1898             S.nextToken();
1899             pos = S.pos();
1900             JCExpression t = parseExpression();
1901             // This Exec is a "StatementExpression"; it subsumes no terminating token
1902             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
1903         }
1904         return stats;
1905     }
1906 
1907     /** ForInit = StatementExpression MoreStatementExpressions
1908      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
1909      */
1910     List<JCStatement> forInit() {
1911         ListBuffer<JCStatement> stats = lb();
1912         int pos = S.pos();
1913         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
1914             return variableDeclarators(optFinal(0), parseType(), stats).toList();
1915         } else {
1916             JCExpression t = term(EXPR | TYPE);
1917             if ((lastmode & TYPE) != 0 &&
1918                 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
1919                 return variableDeclarators(modifiersOpt(), t, stats).toList();
1920             else
1921                 return moreStatementExpressions(pos, t, stats).toList();
1922         }
1923     }
1924 
1925     /** ForUpdate = StatementExpression MoreStatementExpressions
1926      */
1927     List<JCExpressionStatement> forUpdate() {
1928         return moreStatementExpressions(S.pos(),
1929                                         parseExpression(),
1930                                         new ListBuffer<JCExpressionStatement>()).toList();
1931     }
1932 
1933     /** AnnotationsOpt = { '@' Annotation }
1934      */
1935     List<JCAnnotation> annotationsOpt() {
1936         if (S.token() != MONKEYS_AT) return List.nil(); // optimization
1937         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
1938         while (S.token() == MONKEYS_AT) {
1939             int pos = S.pos();
1940             S.nextToken();
1941             buf.append(annotation(pos));
1942         }
1943         return buf.toList();
1944     }
1945 
1946     /** ModifiersOpt = { Modifier }
1947      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
1948      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
1949      *           | "@" Annotation
1950      */
1951     JCModifiers modifiersOpt() {
1952         return modifiersOpt(null);
1953     }
1954     JCModifiers modifiersOpt(JCModifiers partial) {
1955         long flags;
1956         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
1957         int pos;
1958         if (partial == null) {
1959             flags = 0;
1960             pos = S.pos();
1961         } else {
1962             flags = partial.flags;
1963             annotations.appendList(partial.annotations);
1964             pos = partial.pos;
1965         }
1966         if (S.deprecatedFlag()) {
1967             flags |= Flags.DEPRECATED;
1968             S.resetDeprecatedFlag();
1969         }
1970         int lastPos = Position.NOPOS;
1971     loop:
1972         while (true) {
1973             long flag;
1974             switch (S.token()) {
1975             case PRIVATE     : flag = Flags.PRIVATE; break;
1976             case PROTECTED   : flag = Flags.PROTECTED; break;
1977             case PUBLIC      : flag = Flags.PUBLIC; break;
1978             case STATIC      : flag = Flags.STATIC; break;
1979             case TRANSIENT   : flag = Flags.TRANSIENT; break;
1980             case FINAL       : flag = Flags.FINAL; break;
1981             case ABSTRACT    : flag = Flags.ABSTRACT; break;
1982             case NATIVE      : flag = Flags.NATIVE; break;
1983             case VOLATILE    : flag = Flags.VOLATILE; break;
1984             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
1985             case STRICTFP    : flag = Flags.STRICTFP; break;
1986             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
1987             default: break loop;
1988             }
1989             if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
1990             lastPos = S.pos();
1991             S.nextToken();
1992             if (flag == Flags.ANNOTATION) {
1993                 checkAnnotations();
1994                 if (S.token() != INTERFACE) {
1995                     JCAnnotation ann = annotation(lastPos);
1996                     // if first modifier is an annotation, set pos to annotation's.
1997                     if (flags == 0 && annotations.isEmpty())
1998                         pos = ann.pos;
1999                     annotations.append(ann);
2000                     lastPos = ann.pos;
2001                     flag = 0;
2002                 }
2003             }
2004             flags |= flag;
2005         }
2006         switch (S.token()) {
2007         case ENUM: flags |= Flags.ENUM; break;
2008         case INTERFACE: flags |= Flags.INTERFACE; break;
2009         default: break;
2010         }
2011 
2012         /* A modifiers tree with no modifier tokens or annotations
2013          * has no text position. */
2014         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
2015             pos = Position.NOPOS;
2016 
2017         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
2018         if (pos != Position.NOPOS)
2019             storeEnd(mods, S.prevEndPos());
2020         return mods;
2021     }
2022 
2023     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
2024      * @param pos position of "@" token
2025      */
2026     JCAnnotation annotation(int pos) {
2027         // accept(AT); // AT consumed by caller
2028         checkAnnotations();
2029         JCTree ident = qualident();
2030         List<JCExpression> fieldValues = annotationFieldValuesOpt();
2031         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
2032         storeEnd(ann, S.prevEndPos());
2033         return ann;
2034     }
2035 
2036     List<JCExpression> annotationFieldValuesOpt() {
2037         return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
2038     }
2039 
2040     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
2041     List<JCExpression> annotationFieldValues() {
2042         accept(LPAREN);
2043         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2044         if (S.token() != RPAREN) {
2045             buf.append(annotationFieldValue());
2046             while (S.token() == COMMA) {
2047                 S.nextToken();
2048                 buf.append(annotationFieldValue());
2049             }
2050         }
2051         accept(RPAREN);
2052         return buf.toList();
2053     }
2054 
2055     /** AnnotationFieldValue    = AnnotationValue
2056      *                          | Identifier "=" AnnotationValue
2057      */
2058     JCExpression annotationFieldValue() {
2059         if (S.token() == IDENTIFIER) {
2060             mode = EXPR;
2061             JCExpression t1 = term1();
2062             if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
2063                 int pos = S.pos();
2064                 accept(EQ);
2065                 JCExpression v = annotationValue();
2066                 return toP(F.at(pos).Assign(t1, v));
2067             } else {
2068                 return t1;
2069             }
2070         }
2071         return annotationValue();
2072     }
2073 
2074     /* AnnotationValue          = ConditionalExpression
2075      *                          | Annotation
2076      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
2077      */
2078     JCExpression annotationValue() {
2079         int pos;
2080         switch (S.token()) {
2081         case MONKEYS_AT:
2082             pos = S.pos();
2083             S.nextToken();
2084             return annotation(pos);
2085         case LBRACE:
2086             pos = S.pos();
2087             accept(LBRACE);
2088             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2089             if (S.token() != RBRACE) {
2090                 buf.append(annotationValue());
2091                 while (S.token() == COMMA) {
2092                     S.nextToken();
2093                     if (S.token() == RBRACE) break;
2094                     buf.append(annotationValue());
2095                 }
2096             }
2097             accept(RBRACE);
2098             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2099         default:
2100             mode = EXPR;
2101             return term1();
2102         }
2103     }
2104 
2105     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2106      */
2107     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2108                                                                          JCExpression type,
2109                                                                          T vdefs)
2110     {
2111         return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
2112     }
2113 
2114     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2115      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2116      *
2117      *  @param reqInit  Is an initializer always required?
2118      *  @param dc       The documentation comment for the variable declarations, or null.
2119      */
2120     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2121                                                                      JCModifiers mods,
2122                                                                      JCExpression type,
2123                                                                      Name name,
2124                                                                      boolean reqInit,
2125                                                                      String dc,
2126                                                                      T vdefs)
2127     {
2128         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2129         while (S.token() == COMMA) {
2130             // All but last of multiple declarators subsume a comma
2131             storeEnd((JCTree)vdefs.elems.last(), S.endPos());
2132             S.nextToken();
2133             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2134         }
2135         return vdefs;
2136     }
2137 
2138     /** VariableDeclarator = Ident VariableDeclaratorRest
2139      *  ConstantDeclarator = Ident ConstantDeclaratorRest
2140      */
2141     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
2142         return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
2143     }
2144 
2145     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2146      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2147      *
2148      *  @param reqInit  Is an initializer always required?
2149      *  @param dc       The documentation comment for the variable declarations, or null.
2150      */
2151     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2152                                   boolean reqInit, String dc) {
2153         type = bracketsOpt(type);
2154         JCExpression init = null;
2155         if (S.token() == EQ) {
2156             S.nextToken();
2157             init = variableInitializer();
2158         }
2159         else if (reqInit) syntaxError(S.pos(), "expected", EQ);
2160         JCVariableDecl result =
2161             toP(F.at(pos).VarDef(mods, name, type, init));
2162         attach(result, dc);
2163         return result;
2164     }
2165 
2166     /** VariableDeclaratorId = Ident BracketsOpt
2167      */
2168     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
2169         int pos = S.pos();
2170         Name name = ident();
2171         if ((mods.flags & Flags.VARARGS) == 0)
2172             type = bracketsOpt(type);
2173         return toP(F.at(pos).VarDef(mods, name, type, null));
2174     }
2175 
2176     /** Resources = Resource { ";" Resources }
2177      */
2178     List<JCTree> resources() {
2179         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2180         defs.append(resource());
2181         while (S.token() == SEMI) {
2182             // All but last of multiple declarators subsume a semicolon
2183             storeEnd(defs.elems.last(), S.endPos());
2184             S.nextToken();
2185             defs.append(resource());
2186         }
2187         return defs.toList();
2188     }
2189 
2190     /** Resource =
2191      *    VariableModifiers Type VariableDeclaratorId = Expression
2192      *  | Expression
2193      */
2194     JCTree resource() {
2195         int pos = S.pos();
2196         if (S.token() == FINAL || S.token() == MONKEYS_AT) {
2197             return variableDeclaratorRest(pos, optFinal(0), parseType(),
2198                                           ident(), true, null);
2199         } else {
2200             JCExpression t = term(EXPR | TYPE);
2201             if ((lastmode & TYPE) != 0 && S.token() == IDENTIFIER)
2202                 return variableDeclaratorRest(pos, toP(F.at(pos).Modifiers(Flags.FINAL)), t,
2203                                               ident(), true, null);
2204             else
2205                 return t;
2206         }
2207     }
2208 
2209     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2210      */
2211     public JCTree.JCCompilationUnit parseCompilationUnit() {
2212         int pos = S.pos();
2213         JCExpression pid = null;
2214         String dc = S.docComment();
2215         JCModifiers mods = null;
2216         List<JCAnnotation> packageAnnotations = List.nil();
2217         if (S.token() == MONKEYS_AT)
2218             mods = modifiersOpt();
2219 
2220         if (S.token() == PACKAGE) {
2221             if (mods != null) {
2222                 checkNoMods(mods.flags);
2223                 packageAnnotations = mods.annotations;
2224                 mods = null;
2225             }
2226             S.nextToken();
2227             pid = qualident();
2228             accept(SEMI);
2229         }
2230         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2231         boolean checkForImports = true;
2232         while (S.token() != EOF) {
2233             if (S.pos() <= errorEndPos) {
2234                 // error recovery
2235                 skip(checkForImports, false, false, false);
2236                 if (S.token() == EOF)
2237                     break;
2238             }
2239             if (checkForImports && mods == null && S.token() == IMPORT) {
2240                 defs.append(importDeclaration());
2241             } else {
2242                 JCTree def = typeDeclaration(mods);
2243                 if (keepDocComments && dc != null && docComments.get(def) == dc) {
2244                     // If the first type declaration has consumed the first doc
2245                     // comment, then don't use it for the top level comment as well.
2246                     dc = null;
2247                 }
2248                 if (def instanceof JCExpressionStatement)
2249                     def = ((JCExpressionStatement)def).expr;
2250                 defs.append(def);
2251                 if (def instanceof JCClassDecl)
2252                     checkForImports = false;
2253                 mods = null;
2254             }
2255         }
2256         JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
2257         attach(toplevel, dc);
2258         if (defs.elems.isEmpty())
2259             storeEnd(toplevel, S.prevEndPos());
2260         if (keepDocComments)
2261             toplevel.docComments = docComments;
2262         if (keepLineMap)
2263             toplevel.lineMap = S.getLineMap();
2264         return toplevel;
2265     }
2266 
2267     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2268      */
2269     JCTree importDeclaration() {
2270         int pos = S.pos();
2271         S.nextToken();
2272         boolean importStatic = false;
2273         if (S.token() == STATIC) {
2274             checkStaticImports();
2275             importStatic = true;
2276             S.nextToken();
2277         }
2278         JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
2279         do {
2280             int pos1 = S.pos();
2281             accept(DOT);
2282             if (S.token() == STAR) {
2283                 pid = to(F.at(pos1).Select(pid, names.asterisk));
2284                 S.nextToken();
2285                 break;
2286             } else {
2287                 pid = toP(F.at(pos1).Select(pid, ident()));
2288             }
2289         } while (S.token() == DOT);
2290         accept(SEMI);
2291         return toP(F.at(pos).Import(pid, importStatic));
2292     }
2293 
2294     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2295      *                  | ";"
2296      */
2297     JCTree typeDeclaration(JCModifiers mods) {
2298         int pos = S.pos();
2299         if (mods == null && S.token() == SEMI) {
2300             S.nextToken();
2301             return toP(F.at(pos).Skip());
2302         } else {
2303             String dc = S.docComment();
2304             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
2305         }
2306     }
2307 
2308     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2309      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2310      *  @param mods     Any modifiers starting the class or interface declaration
2311      *  @param dc       The documentation comment for the class, or null.
2312      */
2313     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
2314         if (S.token() == CLASS) {
2315             return classDeclaration(mods, dc);
2316         } else if (S.token() == INTERFACE) {
2317             return interfaceDeclaration(mods, dc);
2318         } else if (allowEnums) {
2319             if (S.token() == ENUM) {
2320                 return enumDeclaration(mods, dc);
2321             } else {
2322                 int pos = S.pos();
2323                 List<JCTree> errs;
2324                 if (S.token() == IDENTIFIER) {
2325                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2326                     setErrorEndPos(S.pos());
2327                 } else {
2328                     errs = List.<JCTree>of(mods);
2329                 }
2330                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
2331                                               CLASS, INTERFACE, ENUM)));
2332             }
2333         } else {
2334             if (S.token() == ENUM) {
2335                 error(S.pos(), "enums.not.supported.in.source", source.name);
2336                 allowEnums = true;
2337                 return enumDeclaration(mods, dc);
2338             }
2339             int pos = S.pos();
2340             List<JCTree> errs;
2341             if (S.token() == IDENTIFIER) {
2342                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2343                 setErrorEndPos(S.pos());
2344             } else {
2345                 errs = List.<JCTree>of(mods);
2346             }
2347             return toP(F.Exec(syntaxError(pos, errs, "expected2",
2348                                           CLASS, INTERFACE)));
2349         }
2350     }
2351 
2352     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2353      *                     [IMPLEMENTS TypeList] ClassBody
2354      *  @param mods    The modifiers starting the class declaration
2355      *  @param dc       The documentation comment for the class, or null.
2356      */
2357     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
2358         int pos = S.pos();
2359         accept(CLASS);
2360         Name name = ident();
2361 
2362         List<JCTypeParameter> typarams = typeParametersOpt();
2363 
2364         JCTree extending = null;
2365         if (S.token() == EXTENDS) {
2366             S.nextToken();
2367             extending = parseType();
2368         }
2369         List<JCExpression> implementing = List.nil();
2370         if (S.token() == IMPLEMENTS) {
2371             S.nextToken();
2372             implementing = typeList();
2373         }
2374         List<JCTree> defs = classOrInterfaceBody(name, false);
2375         JCClassDecl result = toP(F.at(pos).ClassDef(
2376             mods, name, typarams, extending, implementing, defs));
2377         attach(result, dc);
2378         return result;
2379     }
2380 
2381     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2382      *                         [EXTENDS TypeList] InterfaceBody
2383      *  @param mods    The modifiers starting the interface declaration
2384      *  @param dc       The documentation comment for the interface, or null.
2385      */
2386     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
2387         int pos = S.pos();
2388         accept(INTERFACE);
2389         Name name = ident();
2390 
2391         List<JCTypeParameter> typarams = typeParametersOpt();
2392 
2393         List<JCExpression> extending = List.nil();
2394         if (S.token() == EXTENDS) {
2395             S.nextToken();
2396             extending = typeList();
2397         }
2398         List<JCTree> defs = classOrInterfaceBody(name, true);
2399         JCClassDecl result = toP(F.at(pos).ClassDef(
2400             mods, name, typarams, null, extending, defs));
2401         attach(result, dc);
2402         return result;
2403     }
2404 
2405     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2406      *  @param mods    The modifiers starting the enum declaration
2407      *  @param dc       The documentation comment for the enum, or null.
2408      */
2409     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
2410         int pos = S.pos();
2411         accept(ENUM);
2412         Name name = ident();
2413 
2414         List<JCExpression> implementing = List.nil();
2415         if (S.token() == IMPLEMENTS) {
2416             S.nextToken();
2417             implementing = typeList();
2418         }
2419 
2420         List<JCTree> defs = enumBody(name);
2421         mods.flags |= Flags.ENUM;
2422         JCClassDecl result = toP(F.at(pos).
2423             ClassDef(mods, name, List.<JCTypeParameter>nil(),
2424                 null, implementing, defs));
2425         attach(result, dc);
2426         return result;
2427     }
2428 
2429     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2430      *                  [ ";" {ClassBodyDeclaration} ] "}"
2431      */
2432     List<JCTree> enumBody(Name enumName) {
2433         accept(LBRACE);
2434         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2435         if (S.token() == COMMA) {
2436             S.nextToken();
2437         } else if (S.token() != RBRACE && S.token() != SEMI) {
2438             defs.append(enumeratorDeclaration(enumName));
2439             while (S.token() == COMMA) {
2440                 S.nextToken();
2441                 if (S.token() == RBRACE || S.token() == SEMI) break;
2442                 defs.append(enumeratorDeclaration(enumName));
2443             }
2444             if (S.token() != SEMI && S.token() != RBRACE) {
2445                 defs.append(syntaxError(S.pos(), "expected3",
2446                                 COMMA, RBRACE, SEMI));
2447                 S.nextToken();
2448             }
2449         }
2450         if (S.token() == SEMI) {
2451             S.nextToken();
2452             while (S.token() != RBRACE && S.token() != EOF) {
2453                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
2454                                                                 false));
2455                 if (S.pos() <= errorEndPos) {
2456                     // error recovery
2457                    skip(false, true, true, false);
2458                 }
2459             }
2460         }
2461         accept(RBRACE);
2462         return defs.toList();
2463     }
2464 
2465     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2466      */
2467     JCTree enumeratorDeclaration(Name enumName) {
2468         String dc = S.docComment();
2469         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
2470         if (S.deprecatedFlag()) {
2471             flags |= Flags.DEPRECATED;
2472             S.resetDeprecatedFlag();
2473         }
2474         int pos = S.pos();
2475         List<JCAnnotation> annotations = annotationsOpt();
2476         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
2477         List<JCExpression> typeArgs = typeArgumentsOpt();
2478         int identPos = S.pos();
2479         Name name = ident();
2480         int createPos = S.pos();
2481         List<JCExpression> args = (S.token() == LPAREN)
2482             ? arguments() : List.<JCExpression>nil();
2483         JCClassDecl body = null;
2484         if (S.token() == LBRACE) {
2485             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
2486             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2487             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2488         }
2489         if (args.isEmpty() && body == null)
2490             createPos = identPos;
2491         JCIdent ident = F.at(identPos).Ident(enumName);
2492         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
2493         if (createPos != identPos)
2494             storeEnd(create, S.prevEndPos());
2495         ident = F.at(identPos).Ident(enumName);
2496         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2497         attach(result, dc);
2498         return result;
2499     }
2500 
2501     /** TypeList = Type {"," Type}
2502      */
2503     List<JCExpression> typeList() {
2504         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2505         ts.append(parseType());
2506         while (S.token() == COMMA) {
2507             S.nextToken();
2508             ts.append(parseType());
2509         }
2510         return ts.toList();
2511     }
2512 
2513     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
2514      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2515      */
2516     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
2517         accept(LBRACE);
2518         if (S.pos() <= errorEndPos) {
2519             // error recovery
2520             skip(false, true, false, false);
2521             if (S.token() == LBRACE)
2522                 S.nextToken();
2523         }
2524         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2525         while (S.token() != RBRACE && S.token() != EOF) {
2526             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
2527             if (S.pos() <= errorEndPos) {
2528                // error recovery
2529                skip(false, true, true, false);
2530            }
2531         }
2532         accept(RBRACE);
2533         return defs.toList();
2534     }
2535 
2536     /** ClassBodyDeclaration =
2537      *      ";"
2538      *    | [STATIC] Block
2539      *    | ModifiersOpt
2540      *      ( Type Ident
2541      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2542      *      | VOID Ident MethodDeclaratorRest
2543      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2544      *      | Ident ConstructorDeclaratorRest
2545      *      | TypeParameters Ident ConstructorDeclaratorRest
2546      *      | ClassOrInterfaceOrEnumDeclaration
2547      *      )
2548      *  InterfaceBodyDeclaration =
2549      *      ";"
2550      *    | ModifiersOpt Type Ident
2551      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2552      */
2553     List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
2554         if (S.token() == SEMI) {
2555             S.nextToken();
2556             return List.<JCTree>nil();
2557         } else {
2558             String dc = S.docComment();
2559             int pos = S.pos();
2560             JCModifiers mods = modifiersOpt();
2561             if (S.token() == CLASS ||
2562                 S.token() == INTERFACE ||
2563                 allowEnums && S.token() == ENUM) {
2564                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
2565             } else if (S.token() == LBRACE && !isInterface &&
2566                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
2567                        mods.annotations.isEmpty()) {
2568                 return List.<JCTree>of(block(pos, mods.flags));
2569             } else {
2570                 pos = S.pos();
2571                 List<JCTypeParameter> typarams = typeParametersOpt();
2572                 // if there are type parameters but no modifiers, save the start
2573                 // position of the method in the modifiers.
2574                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
2575                     mods.pos = pos;
2576                     storeEnd(mods, pos);
2577                 }
2578                 Name name = S.name();
2579                 pos = S.pos();
2580                 JCExpression type;
2581                 boolean isVoid = S.token() == VOID;
2582                 if (isVoid) {
2583                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
2584                     S.nextToken();
2585                 } else {
2586                     type = parseType();
2587                 }
2588                 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
2589                     if (isInterface || name != className)
2590                         error(pos, "invalid.meth.decl.ret.type.req");
2591                     return List.of(methodDeclaratorRest(
2592                         pos, mods, null, names.init, typarams,
2593                         isInterface, true, dc));
2594                 } else {
2595                     pos = S.pos();
2596                     name = ident();
2597                     if (S.token() == LPAREN) {
2598                         return List.of(methodDeclaratorRest(
2599                             pos, mods, type, name, typarams,
2600                             isInterface, isVoid, dc));
2601                     } else if (!isVoid && typarams.isEmpty()) {
2602                         List<JCTree> defs =
2603                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
2604                                                     new ListBuffer<JCTree>()).toList();
2605                         storeEnd(defs.last(), S.endPos());
2606                         accept(SEMI);
2607                         return defs;
2608                     } else {
2609                         pos = S.pos();
2610                         List<JCTree> err = isVoid
2611                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
2612                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
2613                             : null;
2614                         return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
2615                     }
2616                 }
2617             }
2618         }
2619     }
2620 
2621     /** MethodDeclaratorRest =
2622      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2623      *  VoidMethodDeclaratorRest =
2624      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
2625      *  InterfaceMethodDeclaratorRest =
2626      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
2627      *  VoidInterfaceMethodDeclaratorRest =
2628      *      FormalParameters [THROWS TypeList] ";"
2629      *  ConstructorDeclaratorRest =
2630      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
2631      */
2632     JCTree methodDeclaratorRest(int pos,
2633                               JCModifiers mods,
2634                               JCExpression type,
2635                               Name name,
2636                               List<JCTypeParameter> typarams,
2637                               boolean isInterface, boolean isVoid,
2638                               String dc) {
2639         List<JCVariableDecl> params = formalParameters();
2640         if (!isVoid) type = bracketsOpt(type);
2641         List<JCExpression> thrown = List.nil();
2642         if (S.token() == THROWS) {
2643             S.nextToken();
2644             thrown = qualidentList();
2645         }
2646         JCBlock body = null;
2647         JCExpression defaultValue;
2648         if (S.token() == LBRACE) {
2649             body = block();
2650             defaultValue = null;
2651         } else {
2652             if (S.token() == DEFAULT) {
2653                 accept(DEFAULT);
2654                 defaultValue = annotationValue();
2655             } else {
2656                 defaultValue = null;
2657             }
2658             accept(SEMI);
2659             if (S.pos() <= errorEndPos) {
2660                 // error recovery
2661                 skip(false, true, false, false);
2662                 if (S.token() == LBRACE) {
2663                     body = block();
2664                 }
2665             }
2666         }
2667 
2668         JCMethodDecl result =
2669             toP(F.at(pos).MethodDef(mods, name, type, typarams,
2670                                     params, thrown,
2671                                     body, defaultValue));
2672         attach(result, dc);
2673         return result;
2674     }
2675 
2676     /** QualidentList = Qualident {"," Qualident}
2677      */
2678     List<JCExpression> qualidentList() {
2679         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2680         ts.append(qualident());
2681         while (S.token() == COMMA) {
2682             S.nextToken();
2683             ts.append(qualident());
2684         }
2685         return ts.toList();
2686     }
2687 
2688     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
2689      */
2690     List<JCTypeParameter> typeParametersOpt() {
2691         if (S.token() == LT) {
2692             checkGenerics();
2693             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
2694             S.nextToken();
2695             typarams.append(typeParameter());
2696             while (S.token() == COMMA) {
2697                 S.nextToken();
2698                 typarams.append(typeParameter());
2699             }
2700             accept(GT);
2701             return typarams.toList();
2702         } else {
2703             return List.nil();
2704         }
2705     }
2706 
2707     /** TypeParameter = TypeVariable [TypeParameterBound]
2708      *  TypeParameterBound = EXTENDS Type {"&" Type}
2709      *  TypeVariable = Ident
2710      */
2711     JCTypeParameter typeParameter() {
2712         int pos = S.pos();
2713         Name name = ident();
2714         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
2715         if (S.token() == EXTENDS) {
2716             S.nextToken();
2717             bounds.append(parseType());
2718             while (S.token() == AMP) {
2719                 S.nextToken();
2720                 bounds.append(parseType());
2721             }
2722         }
2723         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
2724     }
2725 
2726     /** FormalParameters = "(" [ FormalParameterList ] ")"
2727      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
2728      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
2729      */
2730     List<JCVariableDecl> formalParameters() {
2731         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
2732         JCVariableDecl lastParam = null;
2733         accept(LPAREN);
2734         if (S.token() != RPAREN) {
2735             params.append(lastParam = formalParameter());
2736             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
2737                 S.nextToken();
2738                 params.append(lastParam = formalParameter());
2739             }
2740         }
2741         accept(RPAREN);
2742         return params.toList();
2743     }
2744 
2745     JCModifiers optFinal(long flags) {
2746         JCModifiers mods = modifiersOpt();
2747         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
2748         mods.flags |= flags;
2749         return mods;
2750     }
2751 
2752     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
2753      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
2754      */
2755     JCVariableDecl formalParameter() {
2756         JCModifiers mods = optFinal(Flags.PARAMETER);
2757         JCExpression type = parseType();
2758         if (S.token() == ELLIPSIS) {
2759             checkVarargs();
2760             mods.flags |= Flags.VARARGS;
2761             type = to(F.at(S.pos()).TypeArray(type));
2762             S.nextToken();
2763         }
2764         return variableDeclaratorId(mods, type);
2765     }
2766 
2767 /* ---------- auxiliary methods -------------- */
2768 
2769     void error(int pos, String key, Object ... args) {
2770         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
2771     }
2772 
2773     void warning(int pos, String key, Object ... args) {
2774         log.warning(pos, key, args);
2775     }
2776 
2777     /** Check that given tree is a legal expression statement.
2778      */
2779     protected JCExpression checkExprStat(JCExpression t) {
2780         switch(t.getTag()) {
2781         case JCTree.PREINC: case JCTree.PREDEC:
2782         case JCTree.POSTINC: case JCTree.POSTDEC:
2783         case JCTree.ASSIGN:
2784         case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
2785         case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
2786         case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
2787         case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
2788         case JCTree.APPLY: case JCTree.NEWCLASS:
2789         case JCTree.ERRONEOUS:
2790             return t;
2791         default:
2792             error(t.pos, "not.stmt");
2793             return F.at(t.pos).Erroneous(List.<JCTree>of(t));
2794         }
2795     }
2796 
2797     /** Return precedence of operator represented by token,
2798      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
2799      */
2800     static int prec(Token token) {
2801         int oc = optag(token);
2802         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
2803     }
2804 
2805     /**
2806      * Return the lesser of two positions, making allowance for either one
2807      * being unset.
2808      */
2809     static int earlier(int pos1, int pos2) {
2810         if (pos1 == Position.NOPOS)
2811             return pos2;
2812         if (pos2 == Position.NOPOS)
2813             return pos1;
2814         return (pos1 < pos2 ? pos1 : pos2);
2815     }
2816 
2817     /** Return operation tag of binary operator represented by token,
2818      *  -1 if token is not a binary operator.
2819      */
2820     static int optag(Token token) {
2821         switch (token) {
2822         case BARBAR:
2823             return JCTree.OR;
2824         case AMPAMP:
2825             return JCTree.AND;
2826         case BAR:
2827             return JCTree.BITOR;
2828         case BAREQ:
2829             return JCTree.BITOR_ASG;
2830         case CARET:
2831             return JCTree.BITXOR;
2832         case CARETEQ:
2833             return JCTree.BITXOR_ASG;
2834         case AMP:
2835             return JCTree.BITAND;
2836         case AMPEQ:
2837             return JCTree.BITAND_ASG;
2838         case EQEQ:
2839             return JCTree.EQ;
2840         case BANGEQ:
2841             return JCTree.NE;
2842         case LT:
2843             return JCTree.LT;
2844         case GT:
2845             return JCTree.GT;
2846         case LTEQ:
2847             return JCTree.LE;
2848         case GTEQ:
2849             return JCTree.GE;
2850         case LTLT:
2851             return JCTree.SL;
2852         case LTLTEQ:
2853             return JCTree.SL_ASG;
2854         case GTGT:
2855             return JCTree.SR;
2856         case GTGTEQ:
2857             return JCTree.SR_ASG;
2858         case GTGTGT:
2859             return JCTree.USR;
2860         case GTGTGTEQ:
2861             return JCTree.USR_ASG;
2862         case PLUS:
2863             return JCTree.PLUS;
2864         case PLUSEQ:
2865             return JCTree.PLUS_ASG;
2866         case SUB:
2867             return JCTree.MINUS;
2868         case SUBEQ:
2869             return JCTree.MINUS_ASG;
2870         case STAR:
2871             return JCTree.MUL;
2872         case STAREQ:
2873             return JCTree.MUL_ASG;
2874         case SLASH:
2875             return JCTree.DIV;
2876         case SLASHEQ:
2877             return JCTree.DIV_ASG;
2878         case PERCENT:
2879             return JCTree.MOD;
2880         case PERCENTEQ:
2881             return JCTree.MOD_ASG;
2882         case INSTANCEOF:
2883             return JCTree.TYPETEST;
2884         default:
2885             return -1;
2886         }
2887     }
2888 
2889     /** Return operation tag of unary operator represented by token,
2890      *  -1 if token is not a binary operator.
2891      */
2892     static int unoptag(Token token) {
2893         switch (token) {
2894         case PLUS:
2895             return JCTree.POS;
2896         case SUB:
2897             return JCTree.NEG;
2898         case BANG:
2899             return JCTree.NOT;
2900         case TILDE:
2901             return JCTree.COMPL;
2902         case PLUSPLUS:
2903             return JCTree.PREINC;
2904         case SUBSUB:
2905             return JCTree.PREDEC;
2906         default:
2907             return -1;
2908         }
2909     }
2910 
2911     /** Return type tag of basic type represented by token,
2912      *  -1 if token is not a basic type identifier.
2913      */
2914     static int typetag(Token token) {
2915         switch (token) {
2916         case BYTE:
2917             return TypeTags.BYTE;
2918         case CHAR:
2919             return TypeTags.CHAR;
2920         case SHORT:
2921             return TypeTags.SHORT;
2922         case INT:
2923             return TypeTags.INT;
2924         case LONG:
2925             return TypeTags.LONG;
2926         case FLOAT:
2927             return TypeTags.FLOAT;
2928         case DOUBLE:
2929             return TypeTags.DOUBLE;
2930         case BOOLEAN:
2931             return TypeTags.BOOLEAN;
2932         default:
2933             return -1;
2934         }
2935     }
2936 
2937     void checkGenerics() {
2938         if (!allowGenerics) {
2939             error(S.pos(), "generics.not.supported.in.source", source.name);
2940             allowGenerics = true;
2941         }
2942     }
2943     void checkVarargs() {
2944         if (!allowVarargs) {
2945             error(S.pos(), "varargs.not.supported.in.source", source.name);
2946             allowVarargs = true;
2947         }
2948     }
2949     void checkForeach() {
2950         if (!allowForeach) {
2951             error(S.pos(), "foreach.not.supported.in.source", source.name);
2952             allowForeach = true;
2953         }
2954     }
2955     void checkStaticImports() {
2956         if (!allowStaticImport) {
2957             error(S.pos(), "static.import.not.supported.in.source", source.name);
2958             allowStaticImport = true;
2959         }
2960     }
2961     void checkAnnotations() {
2962         if (!allowAnnotations) {
2963             error(S.pos(), "annotations.not.supported.in.source", source.name);
2964             allowAnnotations = true;
2965         }
2966     }
2967     void checkDiamond() {
2968         if (!allowDiamond) {
2969             error(S.pos(), "diamond.not.supported.in.source", source.name);
2970             allowDiamond = true;
2971         }
2972     }
2973     void checkMulticatch() {
2974         if (!allowMulticatch) {
2975             error(S.pos(), "multicatch.not.supported.in.source", source.name);
2976             allowMulticatch = true;
2977         }
2978     }
2979     void checkTryWithResources() {
2980         if (!allowTWR) {
2981             error(S.pos(), "try.with.resources.not.supported.in.source", source.name);
2982             allowTWR = true;
2983         }
2984     }
2985 }