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