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

Thu, 04 Oct 2012 13:04:53 +0100

author
mcimadamore
date
Thu, 04 Oct 2012 13:04:53 +0100
changeset 1347
1408af4cd8b0
parent 1346
20e4a54b1629
child 1348
573ceb23beeb
permissions
-rw-r--r--

7177387: Add target-typing support in method context
Summary: Add support for deferred types and speculative attribution
Reviewed-by: jjg, dlsmith

     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             StringBuffer 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 StringBuffer 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                         StringBuffer sbuf =
   845                             new StringBuffer((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(FINAL) ||
   954                         peekToken(RPAREN) ||
   955                         peekToken(IDENTIFIER, COMMA) ||
   956                         peekToken(IDENTIFIER, RPAREN, ARROW)) {
   957                     //implicit n-ary lambda
   958                     t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos);
   959                     break;
   960                 } else {
   961                     nextToken();
   962                     mode = EXPR | TYPE | NOPARAMS;
   963                     t = term3();
   964                     if ((mode & TYPE) != 0 && token.kind == LT) {
   965                         // Could be a cast to a parameterized type
   966                         JCTree.Tag op = JCTree.Tag.LT;
   967                         int pos1 = token.pos;
   968                         nextToken();
   969                         mode &= (EXPR | TYPE);
   970                         mode |= TYPEARG;
   971                         JCExpression t1 = term3();
   972                         if ((mode & TYPE) != 0 &&
   973                             (token.kind == COMMA || token.kind == GT)) {
   974                             mode = TYPE;
   975                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   976                             args.append(t1);
   977                             while (token.kind == COMMA) {
   978                                 nextToken();
   979                                 args.append(typeArgument());
   980                             }
   981                             accept(GT);
   982                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
   983                             checkGenerics();
   984                             mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type
   985                             t = term3Rest(t, typeArgs);
   986                             if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) {
   987                                 //explicit lambda (w/ generic type)
   988                                 mode = EXPR;
   989                                 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
   990                                 if (token.kind == ELLIPSIS) {
   991                                     mods.flags = Flags.VARARGS;
   992                                     t = to(F.at(token.pos).TypeArray(t));
   993                                     nextToken();
   994                                 }
   995                                 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
   996                                 break;
   997                             }
   998                         } else if ((mode & EXPR) != 0) {
   999                             mode = EXPR;
  1000                             JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
  1001                             t = F.at(pos1).Binary(op, t, e);
  1002                             t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
  1003                         } else {
  1004                             accept(GT);
  1006                     } else if ((mode & TYPE) != 0 &&
  1007                             (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) {
  1008                         //explicit lambda (w/ non-generic type)
  1009                         mode = EXPR;
  1010                         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  1011                         if (token.kind == ELLIPSIS) {
  1012                             mods.flags = Flags.VARARGS;
  1013                             t = to(F.at(token.pos).TypeArray(t));
  1014                             nextToken();
  1016                         t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
  1017                         break;
  1018                     } else {
  1019                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
  1023                 accept(RPAREN);
  1024                 lastmode = mode;
  1025                 mode = EXPR;
  1026                 if ((lastmode & EXPR) == 0) {
  1027                     JCExpression t1 = term3();
  1028                     return F.at(pos).TypeCast(t, t1);
  1029                 } else if ((lastmode & TYPE) != 0) {
  1030                     switch (token.kind) {
  1031                     /*case PLUSPLUS: case SUBSUB: */
  1032                     case BANG: case TILDE:
  1033                     case LPAREN: case THIS: case SUPER:
  1034                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1035                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1036                     case TRUE: case FALSE: case NULL:
  1037                         case NEW: case IDENTIFIER: case ASSERT: case ENUM:
  1038                     case BYTE: case SHORT: case CHAR: case INT:
  1039                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1040                         JCExpression t1 = term3();
  1041                         return F.at(pos).TypeCast(t, t1);
  1044             } else {
  1045                 return illegal();
  1047             t = toP(F.at(pos).Parens(t));
  1048             break;
  1049         case THIS:
  1050             if ((mode & EXPR) != 0) {
  1051                 mode = EXPR;
  1052                 t = to(F.at(pos).Ident(names._this));
  1053                 nextToken();
  1054                 if (typeArgs == null)
  1055                     t = argumentsOpt(null, t);
  1056                 else
  1057                     t = arguments(typeArgs, t);
  1058                 typeArgs = null;
  1059             } else return illegal();
  1060             break;
  1061         case SUPER:
  1062             if ((mode & EXPR) != 0) {
  1063                 mode = EXPR;
  1064                 t = to(F.at(pos).Ident(names._super));
  1065                 t = superSuffix(typeArgs, t);
  1066                 typeArgs = null;
  1067             } else return illegal();
  1068             break;
  1069         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1070         case CHARLITERAL: case STRINGLITERAL:
  1071         case TRUE: case FALSE: case NULL:
  1072             if (typeArgs == null && (mode & EXPR) != 0) {
  1073                 mode = EXPR;
  1074                 t = literal(names.empty);
  1075             } else return illegal();
  1076             break;
  1077         case NEW:
  1078             if (typeArgs != null) return illegal();
  1079             if ((mode & EXPR) != 0) {
  1080                 mode = EXPR;
  1081                 nextToken();
  1082                 if (token.kind == LT) typeArgs = typeArguments(false);
  1083                 t = creator(pos, typeArgs);
  1084                 typeArgs = null;
  1085             } else return illegal();
  1086             break;
  1087         case IDENTIFIER: case ASSERT: case ENUM:
  1088             if (typeArgs != null) return illegal();
  1089             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1090                 t = lambdaExpressionOrStatement(false, false, pos);
  1091             } else {
  1092                 t = toP(F.at(token.pos).Ident(ident()));
  1093                 loop: while (true) {
  1094                     pos = token.pos;
  1095                     switch (token.kind) {
  1096                     case LBRACKET:
  1097                         nextToken();
  1098                         if (token.kind == RBRACKET) {
  1099                             nextToken();
  1100                             t = bracketsOpt(t);
  1101                             t = toP(F.at(pos).TypeArray(t));
  1102                             t = bracketsSuffix(t);
  1103                         } else {
  1104                             if ((mode & EXPR) != 0) {
  1105                                 mode = EXPR;
  1106                                 JCExpression t1 = term();
  1107                                 t = to(F.at(pos).Indexed(t, t1));
  1109                             accept(RBRACKET);
  1111                         break loop;
  1112                     case LPAREN:
  1113                         if ((mode & EXPR) != 0) {
  1114                             mode = EXPR;
  1115                             t = arguments(typeArgs, t);
  1116                             typeArgs = null;
  1118                         break loop;
  1119                     case DOT:
  1120                         nextToken();
  1121                         int oldmode = mode;
  1122                         mode &= ~NOPARAMS;
  1123                         typeArgs = typeArgumentsOpt(EXPR);
  1124                         mode = oldmode;
  1125                         if ((mode & EXPR) != 0) {
  1126                             switch (token.kind) {
  1127                             case CLASS:
  1128                                 if (typeArgs != null) return illegal();
  1129                                 mode = EXPR;
  1130                                 t = to(F.at(pos).Select(t, names._class));
  1131                                 nextToken();
  1132                                 break loop;
  1133                             case THIS:
  1134                                 if (typeArgs != null) return illegal();
  1135                                 mode = EXPR;
  1136                                 t = to(F.at(pos).Select(t, names._this));
  1137                                 nextToken();
  1138                                 break loop;
  1139                             case SUPER:
  1140                                 mode = EXPR;
  1141                                 t = to(F.at(pos).Select(t, names._super));
  1142                                 t = superSuffix(typeArgs, t);
  1143                                 typeArgs = null;
  1144                                 break loop;
  1145                             case NEW:
  1146                                 if (typeArgs != null) return illegal();
  1147                                 mode = EXPR;
  1148                                 int pos1 = token.pos;
  1149                                 nextToken();
  1150                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1151                                 t = innerCreator(pos1, typeArgs, t);
  1152                                 typeArgs = null;
  1153                                 break loop;
  1156                         // typeArgs saved for next loop iteration.
  1157                         t = toP(F.at(pos).Select(t, ident()));
  1158                         break;
  1159                     case LT:
  1160                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1161                             //this is an unbound method reference whose qualifier
  1162                             //is a generic type i.e. A<S>#m
  1163                             int pos1 = token.pos;
  1164                             accept(LT);
  1165                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1166                             args.append(typeArgument());
  1167                             while (token.kind == COMMA) {
  1168                                 nextToken();
  1169                                 args.append(typeArgument());
  1171                             accept(GT);
  1172                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1173                             checkGenerics();
  1174                             while (token.kind == DOT) {
  1175                                 nextToken();
  1176                                 mode = TYPE;
  1177                                 t = toP(F.at(token.pos).Select(t, ident()));
  1178                                 t = typeArgumentsOpt(t);
  1180                             if (token.kind != HASH) {
  1181                                 //method reference expected here
  1182                                 t = illegal();
  1184                             mode = EXPR;
  1185                             return term3Rest(t, typeArgs);
  1187                         break loop;
  1188                     default:
  1189                         break loop;
  1193             if (typeArgs != null) illegal();
  1194             t = typeArgumentsOpt(t);
  1195             break;
  1196         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1197         case DOUBLE: case BOOLEAN:
  1198             if (typeArgs != null) illegal();
  1199             t = bracketsSuffix(bracketsOpt(basicType()));
  1200             break;
  1201         case VOID:
  1202             if (typeArgs != null) illegal();
  1203             if ((mode & EXPR) != 0) {
  1204                 nextToken();
  1205                 if (token.kind == DOT) {
  1206                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1207                     t = bracketsSuffix(ti);
  1208                 } else {
  1209                     return illegal(pos);
  1211             } else {
  1212                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1213                 // a void type (like other primitive types) to the next phase.
  1214                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1215                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1216                 nextToken();
  1217                 return ti;
  1218                 //return illegal();
  1220             break;
  1221         default:
  1222             return illegal();
  1224         return term3Rest(t, typeArgs);
  1227     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1228         if (typeArgs != null) illegal();
  1229         while (true) {
  1230             int pos1 = token.pos;
  1231             if (token.kind == LBRACKET) {
  1232                 nextToken();
  1233                 if ((mode & TYPE) != 0) {
  1234                     int oldmode = mode;
  1235                     mode = TYPE;
  1236                     if (token.kind == RBRACKET) {
  1237                         nextToken();
  1238                         t = bracketsOpt(t);
  1239                         t = toP(F.at(pos1).TypeArray(t));
  1240                         return t;
  1242                     mode = oldmode;
  1244                 if ((mode & EXPR) != 0) {
  1245                     mode = EXPR;
  1246                     JCExpression t1 = term();
  1247                     t = to(F.at(pos1).Indexed(t, t1));
  1249                 accept(RBRACKET);
  1250             } else if (token.kind == DOT) {
  1251                 nextToken();
  1252                 typeArgs = typeArgumentsOpt(EXPR);
  1253                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1254                     mode = EXPR;
  1255                     t = to(F.at(pos1).Select(t, names._super));
  1256                     nextToken();
  1257                     t = arguments(typeArgs, t);
  1258                     typeArgs = null;
  1259                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1260                     if (typeArgs != null) return illegal();
  1261                     mode = EXPR;
  1262                     int pos2 = token.pos;
  1263                     nextToken();
  1264                     if (token.kind == LT) typeArgs = typeArguments(false);
  1265                     t = innerCreator(pos2, typeArgs, t);
  1266                     typeArgs = null;
  1267                 } else {
  1268                     t = toP(F.at(pos1).Select(t, ident()));
  1269                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1270                     typeArgs = null;
  1272             } else if ((mode & EXPR) != 0 && token.kind == HASH) {
  1273                 mode = EXPR;
  1274                 if (typeArgs != null) return illegal();
  1275                 accept(HASH);
  1276                 t = memberReferenceSuffix(pos1, t);
  1277             } else {
  1278                 break;
  1281         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1282             mode = EXPR;
  1283             t = to(F.at(token.pos).Unary(
  1284                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1285             nextToken();
  1287         return toP(t);
  1290     /**
  1291      * If we see an identifier followed by a '&lt;' it could be an unbound
  1292      * method reference or a binary expression. To disambiguate, look for a
  1293      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1294      */
  1295     @SuppressWarnings("fallthrough")
  1296     boolean isUnboundMemberRef() {
  1297         int pos = 0, depth = 0;
  1298         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1299             switch (t.kind) {
  1300                 case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
  1301                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1302                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1303                 case DOUBLE: case BOOLEAN: case CHAR:
  1304                     break;
  1305                 case LT:
  1306                     depth++; break;
  1307                 case GTGTGT:
  1308                     depth--;
  1309                 case GTGT:
  1310                     depth--;
  1311                 case GT:
  1312                     depth--;
  1313                     if (depth == 0) {
  1314                         return
  1315                             S.token(pos + 1).kind == TokenKind.DOT ||
  1316                             S.token(pos + 1).kind == TokenKind.HASH;
  1318                     break;
  1319                 default:
  1320                     return false;
  1325     JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
  1326         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  1327         params.append(firstParam);
  1328         JCVariableDecl lastParam = firstParam;
  1329         while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  1330             nextToken();
  1331             params.append(lastParam = formalParameter());
  1333         accept(RPAREN);
  1334         return lambdaExpressionOrStatementRest(params.toList(), pos);
  1337     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1338         List<JCVariableDecl> params = explicitParams ?
  1339                 formalParameters() :
  1340                 implicitParameters(hasParens);
  1342         return lambdaExpressionOrStatementRest(params, pos);
  1345     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1346         if (token.kind != ARROW) {
  1347             //better error recovery
  1348             return F.at(pos).Erroneous(args);
  1351         checkLambda();
  1352         accept(ARROW);
  1354         return token.kind == LBRACE ?
  1355             lambdaStatement(args, pos, pos) :
  1356             lambdaExpression(args, pos);
  1359     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1360         JCBlock block = block(pos2, 0);
  1361         return toP(F.at(pos).Lambda(args, block));
  1364     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1365         JCTree expr = parseExpression();
  1366         return toP(F.at(pos).Lambda(args, expr));
  1369     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1370      */
  1371     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1372         nextToken();
  1373         if (token.kind == LPAREN || typeArgs != null) {
  1374             t = arguments(typeArgs, t);
  1375         } else if (token.kind == HASH) {
  1376             if (typeArgs != null) return illegal();
  1377             t = memberReferenceSuffix(t);
  1378         } else {
  1379             int pos = token.pos;
  1380             accept(DOT);
  1381             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1382             t = toP(F.at(pos).Select(t, ident()));
  1383             t = argumentsOpt(typeArgs, t);
  1385         return t;
  1388     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1389      */
  1390     JCPrimitiveTypeTree basicType() {
  1391         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1392         nextToken();
  1393         return t;
  1396     /** ArgumentsOpt = [ Arguments ]
  1397      */
  1398     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1399         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1400             mode = EXPR;
  1401             return arguments(typeArgs, t);
  1402         } else {
  1403             return t;
  1407     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1408      */
  1409     List<JCExpression> arguments() {
  1410         ListBuffer<JCExpression> args = lb();
  1411         if (token.kind == LPAREN) {
  1412             nextToken();
  1413             if (token.kind != RPAREN) {
  1414                 args.append(parseExpression());
  1415                 while (token.kind == COMMA) {
  1416                     nextToken();
  1417                     args.append(parseExpression());
  1420             accept(RPAREN);
  1421         } else {
  1422             syntaxError(token.pos, "expected", LPAREN);
  1424         return args.toList();
  1427     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1428         int pos = token.pos;
  1429         List<JCExpression> args = arguments();
  1430         return toP(F.at(pos).Apply(typeArgs, t, args));
  1433     /**  TypeArgumentsOpt = [ TypeArguments ]
  1434      */
  1435     JCExpression typeArgumentsOpt(JCExpression t) {
  1436         if (token.kind == LT &&
  1437             (mode & TYPE) != 0 &&
  1438             (mode & NOPARAMS) == 0) {
  1439             mode = TYPE;
  1440             checkGenerics();
  1441             return typeArguments(t, false);
  1442         } else {
  1443             return t;
  1446     List<JCExpression> typeArgumentsOpt() {
  1447         return typeArgumentsOpt(TYPE);
  1450     List<JCExpression> typeArgumentsOpt(int useMode) {
  1451         if (token.kind == LT) {
  1452             checkGenerics();
  1453             if ((mode & useMode) == 0 ||
  1454                 (mode & NOPARAMS) != 0) {
  1455                 illegal();
  1457             mode = useMode;
  1458             return typeArguments(false);
  1460         return null;
  1463     /**
  1464      *  {@literal
  1465      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1466      *  }
  1467      */
  1468     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1469         if (token.kind == LT) {
  1470             nextToken();
  1471             if (token.kind == GT && diamondAllowed) {
  1472                 checkDiamond();
  1473                 mode |= DIAMOND;
  1474                 nextToken();
  1475                 return List.nil();
  1476             } else {
  1477                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1478                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1479                 while (token.kind == COMMA) {
  1480                     nextToken();
  1481                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1483                 switch (token.kind) {
  1485                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1486                 case GTGTGT: case GTGT:
  1487                     token = S.split();
  1488                     break;
  1489                 case GT:
  1490                     nextToken();
  1491                     break;
  1492                 default:
  1493                     args.append(syntaxError(token.pos, "expected", GT));
  1494                     break;
  1496                 return args.toList();
  1498         } else {
  1499             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1503     /**
  1504      *  {@literal
  1505      *  TypeArgument = Type
  1506      *               | "?"
  1507      *               | "?" EXTENDS Type {"&" Type}
  1508      *               | "?" SUPER Type
  1509      *  }
  1510      */
  1511     JCExpression typeArgument() {
  1512         if (token.kind != QUES) return parseType();
  1513         int pos = token.pos;
  1514         nextToken();
  1515         if (token.kind == EXTENDS) {
  1516             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1517             nextToken();
  1518             JCExpression bound = parseType();
  1519             return F.at(pos).Wildcard(t, bound);
  1520         } else if (token.kind == SUPER) {
  1521             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1522             nextToken();
  1523             JCExpression bound = parseType();
  1524             return F.at(pos).Wildcard(t, bound);
  1525         } else if (token.kind == IDENTIFIER) {
  1526             //error recovery
  1527             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1528             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1529             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1530             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1531             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1532             return err;
  1533         } else {
  1534             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1535             return toP(F.at(pos).Wildcard(t, null));
  1539     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1540         int pos = token.pos;
  1541         List<JCExpression> args = typeArguments(diamondAllowed);
  1542         return toP(F.at(pos).TypeApply(t, args));
  1545     /** BracketsOpt = {"[" "]"}
  1546      */
  1547     private JCExpression bracketsOpt(JCExpression t) {
  1548         if (token.kind == LBRACKET) {
  1549             int pos = token.pos;
  1550             nextToken();
  1551             t = bracketsOptCont(t, pos);
  1552             F.at(pos);
  1554         return t;
  1557     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1558         accept(RBRACKET);
  1559         t = bracketsOpt(t);
  1560         return toP(F.at(pos).TypeArray(t));
  1563     /** BracketsSuffixExpr = "." CLASS
  1564      *  BracketsSuffixType =
  1565      */
  1566     JCExpression bracketsSuffix(JCExpression t) {
  1567         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1568             mode = EXPR;
  1569             int pos = token.pos;
  1570             nextToken();
  1571             accept(CLASS);
  1572             if (token.pos == endPosTable.errorEndPos) {
  1573                 // error recovery
  1574                 Name name = null;
  1575                 if (token.kind == IDENTIFIER) {
  1576                     name = token.name();
  1577                     nextToken();
  1578                 } else {
  1579                     name = names.error;
  1581                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1582             } else {
  1583                 t = toP(F.at(pos).Select(t, names._class));
  1585         } else if ((mode & TYPE) != 0) {
  1586             mode = TYPE;
  1587         } else {
  1588             syntaxError(token.pos, "dot.class.expected");
  1590         return t;
  1593     /**
  1594      * MemberReferenceSuffix = "#" [TypeArguments] Ident
  1595      *                       | "#" [TypeArguments] "new"
  1596      */
  1597     JCExpression memberReferenceSuffix(JCExpression t) {
  1598         int pos1 = token.pos;
  1599         accept(HASH);
  1600         return memberReferenceSuffix(pos1, t);
  1603     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1604         checkMethodReferences();
  1605         mode = EXPR;
  1606         List<JCExpression> typeArgs = null;
  1607         if (token.kind == LT) {
  1608             typeArgs = typeArguments(false);
  1610         Name refName = null;
  1611         ReferenceMode refMode = null;
  1612         if (token.kind == NEW) {
  1613             refMode = ReferenceMode.NEW;
  1614             refName = names.init;
  1615             nextToken();
  1616         } else {
  1617             refMode = ReferenceMode.INVOKE;
  1618             refName = ident();
  1620         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  1623     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1624      */
  1625     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1626         switch (token.kind) {
  1627         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1628         case DOUBLE: case BOOLEAN:
  1629             if (typeArgs == null)
  1630                 return arrayCreatorRest(newpos, basicType());
  1631             break;
  1632         default:
  1634         JCExpression t = qualident();
  1635         int oldmode = mode;
  1636         mode = TYPE;
  1637         boolean diamondFound = false;
  1638         int lastTypeargsPos = -1;
  1639         if (token.kind == LT) {
  1640             checkGenerics();
  1641             lastTypeargsPos = token.pos;
  1642             t = typeArguments(t, true);
  1643             diamondFound = (mode & DIAMOND) != 0;
  1645         while (token.kind == DOT) {
  1646             if (diamondFound) {
  1647                 //cannot select after a diamond
  1648                 illegal();
  1650             int pos = token.pos;
  1651             nextToken();
  1652             t = toP(F.at(pos).Select(t, ident()));
  1653             if (token.kind == LT) {
  1654                 lastTypeargsPos = token.pos;
  1655                 checkGenerics();
  1656                 t = typeArguments(t, true);
  1657                 diamondFound = (mode & DIAMOND) != 0;
  1660         mode = oldmode;
  1661         if (token.kind == LBRACKET) {
  1662             JCExpression e = arrayCreatorRest(newpos, t);
  1663             if (diamondFound) {
  1664                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1665                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1667             else if (typeArgs != null) {
  1668                 int pos = newpos;
  1669                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1670                     // note: this should always happen but we should
  1671                     // not rely on this as the parser is continuously
  1672                     // modified to improve error recovery.
  1673                     pos = typeArgs.head.pos;
  1675                 setErrorEndPos(S.prevToken().endPos);
  1676                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1677                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1678                 return toP(err);
  1680             return e;
  1681         } else if (token.kind == LPAREN) {
  1682             return classCreatorRest(newpos, null, typeArgs, t);
  1683         } else {
  1684             setErrorEndPos(token.pos);
  1685             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1686             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1687             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1691     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1692      */
  1693     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1694         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1695         if (token.kind == LT) {
  1696             int oldmode = mode;
  1697             checkGenerics();
  1698             t = typeArguments(t, true);
  1699             mode = oldmode;
  1701         return classCreatorRest(newpos, encl, typeArgs, t);
  1704     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1705      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1706      */
  1707     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1708         accept(LBRACKET);
  1709         if (token.kind == RBRACKET) {
  1710             accept(RBRACKET);
  1711             elemtype = bracketsOpt(elemtype);
  1712             if (token.kind == LBRACE) {
  1713                 return arrayInitializer(newpos, elemtype);
  1714             } else {
  1715                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1716                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1718         } else {
  1719             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1720             dims.append(parseExpression());
  1721             accept(RBRACKET);
  1722             while (token.kind == LBRACKET) {
  1723                 int pos = token.pos;
  1724                 nextToken();
  1725                 if (token.kind == RBRACKET) {
  1726                     elemtype = bracketsOptCont(elemtype, pos);
  1727                 } else {
  1728                     dims.append(parseExpression());
  1729                     accept(RBRACKET);
  1732             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1736     /** ClassCreatorRest = Arguments [ClassBody]
  1737      */
  1738     JCNewClass classCreatorRest(int newpos,
  1739                                   JCExpression encl,
  1740                                   List<JCExpression> typeArgs,
  1741                                   JCExpression t)
  1743         List<JCExpression> args = arguments();
  1744         JCClassDecl body = null;
  1745         if (token.kind == LBRACE) {
  1746             int pos = token.pos;
  1747             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1748             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1749             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1751         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1754     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1755      */
  1756     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1757         accept(LBRACE);
  1758         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1759         if (token.kind == COMMA) {
  1760             nextToken();
  1761         } else if (token.kind != RBRACE) {
  1762             elems.append(variableInitializer());
  1763             while (token.kind == COMMA) {
  1764                 nextToken();
  1765                 if (token.kind == RBRACE) break;
  1766                 elems.append(variableInitializer());
  1769         accept(RBRACE);
  1770         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1773     /** VariableInitializer = ArrayInitializer | Expression
  1774      */
  1775     public JCExpression variableInitializer() {
  1776         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1779     /** ParExpression = "(" Expression ")"
  1780      */
  1781     JCExpression parExpression() {
  1782         int pos = token.pos;
  1783         accept(LPAREN);
  1784         JCExpression t = parseExpression();
  1785         accept(RPAREN);
  1786         return toP(F.at(pos).Parens(t));
  1789     /** Block = "{" BlockStatements "}"
  1790      */
  1791     JCBlock block(int pos, long flags) {
  1792         accept(LBRACE);
  1793         List<JCStatement> stats = blockStatements();
  1794         JCBlock t = F.at(pos).Block(flags, stats);
  1795         while (token.kind == CASE || token.kind == DEFAULT) {
  1796             syntaxError("orphaned", token.kind);
  1797             switchBlockStatementGroups();
  1799         // the Block node has a field "endpos" for first char of last token, which is
  1800         // usually but not necessarily the last char of the last token.
  1801         t.endpos = token.pos;
  1802         accept(RBRACE);
  1803         return toP(t);
  1806     public JCBlock block() {
  1807         return block(token.pos, 0);
  1810     /** BlockStatements = { BlockStatement }
  1811      *  BlockStatement  = LocalVariableDeclarationStatement
  1812      *                  | ClassOrInterfaceOrEnumDeclaration
  1813      *                  | [Ident ":"] Statement
  1814      *  LocalVariableDeclarationStatement
  1815      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1816      */
  1817     @SuppressWarnings("fallthrough")
  1818     List<JCStatement> blockStatements() {
  1819         //todo: skip to anchor on error(?)
  1820         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1821         while (true) {
  1822             List<JCStatement> stat = blockStatement();
  1823             if (stat.isEmpty()) {
  1824                 return stats.toList();
  1825             } else {
  1826                 if (token.pos <= endPosTable.errorEndPos) {
  1827                     skip(false, true, true, true);
  1829                 stats.addAll(stat);
  1834     /*
  1835      * This method parses a statement treating it as a block, relaxing the
  1836      * JLS restrictions, allows us to parse more faulty code, doing so
  1837      * enables us to provide better and accurate diagnostics to the user.
  1838      */
  1839     JCStatement parseStatementAsBlock() {
  1840         int pos = token.pos;
  1841         List<JCStatement> stats = blockStatement();
  1842         if (stats.isEmpty()) {
  1843             JCErroneous e = F.at(pos).Erroneous();
  1844             error(e, "illegal.start.of.stmt");
  1845             return F.at(pos).Exec(e);
  1846         } else {
  1847             JCStatement first = stats.head;
  1848             String error = null;
  1849             switch (first.getTag()) {
  1850             case CLASSDEF:
  1851                 error = "class.not.allowed";
  1852                 break;
  1853             case VARDEF:
  1854                 error = "variable.not.allowed";
  1855                 break;
  1857             if (error != null) {
  1858                 error(first, error);
  1859                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  1860                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  1862             return first;
  1866     @SuppressWarnings("fallthrough")
  1867     List<JCStatement> blockStatement() {
  1868         //todo: skip to anchor on error(?)
  1869         int pos = token.pos;
  1870         switch (token.kind) {
  1871         case RBRACE: case CASE: case DEFAULT: case EOF:
  1872             return List.nil();
  1873         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1874         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1875         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1876             return List.of(parseStatement());
  1877         case MONKEYS_AT:
  1878         case FINAL: {
  1879             Comment dc = token.comment(CommentStyle.JAVADOC);
  1880             JCModifiers mods = modifiersOpt();
  1881             if (token.kind == INTERFACE ||
  1882                 token.kind == CLASS ||
  1883                 allowEnums && token.kind == ENUM) {
  1884                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1885             } else {
  1886                 JCExpression t = parseType();
  1887                 ListBuffer<JCStatement> stats =
  1888                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1889                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1890                 storeEnd(stats.elems.last(), token.endPos);
  1891                 accept(SEMI);
  1892                 return stats.toList();
  1895         case ABSTRACT: case STRICTFP: {
  1896             Comment dc = token.comment(CommentStyle.JAVADOC);
  1897             JCModifiers mods = modifiersOpt();
  1898             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1900         case INTERFACE:
  1901         case CLASS:
  1902             Comment dc = token.comment(CommentStyle.JAVADOC);
  1903             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1904         case ENUM:
  1905         case ASSERT:
  1906             if (allowEnums && token.kind == ENUM) {
  1907                 error(token.pos, "local.enum");
  1908                 dc = token.comment(CommentStyle.JAVADOC);
  1909                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1910             } else if (allowAsserts && token.kind == ASSERT) {
  1911                 return List.of(parseStatement());
  1913             /* fall through to default */
  1914         default:
  1915             Token prevToken = token;
  1916             JCExpression t = term(EXPR | TYPE);
  1917             if (token.kind == COLON && t.hasTag(IDENT)) {
  1918                 nextToken();
  1919                 JCStatement stat = parseStatement();
  1920                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  1921             } else if ((lastmode & TYPE) != 0 &&
  1922                        (token.kind == IDENTIFIER ||
  1923                         token.kind == ASSERT ||
  1924                         token.kind == ENUM)) {
  1925                 pos = token.pos;
  1926                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1927                 F.at(pos);
  1928                 ListBuffer<JCStatement> stats =
  1929                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1930                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1931                 storeEnd(stats.elems.last(), token.endPos);
  1932                 accept(SEMI);
  1933                 return stats.toList();
  1934             } else {
  1935                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1936                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  1937                 accept(SEMI);
  1938                 return List.<JCStatement>of(expr);
  1943     /** Statement =
  1944      *       Block
  1945      *     | IF ParExpression Statement [ELSE Statement]
  1946      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1947      *     | FOR "(" FormalParameter : Expression ")" Statement
  1948      *     | WHILE ParExpression Statement
  1949      *     | DO Statement WHILE ParExpression ";"
  1950      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1951      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  1952      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1953      *     | SYNCHRONIZED ParExpression Block
  1954      *     | RETURN [Expression] ";"
  1955      *     | THROW Expression ";"
  1956      *     | BREAK [Ident] ";"
  1957      *     | CONTINUE [Ident] ";"
  1958      *     | ASSERT Expression [ ":" Expression ] ";"
  1959      *     | ";"
  1960      *     | ExpressionStatement
  1961      *     | Ident ":" Statement
  1962      */
  1963     @SuppressWarnings("fallthrough")
  1964     public JCStatement parseStatement() {
  1965         int pos = token.pos;
  1966         switch (token.kind) {
  1967         case LBRACE:
  1968             return block();
  1969         case IF: {
  1970             nextToken();
  1971             JCExpression cond = parExpression();
  1972             JCStatement thenpart = parseStatementAsBlock();
  1973             JCStatement elsepart = null;
  1974             if (token.kind == ELSE) {
  1975                 nextToken();
  1976                 elsepart = parseStatementAsBlock();
  1978             return F.at(pos).If(cond, thenpart, elsepart);
  1980         case FOR: {
  1981             nextToken();
  1982             accept(LPAREN);
  1983             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  1984             if (inits.length() == 1 &&
  1985                 inits.head.hasTag(VARDEF) &&
  1986                 ((JCVariableDecl) inits.head).init == null &&
  1987                 token.kind == COLON) {
  1988                 checkForeach();
  1989                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1990                 accept(COLON);
  1991                 JCExpression expr = parseExpression();
  1992                 accept(RPAREN);
  1993                 JCStatement body = parseStatementAsBlock();
  1994                 return F.at(pos).ForeachLoop(var, expr, body);
  1995             } else {
  1996                 accept(SEMI);
  1997                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  1998                 accept(SEMI);
  1999                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2000                 accept(RPAREN);
  2001                 JCStatement body = parseStatementAsBlock();
  2002                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2005         case WHILE: {
  2006             nextToken();
  2007             JCExpression cond = parExpression();
  2008             JCStatement body = parseStatementAsBlock();
  2009             return F.at(pos).WhileLoop(cond, body);
  2011         case DO: {
  2012             nextToken();
  2013             JCStatement body = parseStatementAsBlock();
  2014             accept(WHILE);
  2015             JCExpression cond = parExpression();
  2016             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2017             accept(SEMI);
  2018             return t;
  2020         case TRY: {
  2021             nextToken();
  2022             List<JCTree> resources = List.<JCTree>nil();
  2023             if (token.kind == LPAREN) {
  2024                 checkTryWithResources();
  2025                 nextToken();
  2026                 resources = resources();
  2027                 accept(RPAREN);
  2029             JCBlock body = block();
  2030             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2031             JCBlock finalizer = null;
  2032             if (token.kind == CATCH || token.kind == FINALLY) {
  2033                 while (token.kind == CATCH) catchers.append(catchClause());
  2034                 if (token.kind == FINALLY) {
  2035                     nextToken();
  2036                     finalizer = block();
  2038             } else {
  2039                 if (allowTWR) {
  2040                     if (resources.isEmpty())
  2041                         error(pos, "try.without.catch.finally.or.resource.decls");
  2042                 } else
  2043                     error(pos, "try.without.catch.or.finally");
  2045             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2047         case SWITCH: {
  2048             nextToken();
  2049             JCExpression selector = parExpression();
  2050             accept(LBRACE);
  2051             List<JCCase> cases = switchBlockStatementGroups();
  2052             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2053             accept(RBRACE);
  2054             return t;
  2056         case SYNCHRONIZED: {
  2057             nextToken();
  2058             JCExpression lock = parExpression();
  2059             JCBlock body = block();
  2060             return F.at(pos).Synchronized(lock, body);
  2062         case RETURN: {
  2063             nextToken();
  2064             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2065             JCReturn t = to(F.at(pos).Return(result));
  2066             accept(SEMI);
  2067             return t;
  2069         case THROW: {
  2070             nextToken();
  2071             JCExpression exc = parseExpression();
  2072             JCThrow t = to(F.at(pos).Throw(exc));
  2073             accept(SEMI);
  2074             return t;
  2076         case BREAK: {
  2077             nextToken();
  2078             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2079             JCBreak t = to(F.at(pos).Break(label));
  2080             accept(SEMI);
  2081             return t;
  2083         case CONTINUE: {
  2084             nextToken();
  2085             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2086             JCContinue t =  to(F.at(pos).Continue(label));
  2087             accept(SEMI);
  2088             return t;
  2090         case SEMI:
  2091             nextToken();
  2092             return toP(F.at(pos).Skip());
  2093         case ELSE:
  2094             return toP(F.Exec(syntaxError("else.without.if")));
  2095         case FINALLY:
  2096             return toP(F.Exec(syntaxError("finally.without.try")));
  2097         case CATCH:
  2098             return toP(F.Exec(syntaxError("catch.without.try")));
  2099         case ASSERT: {
  2100             if (allowAsserts && token.kind == ASSERT) {
  2101                 nextToken();
  2102                 JCExpression assertion = parseExpression();
  2103                 JCExpression message = null;
  2104                 if (token.kind == COLON) {
  2105                     nextToken();
  2106                     message = parseExpression();
  2108                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2109                 accept(SEMI);
  2110                 return t;
  2112             /* else fall through to default case */
  2114         case ENUM:
  2115         default:
  2116             Token prevToken = token;
  2117             JCExpression expr = parseExpression();
  2118             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2119                 nextToken();
  2120                 JCStatement stat = parseStatement();
  2121                 return F.at(pos).Labelled(prevToken.name(), stat);
  2122             } else {
  2123                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2124                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2125                 accept(SEMI);
  2126                 return stat;
  2131     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2132      */
  2133     protected JCCatch catchClause() {
  2134         int pos = token.pos;
  2135         accept(CATCH);
  2136         accept(LPAREN);
  2137         JCModifiers mods = optFinal(Flags.PARAMETER);
  2138         List<JCExpression> catchTypes = catchTypes();
  2139         JCExpression paramType = catchTypes.size() > 1 ?
  2140                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2141                 catchTypes.head;
  2142         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2143         accept(RPAREN);
  2144         JCBlock body = block();
  2145         return F.at(pos).Catch(formal, body);
  2148     List<JCExpression> catchTypes() {
  2149         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2150         catchTypes.add(parseType());
  2151         while (token.kind == BAR) {
  2152             checkMulticatch();
  2153             nextToken();
  2154             catchTypes.add(qualident());
  2156         return catchTypes.toList();
  2159     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2160      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2161      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2162      */
  2163     List<JCCase> switchBlockStatementGroups() {
  2164         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2165         while (true) {
  2166             int pos = token.pos;
  2167             switch (token.kind) {
  2168             case CASE:
  2169             case DEFAULT:
  2170                 cases.append(switchBlockStatementGroup());
  2171                 break;
  2172             case RBRACE: case EOF:
  2173                 return cases.toList();
  2174             default:
  2175                 nextToken(); // to ensure progress
  2176                 syntaxError(pos, "expected3",
  2177                     CASE, DEFAULT, RBRACE);
  2182     protected JCCase switchBlockStatementGroup() {
  2183         int pos = token.pos;
  2184         List<JCStatement> stats;
  2185         JCCase c;
  2186         switch (token.kind) {
  2187         case CASE:
  2188             nextToken();
  2189             JCExpression pat = parseExpression();
  2190             accept(COLON);
  2191             stats = blockStatements();
  2192             c = F.at(pos).Case(pat, stats);
  2193             if (stats.isEmpty())
  2194                 storeEnd(c, S.prevToken().endPos);
  2195             return c;
  2196         case DEFAULT:
  2197             nextToken();
  2198             accept(COLON);
  2199             stats = blockStatements();
  2200             c = F.at(pos).Case(null, stats);
  2201             if (stats.isEmpty())
  2202                 storeEnd(c, S.prevToken().endPos);
  2203             return c;
  2205         throw new AssertionError("should not reach here");
  2208     /** MoreStatementExpressions = { COMMA StatementExpression }
  2209      */
  2210     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2211                                                                     JCExpression first,
  2212                                                                     T stats) {
  2213         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2214         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2215         while (token.kind == COMMA) {
  2216             nextToken();
  2217             pos = token.pos;
  2218             JCExpression t = parseExpression();
  2219             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2220             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2222         return stats;
  2225     /** ForInit = StatementExpression MoreStatementExpressions
  2226      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2227      */
  2228     List<JCStatement> forInit() {
  2229         ListBuffer<JCStatement> stats = lb();
  2230         int pos = token.pos;
  2231         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2232             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2233         } else {
  2234             JCExpression t = term(EXPR | TYPE);
  2235             if ((lastmode & TYPE) != 0 &&
  2236                 (token.kind == IDENTIFIER || token.kind == ASSERT ||
  2237                  token.kind == ENUM)) {
  2238                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2239             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2240                 error(pos, "bad.initializer", "for-loop");
  2241                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2242             } else {
  2243                 return moreStatementExpressions(pos, t, stats).toList();
  2248     /** ForUpdate = StatementExpression MoreStatementExpressions
  2249      */
  2250     List<JCExpressionStatement> forUpdate() {
  2251         return moreStatementExpressions(token.pos,
  2252                                         parseExpression(),
  2253                                         new ListBuffer<JCExpressionStatement>()).toList();
  2256     /** AnnotationsOpt = { '@' Annotation }
  2257      */
  2258     List<JCAnnotation> annotationsOpt() {
  2259         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2260         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2261         while (token.kind == MONKEYS_AT) {
  2262             int pos = token.pos;
  2263             nextToken();
  2264             buf.append(annotation(pos));
  2266         return buf.toList();
  2269     /** ModifiersOpt = { Modifier }
  2270      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2271      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2272      *           | "@" Annotation
  2273      */
  2274     JCModifiers modifiersOpt() {
  2275         return modifiersOpt(null);
  2277     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2278         long flags;
  2279         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2280         int pos;
  2281         if (partial == null) {
  2282             flags = 0;
  2283             pos = token.pos;
  2284         } else {
  2285             flags = partial.flags;
  2286             annotations.appendList(partial.annotations);
  2287             pos = partial.pos;
  2289         if (token.deprecatedFlag()) {
  2290             flags |= Flags.DEPRECATED;
  2292         int lastPos = Position.NOPOS;
  2293     loop:
  2294         while (true) {
  2295             long flag;
  2296             switch (token.kind) {
  2297             case PRIVATE     : flag = Flags.PRIVATE; break;
  2298             case PROTECTED   : flag = Flags.PROTECTED; break;
  2299             case PUBLIC      : flag = Flags.PUBLIC; break;
  2300             case STATIC      : flag = Flags.STATIC; break;
  2301             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2302             case FINAL       : flag = Flags.FINAL; break;
  2303             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2304             case NATIVE      : flag = Flags.NATIVE; break;
  2305             case VOLATILE    : flag = Flags.VOLATILE; break;
  2306             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2307             case STRICTFP    : flag = Flags.STRICTFP; break;
  2308             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2309             case ERROR       : flag = 0; nextToken(); break;
  2310             default: break loop;
  2312             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2313             lastPos = token.pos;
  2314             nextToken();
  2315             if (flag == Flags.ANNOTATION) {
  2316                 checkAnnotations();
  2317                 if (token.kind != INTERFACE) {
  2318                     JCAnnotation ann = annotation(lastPos);
  2319                     // if first modifier is an annotation, set pos to annotation's.
  2320                     if (flags == 0 && annotations.isEmpty())
  2321                         pos = ann.pos;
  2322                     annotations.append(ann);
  2323                     lastPos = ann.pos;
  2324                     flag = 0;
  2327             flags |= flag;
  2329         switch (token.kind) {
  2330         case ENUM: flags |= Flags.ENUM; break;
  2331         case INTERFACE: flags |= Flags.INTERFACE; break;
  2332         default: break;
  2335         /* A modifiers tree with no modifier tokens or annotations
  2336          * has no text position. */
  2337         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2338             pos = Position.NOPOS;
  2340         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2341         if (pos != Position.NOPOS)
  2342             storeEnd(mods, S.prevToken().endPos);
  2343         return mods;
  2346     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2347      * @param pos position of "@" token
  2348      */
  2349     JCAnnotation annotation(int pos) {
  2350         // accept(AT); // AT consumed by caller
  2351         checkAnnotations();
  2352         JCTree ident = qualident();
  2353         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2354         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2355         storeEnd(ann, S.prevToken().endPos);
  2356         return ann;
  2359     List<JCExpression> annotationFieldValuesOpt() {
  2360         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2363     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2364     List<JCExpression> annotationFieldValues() {
  2365         accept(LPAREN);
  2366         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2367         if (token.kind != RPAREN) {
  2368             buf.append(annotationFieldValue());
  2369             while (token.kind == COMMA) {
  2370                 nextToken();
  2371                 buf.append(annotationFieldValue());
  2374         accept(RPAREN);
  2375         return buf.toList();
  2378     /** AnnotationFieldValue    = AnnotationValue
  2379      *                          | Identifier "=" AnnotationValue
  2380      */
  2381     JCExpression annotationFieldValue() {
  2382         if (token.kind == IDENTIFIER) {
  2383             mode = EXPR;
  2384             JCExpression t1 = term1();
  2385             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2386                 int pos = token.pos;
  2387                 accept(EQ);
  2388                 JCExpression v = annotationValue();
  2389                 return toP(F.at(pos).Assign(t1, v));
  2390             } else {
  2391                 return t1;
  2394         return annotationValue();
  2397     /* AnnotationValue          = ConditionalExpression
  2398      *                          | Annotation
  2399      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2400      */
  2401     JCExpression annotationValue() {
  2402         int pos;
  2403         switch (token.kind) {
  2404         case MONKEYS_AT:
  2405             pos = token.pos;
  2406             nextToken();
  2407             return annotation(pos);
  2408         case LBRACE:
  2409             pos = token.pos;
  2410             accept(LBRACE);
  2411             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2412             if (token.kind != RBRACE) {
  2413                 buf.append(annotationValue());
  2414                 while (token.kind == COMMA) {
  2415                     nextToken();
  2416                     if (token.kind == RBRACE) break;
  2417                     buf.append(annotationValue());
  2420             accept(RBRACE);
  2421             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2422         default:
  2423             mode = EXPR;
  2424             return term1();
  2428     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2429      */
  2430     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2431                                                                          JCExpression type,
  2432                                                                          T vdefs)
  2434         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2437     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2438      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2440      *  @param reqInit  Is an initializer always required?
  2441      *  @param dc       The documentation comment for the variable declarations, or null.
  2442      */
  2443     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2444                                                                      JCModifiers mods,
  2445                                                                      JCExpression type,
  2446                                                                      Name name,
  2447                                                                      boolean reqInit,
  2448                                                                      Comment dc,
  2449                                                                      T vdefs)
  2451         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2452         while (token.kind == COMMA) {
  2453             // All but last of multiple declarators subsume a comma
  2454             storeEnd((JCTree)vdefs.elems.last(), token.endPos);
  2455             nextToken();
  2456             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2458         return vdefs;
  2461     /** VariableDeclarator = Ident VariableDeclaratorRest
  2462      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2463      */
  2464     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2465         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2468     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2469      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2471      *  @param reqInit  Is an initializer always required?
  2472      *  @param dc       The documentation comment for the variable declarations, or null.
  2473      */
  2474     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2475                                   boolean reqInit, Comment dc) {
  2476         type = bracketsOpt(type);
  2477         JCExpression init = null;
  2478         if (token.kind == EQ) {
  2479             nextToken();
  2480             init = variableInitializer();
  2482         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2483         JCVariableDecl result =
  2484             toP(F.at(pos).VarDef(mods, name, type, init));
  2485         attach(result, dc);
  2486         return result;
  2489     /** VariableDeclaratorId = Ident BracketsOpt
  2490      */
  2491     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2492         int pos = token.pos;
  2493         Name name = ident();
  2494         if ((mods.flags & Flags.VARARGS) != 0 &&
  2495                 token.kind == LBRACKET) {
  2496             log.error(token.pos, "varargs.and.old.array.syntax");
  2498         type = bracketsOpt(type);
  2499         return toP(F.at(pos).VarDef(mods, name, type, null));
  2502     /** Resources = Resource { ";" Resources }
  2503      */
  2504     List<JCTree> resources() {
  2505         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2506         defs.append(resource());
  2507         while (token.kind == SEMI) {
  2508             // All but last of multiple declarators must subsume a semicolon
  2509             storeEnd(defs.elems.last(), token.endPos);
  2510             int semiColonPos = token.pos;
  2511             nextToken();
  2512             if (token.kind == RPAREN) { // Optional trailing semicolon
  2513                                        // after last resource
  2514                 break;
  2516             defs.append(resource());
  2518         return defs.toList();
  2521     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2522      */
  2523     protected JCTree resource() {
  2524         JCModifiers optFinal = optFinal(Flags.FINAL);
  2525         JCExpression type = parseType();
  2526         int pos = token.pos;
  2527         Name ident = ident();
  2528         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2531     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2532      */
  2533     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2534         Token firstToken = token;
  2535         JCExpression pid = null;
  2536         JCModifiers mods = null;
  2537         boolean consumedToplevelDoc = false;
  2538         boolean seenImport = false;
  2539         boolean seenPackage = false;
  2540         List<JCAnnotation> packageAnnotations = List.nil();
  2541         if (token.kind == MONKEYS_AT)
  2542             mods = modifiersOpt();
  2544         if (token.kind == PACKAGE) {
  2545             seenPackage = true;
  2546             if (mods != null) {
  2547                 checkNoMods(mods.flags);
  2548                 packageAnnotations = mods.annotations;
  2549                 mods = null;
  2551             nextToken();
  2552             pid = qualident();
  2553             accept(SEMI);
  2555         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2556         boolean checkForImports = true;
  2557         boolean firstTypeDecl = true;
  2558         while (token.kind != EOF) {
  2559             if (token.pos <= endPosTable.errorEndPos) {
  2560                 // error recovery
  2561                 skip(checkForImports, false, false, false);
  2562                 if (token.kind == EOF)
  2563                     break;
  2565             if (checkForImports && mods == null && token.kind == IMPORT) {
  2566                 seenImport = true;
  2567                 defs.append(importDeclaration());
  2568             } else {
  2569                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  2570                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2571                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2572                     consumedToplevelDoc = true;
  2574                 JCTree def = typeDeclaration(mods, docComment);
  2575                 if (def instanceof JCExpressionStatement)
  2576                     def = ((JCExpressionStatement)def).expr;
  2577                 defs.append(def);
  2578                 if (def instanceof JCClassDecl)
  2579                     checkForImports = false;
  2580                 mods = null;
  2581                 firstTypeDecl = false;
  2584         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2585         if (!consumedToplevelDoc)
  2586             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2587         if (defs.elems.isEmpty())
  2588             storeEnd(toplevel, S.prevToken().endPos);
  2589         if (keepDocComments)
  2590             toplevel.docComments = docComments;
  2591         if (keepLineMap)
  2592             toplevel.lineMap = S.getLineMap();
  2593         toplevel.endPositions = this.endPosTable;
  2594         return toplevel;
  2597     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2598      */
  2599     JCTree importDeclaration() {
  2600         int pos = token.pos;
  2601         nextToken();
  2602         boolean importStatic = false;
  2603         if (token.kind == STATIC) {
  2604             checkStaticImports();
  2605             importStatic = true;
  2606             nextToken();
  2608         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2609         do {
  2610             int pos1 = token.pos;
  2611             accept(DOT);
  2612             if (token.kind == STAR) {
  2613                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2614                 nextToken();
  2615                 break;
  2616             } else {
  2617                 pid = toP(F.at(pos1).Select(pid, ident()));
  2619         } while (token.kind == DOT);
  2620         accept(SEMI);
  2621         return toP(F.at(pos).Import(pid, importStatic));
  2624     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2625      *                  | ";"
  2626      */
  2627     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  2628         int pos = token.pos;
  2629         if (mods == null && token.kind == SEMI) {
  2630             nextToken();
  2631             return toP(F.at(pos).Skip());
  2632         } else {
  2633             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2637     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2638      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2639      *  @param mods     Any modifiers starting the class or interface declaration
  2640      *  @param dc       The documentation comment for the class, or null.
  2641      */
  2642     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  2643         if (token.kind == CLASS) {
  2644             return classDeclaration(mods, dc);
  2645         } else if (token.kind == INTERFACE) {
  2646             return interfaceDeclaration(mods, dc);
  2647         } else if (allowEnums) {
  2648             if (token.kind == ENUM) {
  2649                 return enumDeclaration(mods, dc);
  2650             } else {
  2651                 int pos = token.pos;
  2652                 List<JCTree> errs;
  2653                 if (token.kind == IDENTIFIER) {
  2654                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2655                     setErrorEndPos(token.pos);
  2656                 } else {
  2657                     errs = List.<JCTree>of(mods);
  2659                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2660                                               CLASS, INTERFACE, ENUM)));
  2662         } else {
  2663             if (token.kind == ENUM) {
  2664                 error(token.pos, "enums.not.supported.in.source", source.name);
  2665                 allowEnums = true;
  2666                 return enumDeclaration(mods, dc);
  2668             int pos = token.pos;
  2669             List<JCTree> errs;
  2670             if (token.kind == IDENTIFIER) {
  2671                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2672                 setErrorEndPos(token.pos);
  2673             } else {
  2674                 errs = List.<JCTree>of(mods);
  2676             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2677                                           CLASS, INTERFACE)));
  2681     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2682      *                     [IMPLEMENTS TypeList] ClassBody
  2683      *  @param mods    The modifiers starting the class declaration
  2684      *  @param dc       The documentation comment for the class, or null.
  2685      */
  2686     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  2687         int pos = token.pos;
  2688         accept(CLASS);
  2689         Name name = ident();
  2691         List<JCTypeParameter> typarams = typeParametersOpt();
  2693         JCExpression extending = null;
  2694         if (token.kind == EXTENDS) {
  2695             nextToken();
  2696             extending = parseType();
  2698         List<JCExpression> implementing = List.nil();
  2699         if (token.kind == IMPLEMENTS) {
  2700             nextToken();
  2701             implementing = typeList();
  2703         List<JCTree> defs = classOrInterfaceBody(name, false);
  2704         JCClassDecl result = toP(F.at(pos).ClassDef(
  2705             mods, name, typarams, extending, implementing, defs));
  2706         attach(result, dc);
  2707         return result;
  2710     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2711      *                         [EXTENDS TypeList] InterfaceBody
  2712      *  @param mods    The modifiers starting the interface declaration
  2713      *  @param dc       The documentation comment for the interface, or null.
  2714      */
  2715     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  2716         int pos = token.pos;
  2717         accept(INTERFACE);
  2718         Name name = ident();
  2720         List<JCTypeParameter> typarams = typeParametersOpt();
  2722         List<JCExpression> extending = List.nil();
  2723         if (token.kind == EXTENDS) {
  2724             nextToken();
  2725             extending = typeList();
  2727         List<JCTree> defs = classOrInterfaceBody(name, true);
  2728         JCClassDecl result = toP(F.at(pos).ClassDef(
  2729             mods, name, typarams, null, extending, defs));
  2730         attach(result, dc);
  2731         return result;
  2734     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2735      *  @param mods    The modifiers starting the enum declaration
  2736      *  @param dc       The documentation comment for the enum, or null.
  2737      */
  2738     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  2739         int pos = token.pos;
  2740         accept(ENUM);
  2741         Name name = ident();
  2743         List<JCExpression> implementing = List.nil();
  2744         if (token.kind == IMPLEMENTS) {
  2745             nextToken();
  2746             implementing = typeList();
  2749         List<JCTree> defs = enumBody(name);
  2750         mods.flags |= Flags.ENUM;
  2751         JCClassDecl result = toP(F.at(pos).
  2752             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2753                 null, implementing, defs));
  2754         attach(result, dc);
  2755         return result;
  2758     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2759      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2760      */
  2761     List<JCTree> enumBody(Name enumName) {
  2762         accept(LBRACE);
  2763         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2764         if (token.kind == COMMA) {
  2765             nextToken();
  2766         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2767             defs.append(enumeratorDeclaration(enumName));
  2768             while (token.kind == COMMA) {
  2769                 nextToken();
  2770                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2771                 defs.append(enumeratorDeclaration(enumName));
  2773             if (token.kind != SEMI && token.kind != RBRACE) {
  2774                 defs.append(syntaxError(token.pos, "expected3",
  2775                                 COMMA, RBRACE, SEMI));
  2776                 nextToken();
  2779         if (token.kind == SEMI) {
  2780             nextToken();
  2781             while (token.kind != RBRACE && token.kind != EOF) {
  2782                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2783                                                                 false));
  2784                 if (token.pos <= endPosTable.errorEndPos) {
  2785                     // error recovery
  2786                    skip(false, true, true, false);
  2790         accept(RBRACE);
  2791         return defs.toList();
  2794     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2795      */
  2796     JCTree enumeratorDeclaration(Name enumName) {
  2797         Comment dc = token.comment(CommentStyle.JAVADOC);
  2798         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2799         if (token.deprecatedFlag()) {
  2800             flags |= Flags.DEPRECATED;
  2802         int pos = token.pos;
  2803         List<JCAnnotation> annotations = annotationsOpt();
  2804         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2805         List<JCExpression> typeArgs = typeArgumentsOpt();
  2806         int identPos = token.pos;
  2807         Name name = ident();
  2808         int createPos = token.pos;
  2809         List<JCExpression> args = (token.kind == LPAREN)
  2810             ? arguments() : List.<JCExpression>nil();
  2811         JCClassDecl body = null;
  2812         if (token.kind == LBRACE) {
  2813             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2814             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2815             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2817         if (args.isEmpty() && body == null)
  2818             createPos = identPos;
  2819         JCIdent ident = F.at(identPos).Ident(enumName);
  2820         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2821         if (createPos != identPos)
  2822             storeEnd(create, S.prevToken().endPos);
  2823         ident = F.at(identPos).Ident(enumName);
  2824         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2825         attach(result, dc);
  2826         return result;
  2829     /** TypeList = Type {"," Type}
  2830      */
  2831     List<JCExpression> typeList() {
  2832         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2833         ts.append(parseType());
  2834         while (token.kind == COMMA) {
  2835             nextToken();
  2836             ts.append(parseType());
  2838         return ts.toList();
  2841     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2842      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2843      */
  2844     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2845         accept(LBRACE);
  2846         if (token.pos <= endPosTable.errorEndPos) {
  2847             // error recovery
  2848             skip(false, true, false, false);
  2849             if (token.kind == LBRACE)
  2850                 nextToken();
  2852         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2853         while (token.kind != RBRACE && token.kind != EOF) {
  2854             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2855             if (token.pos <= endPosTable.errorEndPos) {
  2856                // error recovery
  2857                skip(false, true, true, false);
  2860         accept(RBRACE);
  2861         return defs.toList();
  2864     /** ClassBodyDeclaration =
  2865      *      ";"
  2866      *    | [STATIC] Block
  2867      *    | ModifiersOpt
  2868      *      ( Type Ident
  2869      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2870      *      | VOID Ident MethodDeclaratorRest
  2871      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2872      *      | Ident ConstructorDeclaratorRest
  2873      *      | TypeParameters Ident ConstructorDeclaratorRest
  2874      *      | ClassOrInterfaceOrEnumDeclaration
  2875      *      )
  2876      *  InterfaceBodyDeclaration =
  2877      *      ";"
  2878      *    | ModifiersOpt Type Ident
  2879      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2880      */
  2881     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2882         if (token.kind == SEMI) {
  2883             nextToken();
  2884             return List.<JCTree>nil();
  2885         } else {
  2886             Comment dc = token.comment(CommentStyle.JAVADOC);
  2887             int pos = token.pos;
  2888             JCModifiers mods = modifiersOpt();
  2889             if (token.kind == CLASS ||
  2890                 token.kind == INTERFACE ||
  2891                 allowEnums && token.kind == ENUM) {
  2892                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2893             } else if (token.kind == LBRACE && !isInterface &&
  2894                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2895                        mods.annotations.isEmpty()) {
  2896                 return List.<JCTree>of(block(pos, mods.flags));
  2897             } else {
  2898                 pos = token.pos;
  2899                 List<JCTypeParameter> typarams = typeParametersOpt();
  2900                 // if there are type parameters but no modifiers, save the start
  2901                 // position of the method in the modifiers.
  2902                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  2903                     mods.pos = pos;
  2904                     storeEnd(mods, pos);
  2906                 Token tk = token;
  2907                 pos = token.pos;
  2908                 JCExpression type;
  2909                 boolean isVoid = token.kind == VOID;
  2910                 if (isVoid) {
  2911                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2912                     nextToken();
  2913                 } else {
  2914                     type = parseType();
  2916                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  2917                     if (isInterface || tk.name() != className)
  2918                         error(pos, "invalid.meth.decl.ret.type.req");
  2919                     return List.of(methodDeclaratorRest(
  2920                         pos, mods, null, names.init, typarams,
  2921                         isInterface, true, dc));
  2922                 } else {
  2923                     pos = token.pos;
  2924                     Name name = ident();
  2925                     if (token.kind == LPAREN) {
  2926                         return List.of(methodDeclaratorRest(
  2927                             pos, mods, type, name, typarams,
  2928                             isInterface, isVoid, dc));
  2929                     } else if (!isVoid && typarams.isEmpty()) {
  2930                         List<JCTree> defs =
  2931                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2932                                                     new ListBuffer<JCTree>()).toList();
  2933                         storeEnd(defs.last(), token.endPos);
  2934                         accept(SEMI);
  2935                         return defs;
  2936                     } else {
  2937                         pos = token.pos;
  2938                         List<JCTree> err = isVoid
  2939                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2940                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2941                             : null;
  2942                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  2949     /** MethodDeclaratorRest =
  2950      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2951      *  VoidMethodDeclaratorRest =
  2952      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2953      *  InterfaceMethodDeclaratorRest =
  2954      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2955      *  VoidInterfaceMethodDeclaratorRest =
  2956      *      FormalParameters [THROWS TypeList] ";"
  2957      *  ConstructorDeclaratorRest =
  2958      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2959      */
  2960     protected JCTree methodDeclaratorRest(int pos,
  2961                               JCModifiers mods,
  2962                               JCExpression type,
  2963                               Name name,
  2964                               List<JCTypeParameter> typarams,
  2965                               boolean isInterface, boolean isVoid,
  2966                               Comment dc) {
  2967         List<JCVariableDecl> params = formalParameters();
  2968         if (!isVoid) type = bracketsOpt(type);
  2969         List<JCExpression> thrown = List.nil();
  2970         if (token.kind == THROWS) {
  2971             nextToken();
  2972             thrown = qualidentList();
  2974         JCBlock body = null;
  2975         JCExpression defaultValue;
  2976         if (token.kind == LBRACE) {
  2977             body = block();
  2978             defaultValue = null;
  2979         } else {
  2980             if (token.kind == DEFAULT) {
  2981                 accept(DEFAULT);
  2982                 defaultValue = annotationValue();
  2983             } else {
  2984                 defaultValue = null;
  2986             accept(SEMI);
  2987             if (token.pos <= endPosTable.errorEndPos) {
  2988                 // error recovery
  2989                 skip(false, true, false, false);
  2990                 if (token.kind == LBRACE) {
  2991                     body = block();
  2996         JCMethodDecl result =
  2997             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2998                                     params, thrown,
  2999                                     body, defaultValue));
  3000         attach(result, dc);
  3001         return result;
  3004     /** QualidentList = Qualident {"," Qualident}
  3005      */
  3006     List<JCExpression> qualidentList() {
  3007         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3008         ts.append(qualident());
  3009         while (token.kind == COMMA) {
  3010             nextToken();
  3011             ts.append(qualident());
  3013         return ts.toList();
  3016     /**
  3017      *  {@literal
  3018      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3019      *  }
  3020      */
  3021     List<JCTypeParameter> typeParametersOpt() {
  3022         if (token.kind == LT) {
  3023             checkGenerics();
  3024             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3025             nextToken();
  3026             typarams.append(typeParameter());
  3027             while (token.kind == COMMA) {
  3028                 nextToken();
  3029                 typarams.append(typeParameter());
  3031             accept(GT);
  3032             return typarams.toList();
  3033         } else {
  3034             return List.nil();
  3038     /**
  3039      *  {@literal
  3040      *  TypeParameter = TypeVariable [TypeParameterBound]
  3041      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3042      *  TypeVariable = Ident
  3043      *  }
  3044      */
  3045     JCTypeParameter typeParameter() {
  3046         int pos = token.pos;
  3047         Name name = ident();
  3048         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3049         if (token.kind == EXTENDS) {
  3050             nextToken();
  3051             bounds.append(parseType());
  3052             while (token.kind == AMP) {
  3053                 nextToken();
  3054                 bounds.append(parseType());
  3057         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  3060     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3061      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3062      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3063      */
  3064     List<JCVariableDecl> formalParameters() {
  3065         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3066         JCVariableDecl lastParam = null;
  3067         accept(LPAREN);
  3068         if (token.kind != RPAREN) {
  3069             params.append(lastParam = formalParameter());
  3070             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3071                 nextToken();
  3072                 params.append(lastParam = formalParameter());
  3075         accept(RPAREN);
  3076         return params.toList();
  3079     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3080         if (hasParens) {
  3081             accept(LPAREN);
  3083         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3084         if (token.kind != RPAREN && token.kind != ARROW) {
  3085             params.append(implicitParameter());
  3086             while (token.kind == COMMA) {
  3087                 nextToken();
  3088                 params.append(implicitParameter());
  3091         if (hasParens) {
  3092             accept(RPAREN);
  3094         return params.toList();
  3097     JCModifiers optFinal(long flags) {
  3098         JCModifiers mods = modifiersOpt();
  3099         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3100         mods.flags |= flags;
  3101         return mods;
  3104     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3105      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3106      */
  3107     protected JCVariableDecl formalParameter() {
  3108         JCModifiers mods = optFinal(Flags.PARAMETER);
  3109         JCExpression type = parseType();
  3110         if (token.kind == ELLIPSIS) {
  3111             checkVarargs();
  3112             mods.flags |= Flags.VARARGS;
  3113             type = to(F.at(token.pos).TypeArray(type));
  3114             nextToken();
  3116         return variableDeclaratorId(mods, type);
  3119     protected JCVariableDecl implicitParameter() {
  3120         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3121         return variableDeclaratorId(mods, null);
  3124 /* ---------- auxiliary methods -------------- */
  3126     void error(int pos, String key, Object ... args) {
  3127         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3130     void error(DiagnosticPosition pos, String key, Object ... args) {
  3131         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3134     void warning(int pos, String key, Object ... args) {
  3135         log.warning(pos, key, args);
  3138     /** Check that given tree is a legal expression statement.
  3139      */
  3140     protected JCExpression checkExprStat(JCExpression t) {
  3141         switch(t.getTag()) {
  3142         case PREINC: case PREDEC:
  3143         case POSTINC: case POSTDEC:
  3144         case ASSIGN:
  3145         case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
  3146         case SL_ASG: case SR_ASG: case USR_ASG:
  3147         case PLUS_ASG: case MINUS_ASG:
  3148         case MUL_ASG: case DIV_ASG: case MOD_ASG:
  3149         case APPLY: case NEWCLASS:
  3150         case ERRONEOUS:
  3151             return t;
  3152         default:
  3153             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3154             error(ret, "not.stmt");
  3155             return ret;
  3159     /** Return precedence of operator represented by token,
  3160      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3161      */
  3162     static int prec(TokenKind token) {
  3163         JCTree.Tag oc = optag(token);
  3164         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3167     /**
  3168      * Return the lesser of two positions, making allowance for either one
  3169      * being unset.
  3170      */
  3171     static int earlier(int pos1, int pos2) {
  3172         if (pos1 == Position.NOPOS)
  3173             return pos2;
  3174         if (pos2 == Position.NOPOS)
  3175             return pos1;
  3176         return (pos1 < pos2 ? pos1 : pos2);
  3179     /** Return operation tag of binary operator represented by token,
  3180      *  No_TAG if token is not a binary operator.
  3181      */
  3182     static JCTree.Tag optag(TokenKind token) {
  3183         switch (token) {
  3184         case BARBAR:
  3185             return OR;
  3186         case AMPAMP:
  3187             return AND;
  3188         case BAR:
  3189             return BITOR;
  3190         case BAREQ:
  3191             return BITOR_ASG;
  3192         case CARET:
  3193             return BITXOR;
  3194         case CARETEQ:
  3195             return BITXOR_ASG;
  3196         case AMP:
  3197             return BITAND;
  3198         case AMPEQ:
  3199             return BITAND_ASG;
  3200         case EQEQ:
  3201             return JCTree.Tag.EQ;
  3202         case BANGEQ:
  3203             return NE;
  3204         case LT:
  3205             return JCTree.Tag.LT;
  3206         case GT:
  3207             return JCTree.Tag.GT;
  3208         case LTEQ:
  3209             return LE;
  3210         case GTEQ:
  3211             return GE;
  3212         case LTLT:
  3213             return SL;
  3214         case LTLTEQ:
  3215             return SL_ASG;
  3216         case GTGT:
  3217             return SR;
  3218         case GTGTEQ:
  3219             return SR_ASG;
  3220         case GTGTGT:
  3221             return USR;
  3222         case GTGTGTEQ:
  3223             return USR_ASG;
  3224         case PLUS:
  3225             return JCTree.Tag.PLUS;
  3226         case PLUSEQ:
  3227             return PLUS_ASG;
  3228         case SUB:
  3229             return MINUS;
  3230         case SUBEQ:
  3231             return MINUS_ASG;
  3232         case STAR:
  3233             return MUL;
  3234         case STAREQ:
  3235             return MUL_ASG;
  3236         case SLASH:
  3237             return DIV;
  3238         case SLASHEQ:
  3239             return DIV_ASG;
  3240         case PERCENT:
  3241             return MOD;
  3242         case PERCENTEQ:
  3243             return MOD_ASG;
  3244         case INSTANCEOF:
  3245             return TYPETEST;
  3246         default:
  3247             return NO_TAG;
  3251     /** Return operation tag of unary operator represented by token,
  3252      *  No_TAG if token is not a binary operator.
  3253      */
  3254     static JCTree.Tag unoptag(TokenKind token) {
  3255         switch (token) {
  3256         case PLUS:
  3257             return POS;
  3258         case SUB:
  3259             return NEG;
  3260         case BANG:
  3261             return NOT;
  3262         case TILDE:
  3263             return COMPL;
  3264         case PLUSPLUS:
  3265             return PREINC;
  3266         case SUBSUB:
  3267             return PREDEC;
  3268         default:
  3269             return NO_TAG;
  3273     /** Return type tag of basic type represented by token,
  3274      *  -1 if token is not a basic type identifier.
  3275      */
  3276     static int typetag(TokenKind token) {
  3277         switch (token) {
  3278         case BYTE:
  3279             return TypeTags.BYTE;
  3280         case CHAR:
  3281             return TypeTags.CHAR;
  3282         case SHORT:
  3283             return TypeTags.SHORT;
  3284         case INT:
  3285             return TypeTags.INT;
  3286         case LONG:
  3287             return TypeTags.LONG;
  3288         case FLOAT:
  3289             return TypeTags.FLOAT;
  3290         case DOUBLE:
  3291             return TypeTags.DOUBLE;
  3292         case BOOLEAN:
  3293             return TypeTags.BOOLEAN;
  3294         default:
  3295             return -1;
  3299     void checkGenerics() {
  3300         if (!allowGenerics) {
  3301             error(token.pos, "generics.not.supported.in.source", source.name);
  3302             allowGenerics = true;
  3305     void checkVarargs() {
  3306         if (!allowVarargs) {
  3307             error(token.pos, "varargs.not.supported.in.source", source.name);
  3308             allowVarargs = true;
  3311     void checkForeach() {
  3312         if (!allowForeach) {
  3313             error(token.pos, "foreach.not.supported.in.source", source.name);
  3314             allowForeach = true;
  3317     void checkStaticImports() {
  3318         if (!allowStaticImport) {
  3319             error(token.pos, "static.import.not.supported.in.source", source.name);
  3320             allowStaticImport = true;
  3323     void checkAnnotations() {
  3324         if (!allowAnnotations) {
  3325             error(token.pos, "annotations.not.supported.in.source", source.name);
  3326             allowAnnotations = true;
  3329     void checkDiamond() {
  3330         if (!allowDiamond) {
  3331             error(token.pos, "diamond.not.supported.in.source", source.name);
  3332             allowDiamond = true;
  3335     void checkMulticatch() {
  3336         if (!allowMulticatch) {
  3337             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3338             allowMulticatch = true;
  3341     void checkTryWithResources() {
  3342         if (!allowTWR) {
  3343             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3344             allowTWR = true;
  3347     void checkLambda() {
  3348         if (!allowLambda) {
  3349             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3350             allowLambda = true;
  3353     void checkMethodReferences() {
  3354         if (!allowMethodReferences) {
  3355             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3356             allowMethodReferences = true;
  3360     /*
  3361      * a functional source tree and end position mappings
  3362      */
  3363     protected class SimpleEndPosTable extends AbstractEndPosTable {
  3365         private final Map<JCTree, Integer> endPosMap;
  3367         SimpleEndPosTable() {
  3368             endPosMap = new HashMap<JCTree, Integer>();
  3371         protected void storeEnd(JCTree tree, int endpos) {
  3372             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  3375         protected <T extends JCTree> T to(T t) {
  3376             storeEnd(t, token.endPos);
  3377             return t;
  3380         protected <T extends JCTree> T toP(T t) {
  3381             storeEnd(t, S.prevToken().endPos);
  3382             return t;
  3385         public int getEndPos(JCTree tree) {
  3386             Integer value = endPosMap.get(tree);
  3387             return (value == null) ? Position.NOPOS : value;
  3390         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3391             Integer pos = endPosMap.remove(oldTree);
  3392             if (pos != null) {
  3393                 endPosMap.put(newTree, pos);
  3394                 return pos;
  3396             return Position.NOPOS;
  3400     /*
  3401      * a default skeletal implementation without any mapping overhead.
  3402      */
  3403     protected class EmptyEndPosTable extends AbstractEndPosTable {
  3405         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  3407         protected <T extends JCTree> T to(T t) {
  3408             return t;
  3411         protected <T extends JCTree> T toP(T t) {
  3412             return t;
  3415         public int getEndPos(JCTree tree) {
  3416             return Position.NOPOS;
  3419         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3420             return Position.NOPOS;
  3425     protected abstract class AbstractEndPosTable implements EndPosTable {
  3427         /**
  3428          * Store the last error position.
  3429          */
  3430         protected int errorEndPos;
  3432         /**
  3433          * Store ending position for a tree, the value of which is the greater
  3434          * of last error position and the given ending position.
  3435          * @param tree   The tree.
  3436          * @param endpos The ending position to associate with the tree.
  3437          */
  3438         protected abstract void storeEnd(JCTree tree, int endpos);
  3440         /**
  3441          * Store current token's ending position for a tree, the value of which
  3442          * will be the greater of last error position and the ending position of
  3443          * the current token.
  3444          * @param t The tree.
  3445          */
  3446         protected abstract <T extends JCTree> T to(T t);
  3448         /**
  3449          * Store current token's ending position for a tree, the value of which
  3450          * will be the greater of last error position and the ending position of
  3451          * the previous token.
  3452          * @param t The tree.
  3453          */
  3454         protected abstract <T extends JCTree> T toP(T t);
  3456         /**
  3457          * Set the error position during the parsing phases, the value of which
  3458          * will be set only if it is greater than the last stored error position.
  3459          * @param errPos The error position
  3460          */
  3461         protected void setErrorEndPos(int errPos) {
  3462             if (errPos > errorEndPos) {
  3463                 errorEndPos = errPos;

mercurial