src/share/classes/com/sun/tools/javac/parser/JavacParser.java

Wed, 10 Oct 2012 18:44:21 -0700

author
jjg
date
Wed, 10 Oct 2012 18:44:21 -0700
changeset 1362
c46e0c9940d6
parent 1352
d4b3cb1ece84
child 1366
12cf6bfd8c05
permissions
-rw-r--r--

8000310: Clean up use of StringBuffer in langtools
Reviewed-by: bpatel

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

mercurial