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