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

Mon, 21 Jan 2013 20:19:53 +0000

author
mcimadamore
date
Mon, 21 Jan 2013 20:19:53 +0000
changeset 1513
cf84b07a82db
parent 1511
c7c41a044e7c
child 1521
71f35e4b93a5
permissions
-rw-r--r--

8005166: Add support for static interface methods
Summary: Support public static interface methods
Reviewed-by: jjg

     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.tree.JCTree.Tag.*;
    51 import static com.sun.tools.javac.util.ListBuffer.lb;
    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     interface ErrorRecoveryAction {
    92         JCTree doRecover(JavacParser parser);
    93     }
    95     enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
    96         BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
    97         CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
    98     }
   100     /** Construct a parser from a given scanner, tree factory and log.
   101      */
   102     protected JavacParser(ParserFactory fac,
   103                      Lexer S,
   104                      boolean keepDocComments,
   105                      boolean keepLineMap,
   106                      boolean keepEndPositions) {
   107         this.S = S;
   108         nextToken(); // prime the pump
   109         this.F = fac.F;
   110         this.log = fac.log;
   111         this.names = fac.names;
   112         this.source = fac.source;
   113         this.allowGenerics = source.allowGenerics();
   114         this.allowVarargs = source.allowVarargs();
   115         this.allowAsserts = source.allowAsserts();
   116         this.allowEnums = source.allowEnums();
   117         this.allowForeach = source.allowForeach();
   118         this.allowStaticImport = source.allowStaticImport();
   119         this.allowAnnotations = source.allowAnnotations();
   120         this.allowTWR = source.allowTryWithResources();
   121         this.allowDiamond = source.allowDiamond();
   122         this.allowMulticatch = source.allowMulticatch();
   123         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   124         this.allowLambda = source.allowLambda();
   125         this.allowMethodReferences = source.allowMethodReferences();
   126         this.allowDefaultMethods = source.allowDefaultMethods();
   127         this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
   128         this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
   129         this.keepDocComments = keepDocComments;
   130         docComments = newDocCommentTable(keepDocComments, fac);
   131         this.keepLineMap = keepLineMap;
   132         this.errorTree = F.Erroneous();
   133         endPosTable = newEndPosTable(keepEndPositions);
   134     }
   136     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
   137         return  keepEndPositions
   138                 ? new SimpleEndPosTable()
   139                 : new EmptyEndPosTable();
   140     }
   142     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
   143         return keepDocComments ? new LazyDocCommentTable(fac) : null;
   144     }
   146     /** Switch: Should generics be recognized?
   147      */
   148     boolean allowGenerics;
   150     /** Switch: Should diamond operator be recognized?
   151      */
   152     boolean allowDiamond;
   154     /** Switch: Should multicatch clause be accepted?
   155      */
   156     boolean allowMulticatch;
   158     /** Switch: Should varargs be recognized?
   159      */
   160     boolean allowVarargs;
   162     /** Switch: should we recognize assert statements, or just give a warning?
   163      */
   164     boolean allowAsserts;
   166     /** Switch: should we recognize enums, or just give a warning?
   167      */
   168     boolean allowEnums;
   170     /** Switch: should we recognize foreach?
   171      */
   172     boolean allowForeach;
   174     /** Switch: should we recognize foreach?
   175      */
   176     boolean allowStaticImport;
   178     /** Switch: should we recognize annotations?
   179      */
   180     boolean allowAnnotations;
   182     /** Switch: should we recognize try-with-resources?
   183      */
   184     boolean allowTWR;
   186     /** Switch: should we fold strings?
   187      */
   188     boolean allowStringFolding;
   190     /** Switch: should we recognize lambda expressions?
   191      */
   192     boolean allowLambda;
   194     /** Switch: should we allow method/constructor references?
   195      */
   196     boolean allowMethodReferences;
   198     /** Switch: should we allow default methods in interfaces?
   199      */
   200     boolean allowDefaultMethods;
   202     /** Switch: should we allow static methods in interfaces?
   203      */
   204     boolean allowStaticInterfaceMethods;
   206     /** Switch: should we allow intersection types in cast?
   207      */
   208     boolean allowIntersectionTypesInCast;
   210     /** Switch: should we keep docComments?
   211      */
   212     boolean keepDocComments;
   214     /** Switch: should we keep line table?
   215      */
   216     boolean keepLineMap;
   218     /** When terms are parsed, the mode determines which is expected:
   219      *     mode = EXPR        : an expression
   220      *     mode = TYPE        : a type
   221      *     mode = NOPARAMS    : no parameters allowed for type
   222      *     mode = TYPEARG     : type argument
   223      */
   224     static final int EXPR = 0x1;
   225     static final int TYPE = 0x2;
   226     static final int NOPARAMS = 0x4;
   227     static final int TYPEARG = 0x8;
   228     static final int DIAMOND = 0x10;
   230     /** The current mode.
   231      */
   232     private int mode = 0;
   234     /** The mode of the term that was parsed last.
   235      */
   236     private int lastmode = 0;
   238     /* ---------- token management -------------- */
   240     protected Token token;
   242     public Token token() {
   243         return token;
   244     }
   246     public void nextToken() {
   247         S.nextToken();
   248         token = S.token();
   249     }
   251     protected boolean peekToken(Filter<TokenKind> tk) {
   252         return peekToken(0, tk);
   253     }
   255     protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
   256         return tk.accepts(S.token(lookahead + 1).kind);
   257     }
   259     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   260         return peekToken(0, tk1, tk2);
   261     }
   263     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   264         return tk1.accepts(S.token(lookahead + 1).kind) &&
   265                 tk2.accepts(S.token(lookahead + 2).kind);
   266     }
   268     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   269         return peekToken(0, tk1, tk2, tk3);
   270     }
   272     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   273         return tk1.accepts(S.token(lookahead + 1).kind) &&
   274                 tk2.accepts(S.token(lookahead + 2).kind) &&
   275                 tk3.accepts(S.token(lookahead + 3).kind);
   276     }
   278     @SuppressWarnings("unchecked")
   279     protected boolean peekToken(Filter<TokenKind>... kinds) {
   280         return peekToken(0, kinds);
   281     }
   283     @SuppressWarnings("unchecked")
   284     protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
   285         for (; lookahead < kinds.length ; lookahead++) {
   286             if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
   287                 return false;
   288             }
   289         }
   290         return true;
   291     }
   293     /* ---------- error recovery -------------- */
   295     private JCErroneous errorTree;
   297     /** Skip forward until a suitable stop token is found.
   298      */
   299     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   300          while (true) {
   301              switch (token.kind) {
   302                 case SEMI:
   303                     nextToken();
   304                     return;
   305                 case PUBLIC:
   306                 case FINAL:
   307                 case ABSTRACT:
   308                 case MONKEYS_AT:
   309                 case EOF:
   310                 case CLASS:
   311                 case INTERFACE:
   312                 case ENUM:
   313                     return;
   314                 case IMPORT:
   315                     if (stopAtImport)
   316                         return;
   317                     break;
   318                 case LBRACE:
   319                 case RBRACE:
   320                 case PRIVATE:
   321                 case PROTECTED:
   322                 case STATIC:
   323                 case TRANSIENT:
   324                 case NATIVE:
   325                 case VOLATILE:
   326                 case SYNCHRONIZED:
   327                 case STRICTFP:
   328                 case LT:
   329                 case BYTE:
   330                 case SHORT:
   331                 case CHAR:
   332                 case INT:
   333                 case LONG:
   334                 case FLOAT:
   335                 case DOUBLE:
   336                 case BOOLEAN:
   337                 case VOID:
   338                     if (stopAtMemberDecl)
   339                         return;
   340                     break;
   341                 case UNDERSCORE:
   342                 case IDENTIFIER:
   343                    if (stopAtIdentifier)
   344                         return;
   345                     break;
   346                 case CASE:
   347                 case DEFAULT:
   348                 case IF:
   349                 case FOR:
   350                 case WHILE:
   351                 case DO:
   352                 case TRY:
   353                 case SWITCH:
   354                 case RETURN:
   355                 case THROW:
   356                 case BREAK:
   357                 case CONTINUE:
   358                 case ELSE:
   359                 case FINALLY:
   360                 case CATCH:
   361                     if (stopAtStatement)
   362                         return;
   363                     break;
   364             }
   365             nextToken();
   366         }
   367     }
   369     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   370         return syntaxError(pos, List.<JCTree>nil(), key, args);
   371     }
   373     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   374         setErrorEndPos(pos);
   375         JCErroneous err = F.at(pos).Erroneous(errs);
   376         reportSyntaxError(err, key, (Object[])args);
   377         if (errs != null) {
   378             JCTree last = errs.last();
   379             if (last != null)
   380                 storeEnd(last, pos);
   381         }
   382         return toP(err);
   383     }
   385     private int errorPos = Position.NOPOS;
   387     /**
   388      * Report a syntax using the given the position parameter and arguments,
   389      * unless one was already reported at the same position.
   390      */
   391     private void reportSyntaxError(int pos, String key, Object... args) {
   392         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   393         reportSyntaxError(diag, key, args);
   394     }
   396     /**
   397      * Report a syntax error using the given DiagnosticPosition object and
   398      * arguments, unless one was already reported at the same position.
   399      */
   400     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   401         int pos = diagPos.getPreferredPosition();
   402         if (pos > S.errPos() || pos == Position.NOPOS) {
   403             if (token.kind == EOF) {
   404                 error(diagPos, "premature.eof");
   405             } else {
   406                 error(diagPos, key, args);
   407             }
   408         }
   409         S.errPos(pos);
   410         if (token.pos == errorPos)
   411             nextToken(); // guarantee progress
   412         errorPos = token.pos;
   413     }
   416     /** Generate a syntax error at current position unless one was already
   417      *  reported at the same position.
   418      */
   419     private JCErroneous syntaxError(String key) {
   420         return syntaxError(token.pos, key);
   421     }
   423     /** Generate a syntax error at current position unless one was
   424      *  already reported at the same position.
   425      */
   426     private JCErroneous syntaxError(String key, TokenKind arg) {
   427         return syntaxError(token.pos, key, arg);
   428     }
   430     /** If next input token matches given token, skip it, otherwise report
   431      *  an error.
   432      */
   433     public void accept(TokenKind tk) {
   434         if (token.kind == tk) {
   435             nextToken();
   436         } else {
   437             setErrorEndPos(token.pos);
   438             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   439         }
   440     }
   442     /** Report an illegal start of expression/type error at given position.
   443      */
   444     JCExpression illegal(int pos) {
   445         setErrorEndPos(pos);
   446         if ((mode & EXPR) != 0)
   447             return syntaxError(pos, "illegal.start.of.expr");
   448         else
   449             return syntaxError(pos, "illegal.start.of.type");
   451     }
   453     /** Report an illegal start of expression/type error at current position.
   454      */
   455     JCExpression illegal() {
   456         return illegal(token.pos);
   457     }
   459     /** Diagnose a modifier flag from the set, if any. */
   460     void checkNoMods(long mods) {
   461         if (mods != 0) {
   462             long lowestMod = mods & -mods;
   463             error(token.pos, "mod.not.allowed.here",
   464                       Flags.asFlagSet(lowestMod));
   465         }
   466     }
   468 /* ---------- doc comments --------- */
   470     /** A table to store all documentation comments
   471      *  indexed by the tree nodes they refer to.
   472      *  defined only if option flag keepDocComment is set.
   473      */
   474     private final DocCommentTable docComments;
   476     /** Make an entry into docComments hashtable,
   477      *  provided flag keepDocComments is set and given doc comment is non-null.
   478      *  @param tree   The tree to be used as index in the hashtable
   479      *  @param dc     The doc comment to associate with the tree, or null.
   480      */
   481     void attach(JCTree tree, Comment dc) {
   482         if (keepDocComments && dc != null) {
   483 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   484             docComments.putComment(tree, dc);
   485         }
   486     }
   488 /* -------- source positions ------- */
   490     private void setErrorEndPos(int errPos) {
   491         endPosTable.setErrorEndPos(errPos);
   492     }
   494     private void storeEnd(JCTree tree, int endpos) {
   495         endPosTable.storeEnd(tree, endpos);
   496     }
   498     private <T extends JCTree> T to(T t) {
   499         return endPosTable.to(t);
   500     }
   502     private <T extends JCTree> T toP(T t) {
   503         return endPosTable.toP(t);
   504     }
   506     /** Get the start position for a tree node.  The start position is
   507      * defined to be the position of the first character of the first
   508      * token of the node's source text.
   509      * @param tree  The tree node
   510      */
   511     public int getStartPos(JCTree tree) {
   512         return TreeInfo.getStartPos(tree);
   513     }
   515     /**
   516      * Get the end position for a tree node.  The end position is
   517      * defined to be the position of the last character of the last
   518      * token of the node's source text.  Returns Position.NOPOS if end
   519      * positions are not generated or the position is otherwise not
   520      * found.
   521      * @param tree  The tree node
   522      */
   523     public int getEndPos(JCTree tree) {
   524         return endPosTable.getEndPos(tree);
   525     }
   529 /* ---------- parsing -------------- */
   531     /**
   532      * Ident = IDENTIFIER
   533      */
   534     Name ident() {
   535         if (token.kind == IDENTIFIER) {
   536             Name name = token.name();
   537             nextToken();
   538             return name;
   539         } else if (token.kind == ASSERT) {
   540             if (allowAsserts) {
   541                 error(token.pos, "assert.as.identifier");
   542                 nextToken();
   543                 return names.error;
   544             } else {
   545                 warning(token.pos, "assert.as.identifier");
   546                 Name name = token.name();
   547                 nextToken();
   548                 return name;
   549             }
   550         } else if (token.kind == ENUM) {
   551             if (allowEnums) {
   552                 error(token.pos, "enum.as.identifier");
   553                 nextToken();
   554                 return names.error;
   555             } else {
   556                 warning(token.pos, "enum.as.identifier");
   557                 Name name = token.name();
   558                 nextToken();
   559                 return name;
   560             }
   561         } else if (token.kind == UNDERSCORE) {
   562             warning(token.pos, "underscore.as.identifier");
   563             Name name = token.name();
   564             nextToken();
   565             return name;
   566         } else {
   567             accept(IDENTIFIER);
   568             return names.error;
   569         }
   570     }
   572     /**
   573      * Qualident = Ident { DOT Ident }
   574      */
   575     public JCExpression qualident() {
   576         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   577         while (token.kind == DOT) {
   578             int pos = token.pos;
   579             nextToken();
   580             t = toP(F.at(pos).Select(t, ident()));
   581         }
   582         return t;
   583     }
   585     JCExpression literal(Name prefix) {
   586         return literal(prefix, token.pos);
   587     }
   589     /**
   590      * Literal =
   591      *     INTLITERAL
   592      *   | LONGLITERAL
   593      *   | FLOATLITERAL
   594      *   | DOUBLELITERAL
   595      *   | CHARLITERAL
   596      *   | STRINGLITERAL
   597      *   | TRUE
   598      *   | FALSE
   599      *   | NULL
   600      */
   601     JCExpression literal(Name prefix, int pos) {
   602         JCExpression t = errorTree;
   603         switch (token.kind) {
   604         case INTLITERAL:
   605             try {
   606                 t = F.at(pos).Literal(
   607                     TypeTag.INT,
   608                     Convert.string2int(strval(prefix), token.radix()));
   609             } catch (NumberFormatException ex) {
   610                 error(token.pos, "int.number.too.large", strval(prefix));
   611             }
   612             break;
   613         case LONGLITERAL:
   614             try {
   615                 t = F.at(pos).Literal(
   616                     TypeTag.LONG,
   617                     new Long(Convert.string2long(strval(prefix), token.radix())));
   618             } catch (NumberFormatException ex) {
   619                 error(token.pos, "int.number.too.large", strval(prefix));
   620             }
   621             break;
   622         case FLOATLITERAL: {
   623             String proper = token.radix() == 16 ?
   624                     ("0x"+ token.stringVal()) :
   625                     token.stringVal();
   626             Float n;
   627             try {
   628                 n = Float.valueOf(proper);
   629             } catch (NumberFormatException ex) {
   630                 // error already reported in scanner
   631                 n = Float.NaN;
   632             }
   633             if (n.floatValue() == 0.0f && !isZero(proper))
   634                 error(token.pos, "fp.number.too.small");
   635             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   636                 error(token.pos, "fp.number.too.large");
   637             else
   638                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
   639             break;
   640         }
   641         case DOUBLELITERAL: {
   642             String proper = token.radix() == 16 ?
   643                     ("0x"+ token.stringVal()) :
   644                     token.stringVal();
   645             Double n;
   646             try {
   647                 n = Double.valueOf(proper);
   648             } catch (NumberFormatException ex) {
   649                 // error already reported in scanner
   650                 n = Double.NaN;
   651             }
   652             if (n.doubleValue() == 0.0d && !isZero(proper))
   653                 error(token.pos, "fp.number.too.small");
   654             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   655                 error(token.pos, "fp.number.too.large");
   656             else
   657                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
   658             break;
   659         }
   660         case CHARLITERAL:
   661             t = F.at(pos).Literal(
   662                 TypeTag.CHAR,
   663                 token.stringVal().charAt(0) + 0);
   664             break;
   665         case STRINGLITERAL:
   666             t = F.at(pos).Literal(
   667                 TypeTag.CLASS,
   668                 token.stringVal());
   669             break;
   670         case TRUE: case FALSE:
   671             t = F.at(pos).Literal(
   672                 TypeTag.BOOLEAN,
   673                 (token.kind == TRUE ? 1 : 0));
   674             break;
   675         case NULL:
   676             t = F.at(pos).Literal(
   677                 TypeTag.BOT,
   678                 null);
   679             break;
   680         default:
   681             Assert.error();
   682         }
   683         if (t == errorTree)
   684             t = F.at(pos).Erroneous();
   685         storeEnd(t, token.endPos);
   686         nextToken();
   687         return t;
   688     }
   689 //where
   690         boolean isZero(String s) {
   691             char[] cs = s.toCharArray();
   692             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   693             int i = ((base==16) ? 2 : 0);
   694             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   695             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   696         }
   698         String strval(Name prefix) {
   699             String s = token.stringVal();
   700             return prefix.isEmpty() ? s : prefix + s;
   701         }
   703     /** terms can be either expressions or types.
   704      */
   705     public JCExpression parseExpression() {
   706         return term(EXPR);
   707     }
   709     public JCExpression parseType() {
   710         return term(TYPE);
   711     }
   713     JCExpression term(int newmode) {
   714         int prevmode = mode;
   715         mode = newmode;
   716         JCExpression t = term();
   717         lastmode = mode;
   718         mode = prevmode;
   719         return t;
   720     }
   722     /**
   723      *  {@literal
   724      *  Expression = Expression1 [ExpressionRest]
   725      *  ExpressionRest = [AssignmentOperator Expression1]
   726      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   727      *                       "&=" | "|=" | "^=" |
   728      *                       "%=" | "<<=" | ">>=" | ">>>="
   729      *  Type = Type1
   730      *  TypeNoParams = TypeNoParams1
   731      *  StatementExpression = Expression
   732      *  ConstantExpression = Expression
   733      *  }
   734      */
   735     JCExpression term() {
   736         JCExpression t = term1();
   737         if ((mode & EXPR) != 0 &&
   738             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   739             return termRest(t);
   740         else
   741             return t;
   742     }
   744     JCExpression termRest(JCExpression t) {
   745         switch (token.kind) {
   746         case EQ: {
   747             int pos = token.pos;
   748             nextToken();
   749             mode = EXPR;
   750             JCExpression t1 = term();
   751             return toP(F.at(pos).Assign(t, t1));
   752         }
   753         case PLUSEQ:
   754         case SUBEQ:
   755         case STAREQ:
   756         case SLASHEQ:
   757         case PERCENTEQ:
   758         case AMPEQ:
   759         case BAREQ:
   760         case CARETEQ:
   761         case LTLTEQ:
   762         case GTGTEQ:
   763         case GTGTGTEQ:
   764             int pos = token.pos;
   765             TokenKind tk = token.kind;
   766             nextToken();
   767             mode = EXPR;
   768             JCExpression t1 = term();
   769             return F.at(pos).Assignop(optag(tk), t, t1);
   770         default:
   771             return t;
   772         }
   773     }
   775     /** Expression1   = Expression2 [Expression1Rest]
   776      *  Type1         = Type2
   777      *  TypeNoParams1 = TypeNoParams2
   778      */
   779     JCExpression term1() {
   780         JCExpression t = term2();
   781         if ((mode & EXPR) != 0 && token.kind == QUES) {
   782             mode = EXPR;
   783             return term1Rest(t);
   784         } else {
   785             return t;
   786         }
   787     }
   789     /** Expression1Rest = ["?" Expression ":" Expression1]
   790      */
   791     JCExpression term1Rest(JCExpression t) {
   792         if (token.kind == QUES) {
   793             int pos = token.pos;
   794             nextToken();
   795             JCExpression t1 = term();
   796             accept(COLON);
   797             JCExpression t2 = term1();
   798             return F.at(pos).Conditional(t, t1, t2);
   799         } else {
   800             return t;
   801         }
   802     }
   804     /** Expression2   = Expression3 [Expression2Rest]
   805      *  Type2         = Type3
   806      *  TypeNoParams2 = TypeNoParams3
   807      */
   808     JCExpression term2() {
   809         JCExpression t = term3();
   810         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   811             mode = EXPR;
   812             return term2Rest(t, TreeInfo.orPrec);
   813         } else {
   814             return t;
   815         }
   816     }
   818     /*  Expression2Rest = {infixop Expression3}
   819      *                  | Expression3 instanceof Type
   820      *  infixop         = "||"
   821      *                  | "&&"
   822      *                  | "|"
   823      *                  | "^"
   824      *                  | "&"
   825      *                  | "==" | "!="
   826      *                  | "<" | ">" | "<=" | ">="
   827      *                  | "<<" | ">>" | ">>>"
   828      *                  | "+" | "-"
   829      *                  | "*" | "/" | "%"
   830      */
   831     JCExpression term2Rest(JCExpression t, int minprec) {
   832         JCExpression[] odStack = newOdStack();
   833         Token[] opStack = newOpStack();
   835         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   836         int top = 0;
   837         odStack[0] = t;
   838         int startPos = token.pos;
   839         Token topOp = Tokens.DUMMY;
   840         while (prec(token.kind) >= minprec) {
   841             opStack[top] = topOp;
   842             top++;
   843             topOp = token;
   844             nextToken();
   845             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   846             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   847                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   848                                         odStack[top]);
   849                 top--;
   850                 topOp = opStack[top];
   851             }
   852         }
   853         Assert.check(top == 0);
   854         t = odStack[0];
   856         if (t.hasTag(JCTree.Tag.PLUS)) {
   857             StringBuilder buf = foldStrings(t);
   858             if (buf != null) {
   859                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
   860             }
   861         }
   863         odStackSupply.add(odStack);
   864         opStackSupply.add(opStack);
   865         return t;
   866     }
   867 //where
   868         /** Construct a binary or type test node.
   869          */
   870         private JCExpression makeOp(int pos,
   871                                     TokenKind topOp,
   872                                     JCExpression od1,
   873                                     JCExpression od2)
   874         {
   875             if (topOp == INSTANCEOF) {
   876                 return F.at(pos).TypeTest(od1, od2);
   877             } else {
   878                 return F.at(pos).Binary(optag(topOp), od1, od2);
   879             }
   880         }
   881         /** If tree is a concatenation of string literals, replace it
   882          *  by a single literal representing the concatenated string.
   883          */
   884         protected StringBuilder foldStrings(JCTree tree) {
   885             if (!allowStringFolding)
   886                 return null;
   887             List<String> buf = List.nil();
   888             while (true) {
   889                 if (tree.hasTag(LITERAL)) {
   890                     JCLiteral lit = (JCLiteral) tree;
   891                     if (lit.typetag == TypeTag.CLASS) {
   892                         StringBuilder sbuf =
   893                             new StringBuilder((String)lit.value);
   894                         while (buf.nonEmpty()) {
   895                             sbuf.append(buf.head);
   896                             buf = buf.tail;
   897                         }
   898                         return sbuf;
   899                     }
   900                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   901                     JCBinary op = (JCBinary)tree;
   902                     if (op.rhs.hasTag(LITERAL)) {
   903                         JCLiteral lit = (JCLiteral) op.rhs;
   904                         if (lit.typetag == TypeTag.CLASS) {
   905                             buf = buf.prepend((String) lit.value);
   906                             tree = op.lhs;
   907                             continue;
   908                         }
   909                     }
   910                 }
   911                 return null;
   912             }
   913         }
   915         /** optimization: To save allocating a new operand/operator stack
   916          *  for every binary operation, we use supplys.
   917          */
   918         ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>();
   919         ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>();
   921         private JCExpression[] newOdStack() {
   922             if (odStackSupply.isEmpty())
   923                 return new JCExpression[infixPrecedenceLevels + 1];
   924             return odStackSupply.remove(odStackSupply.size() - 1);
   925         }
   927         private Token[] newOpStack() {
   928             if (opStackSupply.isEmpty())
   929                 return new Token[infixPrecedenceLevels + 1];
   930             return opStackSupply.remove(opStackSupply.size() - 1);
   931         }
   933     /**
   934      *  Expression3    = PrefixOp Expression3
   935      *                 | "(" Expr | TypeNoParams ")" Expression3
   936      *                 | Primary {Selector} {PostfixOp}
   937      *
   938      *  {@literal
   939      *  Primary        = "(" Expression ")"
   940      *                 | Literal
   941      *                 | [TypeArguments] THIS [Arguments]
   942      *                 | [TypeArguments] SUPER SuperSuffix
   943      *                 | NEW [TypeArguments] Creator
   944      *                 | "(" Arguments ")" "->" ( Expression | Block )
   945      *                 | Ident "->" ( Expression | Block )
   946      *                 | Ident { "." Ident }
   947      *                 | Expression3 MemberReferenceSuffix
   948      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   949      *                   | Arguments
   950      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   951      *                   ]
   952      *                 | BasicType BracketsOpt "." CLASS
   953      *  }
   954      *
   955      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   956      *  PostfixOp      = "++" | "--"
   957      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   958      *                 | BasicType
   959      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   960      *  Selector       = "." [TypeArguments] Ident [Arguments]
   961      *                 | "." THIS
   962      *                 | "." [TypeArguments] SUPER SuperSuffix
   963      *                 | "." NEW [TypeArguments] InnerCreator
   964      *                 | "[" Expression "]"
   965      *  TypeSelector   = "." Ident [TypeArguments]
   966      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   967      */
   968     protected JCExpression term3() {
   969         int pos = token.pos;
   970         JCExpression t;
   971         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   972         switch (token.kind) {
   973         case QUES:
   974             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   975                 mode = TYPE;
   976                 return typeArgument();
   977             } else
   978                 return illegal();
   979         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   980             if (typeArgs == null && (mode & EXPR) != 0) {
   981                 TokenKind tk = token.kind;
   982                 nextToken();
   983                 mode = EXPR;
   984                 if (tk == SUB &&
   985                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
   986                     token.radix() == 10) {
   987                     mode = EXPR;
   988                     t = literal(names.hyphen, pos);
   989                 } else {
   990                     t = term3();
   991                     return F.at(pos).Unary(unoptag(tk), t);
   992                 }
   993             } else return illegal();
   994             break;
   995         case LPAREN:
   996             if (typeArgs == null && (mode & EXPR) != 0) {
   997                 ParensResult pres = analyzeParens();
   998                 switch (pres) {
   999                     case CAST:
  1000                        accept(LPAREN);
  1001                        mode = TYPE;
  1002                        int pos1 = pos;
  1003                        List<JCExpression> targets = List.of(t = term3());
  1004                        while (token.kind == AMP) {
  1005                            checkIntersectionTypesInCast();
  1006                            accept(AMP);
  1007                            targets = targets.prepend(term3());
  1009                        if (targets.length() > 1) {
  1010                            t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
  1012                        accept(RPAREN);
  1013                        mode = EXPR;
  1014                        JCExpression t1 = term3();
  1015                        return F.at(pos).TypeCast(t, t1);
  1016                     case IMPLICIT_LAMBDA:
  1017                     case EXPLICIT_LAMBDA:
  1018                         t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
  1019                         break;
  1020                     default: //PARENS
  1021                         accept(LPAREN);
  1022                         mode = EXPR;
  1023                         t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
  1024                         accept(RPAREN);
  1025                         t = toP(F.at(pos).Parens(t));
  1026                         break;
  1028             } else {
  1029                 return illegal();
  1031             break;
  1032         case THIS:
  1033             if ((mode & EXPR) != 0) {
  1034                 mode = EXPR;
  1035                 t = to(F.at(pos).Ident(names._this));
  1036                 nextToken();
  1037                 if (typeArgs == null)
  1038                     t = argumentsOpt(null, t);
  1039                 else
  1040                     t = arguments(typeArgs, t);
  1041                 typeArgs = null;
  1042             } else return illegal();
  1043             break;
  1044         case SUPER:
  1045             if ((mode & EXPR) != 0) {
  1046                 mode = EXPR;
  1047                 t = to(F.at(pos).Ident(names._super));
  1048                 t = superSuffix(typeArgs, t);
  1049                 typeArgs = null;
  1050             } else return illegal();
  1051             break;
  1052         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1053         case CHARLITERAL: case STRINGLITERAL:
  1054         case TRUE: case FALSE: case NULL:
  1055             if (typeArgs == null && (mode & EXPR) != 0) {
  1056                 mode = EXPR;
  1057                 t = literal(names.empty);
  1058             } else return illegal();
  1059             break;
  1060         case NEW:
  1061             if (typeArgs != null) return illegal();
  1062             if ((mode & EXPR) != 0) {
  1063                 mode = EXPR;
  1064                 nextToken();
  1065                 if (token.kind == LT) typeArgs = typeArguments(false);
  1066                 t = creator(pos, typeArgs);
  1067                 typeArgs = null;
  1068             } else return illegal();
  1069             break;
  1070         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
  1071             if (typeArgs != null) return illegal();
  1072             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1073                 t = lambdaExpressionOrStatement(false, false, pos);
  1074             } else {
  1075                 t = toP(F.at(token.pos).Ident(ident()));
  1076                 loop: while (true) {
  1077                     pos = token.pos;
  1078                     switch (token.kind) {
  1079                     case LBRACKET:
  1080                         nextToken();
  1081                         if (token.kind == RBRACKET) {
  1082                             nextToken();
  1083                             t = bracketsOpt(t);
  1084                             t = toP(F.at(pos).TypeArray(t));
  1085                             t = bracketsSuffix(t);
  1086                         } else {
  1087                             if ((mode & EXPR) != 0) {
  1088                                 mode = EXPR;
  1089                                 JCExpression t1 = term();
  1090                                 t = to(F.at(pos).Indexed(t, t1));
  1092                             accept(RBRACKET);
  1094                         break loop;
  1095                     case LPAREN:
  1096                         if ((mode & EXPR) != 0) {
  1097                             mode = EXPR;
  1098                             t = arguments(typeArgs, t);
  1099                             typeArgs = null;
  1101                         break loop;
  1102                     case DOT:
  1103                         nextToken();
  1104                         int oldmode = mode;
  1105                         mode &= ~NOPARAMS;
  1106                         typeArgs = typeArgumentsOpt(EXPR);
  1107                         mode = oldmode;
  1108                         if ((mode & EXPR) != 0) {
  1109                             switch (token.kind) {
  1110                             case CLASS:
  1111                                 if (typeArgs != null) return illegal();
  1112                                 mode = EXPR;
  1113                                 t = to(F.at(pos).Select(t, names._class));
  1114                                 nextToken();
  1115                                 break loop;
  1116                             case THIS:
  1117                                 if (typeArgs != null) return illegal();
  1118                                 mode = EXPR;
  1119                                 t = to(F.at(pos).Select(t, names._this));
  1120                                 nextToken();
  1121                                 break loop;
  1122                             case SUPER:
  1123                                 mode = EXPR;
  1124                                 t = to(F.at(pos).Select(t, names._super));
  1125                                 t = superSuffix(typeArgs, t);
  1126                                 typeArgs = null;
  1127                                 break loop;
  1128                             case NEW:
  1129                                 if (typeArgs != null) return illegal();
  1130                                 mode = EXPR;
  1131                                 int pos1 = token.pos;
  1132                                 nextToken();
  1133                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1134                                 t = innerCreator(pos1, typeArgs, t);
  1135                                 typeArgs = null;
  1136                                 break loop;
  1139                         // typeArgs saved for next loop iteration.
  1140                         t = toP(F.at(pos).Select(t, ident()));
  1141                         break;
  1142                     case LT:
  1143                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1144                             //this is an unbound method reference whose qualifier
  1145                             //is a generic type i.e. A<S>::m
  1146                             int pos1 = token.pos;
  1147                             accept(LT);
  1148                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1149                             args.append(typeArgument());
  1150                             while (token.kind == COMMA) {
  1151                                 nextToken();
  1152                                 args.append(typeArgument());
  1154                             accept(GT);
  1155                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1156                             checkGenerics();
  1157                             while (token.kind == DOT) {
  1158                                 nextToken();
  1159                                 mode = TYPE;
  1160                                 t = toP(F.at(token.pos).Select(t, ident()));
  1161                                 t = typeArgumentsOpt(t);
  1163                             t = bracketsOpt(t);
  1164                             if (token.kind != COLCOL) {
  1165                                 //method reference expected here
  1166                                 t = illegal();
  1168                             mode = EXPR;
  1169                             return term3Rest(t, typeArgs);
  1171                         break loop;
  1172                     default:
  1173                         break loop;
  1177             if (typeArgs != null) illegal();
  1178             t = typeArgumentsOpt(t);
  1179             break;
  1180         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1181         case DOUBLE: case BOOLEAN:
  1182             if (typeArgs != null) illegal();
  1183             t = bracketsSuffix(bracketsOpt(basicType()));
  1184             break;
  1185         case VOID:
  1186             if (typeArgs != null) illegal();
  1187             if ((mode & EXPR) != 0) {
  1188                 nextToken();
  1189                 if (token.kind == DOT) {
  1190                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
  1191                     t = bracketsSuffix(ti);
  1192                 } else {
  1193                     return illegal(pos);
  1195             } else {
  1196                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1197                 // a void type (like other primitive types) to the next phase.
  1198                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1199                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
  1200                 nextToken();
  1201                 return ti;
  1202                 //return illegal();
  1204             break;
  1205         default:
  1206             return illegal();
  1208         return term3Rest(t, typeArgs);
  1211     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1212         if (typeArgs != null) illegal();
  1213         while (true) {
  1214             int pos1 = token.pos;
  1215             if (token.kind == LBRACKET) {
  1216                 nextToken();
  1217                 if ((mode & TYPE) != 0) {
  1218                     int oldmode = mode;
  1219                     mode = TYPE;
  1220                     if (token.kind == RBRACKET) {
  1221                         nextToken();
  1222                         t = bracketsOpt(t);
  1223                         t = toP(F.at(pos1).TypeArray(t));
  1224                         if (token.kind == COLCOL) {
  1225                             mode = EXPR;
  1226                             continue;
  1228                         return t;
  1230                     mode = oldmode;
  1232                 if ((mode & EXPR) != 0) {
  1233                     mode = EXPR;
  1234                     JCExpression t1 = term();
  1235                     t = to(F.at(pos1).Indexed(t, t1));
  1237                 accept(RBRACKET);
  1238             } else if (token.kind == DOT) {
  1239                 nextToken();
  1240                 typeArgs = typeArgumentsOpt(EXPR);
  1241                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1242                     mode = EXPR;
  1243                     t = to(F.at(pos1).Select(t, names._super));
  1244                     nextToken();
  1245                     t = arguments(typeArgs, t);
  1246                     typeArgs = null;
  1247                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1248                     if (typeArgs != null) return illegal();
  1249                     mode = EXPR;
  1250                     int pos2 = token.pos;
  1251                     nextToken();
  1252                     if (token.kind == LT) typeArgs = typeArguments(false);
  1253                     t = innerCreator(pos2, typeArgs, t);
  1254                     typeArgs = null;
  1255                 } else {
  1256                     t = toP(F.at(pos1).Select(t, ident()));
  1257                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1258                     typeArgs = null;
  1260             } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
  1261                 mode = EXPR;
  1262                 if (typeArgs != null) return illegal();
  1263                 accept(COLCOL);
  1264                 t = memberReferenceSuffix(pos1, t);
  1265             } else {
  1266                 break;
  1269         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1270             mode = EXPR;
  1271             t = to(F.at(token.pos).Unary(
  1272                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1273             nextToken();
  1275         return toP(t);
  1278     /**
  1279      * If we see an identifier followed by a '&lt;' it could be an unbound
  1280      * method reference or a binary expression. To disambiguate, look for a
  1281      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1282      */
  1283     @SuppressWarnings("fallthrough")
  1284     boolean isUnboundMemberRef() {
  1285         int pos = 0, depth = 0;
  1286         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1287             switch (t.kind) {
  1288                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
  1289                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1290                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1291                 case DOUBLE: case BOOLEAN: case CHAR:
  1292                     break;
  1293                 case LT:
  1294                     depth++; break;
  1295                 case GTGTGT:
  1296                     depth--;
  1297                 case GTGT:
  1298                     depth--;
  1299                 case GT:
  1300                     depth--;
  1301                     if (depth == 0) {
  1302                         TokenKind nextKind = S.token(pos + 1).kind;
  1303                         return
  1304                             nextKind == TokenKind.DOT ||
  1305                             nextKind == TokenKind.LBRACKET ||
  1306                             nextKind == TokenKind.COLCOL;
  1308                     break;
  1309                 default:
  1310                     return false;
  1315     /**
  1316      * If we see an identifier followed by a '&lt;' it could be an unbound
  1317      * method reference or a binary expression. To disambiguate, look for a
  1318      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1319      */
  1320     @SuppressWarnings("fallthrough")
  1321     ParensResult analyzeParens() {
  1322         int depth = 0;
  1323         boolean type = false;
  1324         for (int lookahead = 0 ; ; lookahead++) {
  1325             TokenKind tk = S.token(lookahead).kind;
  1326             switch (tk) {
  1327                 case EXTENDS: case SUPER: case COMMA:
  1328                     type = true;
  1329                 case QUES: case DOT: case AMP:
  1330                     //skip
  1331                     break;
  1332                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1333                 case DOUBLE: case BOOLEAN: case CHAR:
  1334                     if (peekToken(lookahead, RPAREN)) {
  1335                         //Type, ')' -> cast
  1336                         return ParensResult.CAST;
  1337                     } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1338                         //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1339                         return ParensResult.EXPLICIT_LAMBDA;
  1341                     break;
  1342                 case LPAREN:
  1343                     if (lookahead != 0) {
  1344                         // '(' in a non-starting position -> parens
  1345                         return ParensResult.PARENS;
  1346                     } else if (peekToken(lookahead, RPAREN)) {
  1347                         // '(', ')' -> explicit lambda
  1348                         return ParensResult.EXPLICIT_LAMBDA;
  1350                     break;
  1351                 case RPAREN:
  1352                     // if we have seen something that looks like a type,
  1353                     // then it's a cast expression
  1354                     if (type) return ParensResult.CAST;
  1355                     // otherwise, disambiguate cast vs. parenthesized expression
  1356                     // based on subsequent token.
  1357                     switch (S.token(lookahead + 1).kind) {
  1358                         /*case PLUSPLUS: case SUBSUB: */
  1359                         case BANG: case TILDE:
  1360                         case LPAREN: case THIS: case SUPER:
  1361                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1362                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1363                         case TRUE: case FALSE: case NULL:
  1364                         case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
  1365                         case BYTE: case SHORT: case CHAR: case INT:
  1366                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1367                             return ParensResult.CAST;
  1368                         default:
  1369                             return ParensResult.PARENS;
  1371                 case UNDERSCORE:
  1372                 case ASSERT:
  1373                 case ENUM:
  1374                 case IDENTIFIER:
  1375                     if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1376                         // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1377                         return ParensResult.EXPLICIT_LAMBDA;
  1378                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
  1379                         // Identifier, ')' '->' -> implicit lambda
  1380                         return ParensResult.IMPLICIT_LAMBDA;
  1382                     break;
  1383                 case FINAL:
  1384                 case ELLIPSIS:
  1385                 case MONKEYS_AT:
  1386                     //those can only appear in explicit lambdas
  1387                     return ParensResult.EXPLICIT_LAMBDA;
  1388                 case LBRACKET:
  1389                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
  1390                         // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
  1391                         return ParensResult.EXPLICIT_LAMBDA;
  1392                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
  1393                             peekToken(lookahead, RBRACKET, AMP)) {
  1394                         // '[', ']', ')' -> cast
  1395                         // '[', ']', '&' -> cast (intersection type)
  1396                         return ParensResult.CAST;
  1397                     } else if (peekToken(lookahead, RBRACKET)) {
  1398                         //consume the ']' and skip
  1399                         type = true;
  1400                         lookahead++;
  1401                         break;
  1402                     } else {
  1403                         return ParensResult.PARENS;
  1405                 case LT:
  1406                     depth++; break;
  1407                 case GTGTGT:
  1408                     depth--;
  1409                 case GTGT:
  1410                     depth--;
  1411                 case GT:
  1412                     depth--;
  1413                     if (depth == 0) {
  1414                         if (peekToken(lookahead, RPAREN) ||
  1415                                 peekToken(lookahead, AMP)) {
  1416                             // '>', ')' -> cast
  1417                             // '>', '&' -> cast
  1418                             return ParensResult.CAST;
  1419                         } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
  1420                                 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
  1421                                 peekToken(lookahead, ELLIPSIS)) {
  1422                             // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
  1423                             // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
  1424                             // '>', '...' -> explicit lambda
  1425                             return ParensResult.EXPLICIT_LAMBDA;
  1427                         //it looks a type, but could still be (i) a cast to generic type,
  1428                         //(ii) an unbound method reference or (iii) an explicit lambda
  1429                         type = true;
  1430                         break;
  1431                     } else if (depth < 0) {
  1432                         //unbalanced '<', '>' - not a generic type
  1433                         return ParensResult.PARENS;
  1435                     break;
  1436                 default:
  1437                     //this includes EOF
  1438                     return ParensResult.PARENS;
  1443     /** Accepts all identifier-like tokens */
  1444     Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
  1445         public boolean accepts(TokenKind t) {
  1446             return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
  1448     };
  1450     enum ParensResult {
  1451         CAST,
  1452         EXPLICIT_LAMBDA,
  1453         IMPLICIT_LAMBDA,
  1454         PARENS;
  1457     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1458         List<JCVariableDecl> params = explicitParams ?
  1459                 formalParameters(true) :
  1460                 implicitParameters(hasParens);
  1462         return lambdaExpressionOrStatementRest(params, pos);
  1465     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1466         checkLambda();
  1467         accept(ARROW);
  1469         return token.kind == LBRACE ?
  1470             lambdaStatement(args, pos, pos) :
  1471             lambdaExpression(args, pos);
  1474     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1475         JCBlock block = block(pos2, 0);
  1476         return toP(F.at(pos).Lambda(args, block));
  1479     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1480         JCTree expr = parseExpression();
  1481         return toP(F.at(pos).Lambda(args, expr));
  1484     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1485      */
  1486     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1487         nextToken();
  1488         if (token.kind == LPAREN || typeArgs != null) {
  1489             t = arguments(typeArgs, t);
  1490         } else if (token.kind == COLCOL) {
  1491             if (typeArgs != null) return illegal();
  1492             t = memberReferenceSuffix(t);
  1493         } else {
  1494             int pos = token.pos;
  1495             accept(DOT);
  1496             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1497             t = toP(F.at(pos).Select(t, ident()));
  1498             t = argumentsOpt(typeArgs, t);
  1500         return t;
  1503     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1504      */
  1505     JCPrimitiveTypeTree basicType() {
  1506         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1507         nextToken();
  1508         return t;
  1511     /** ArgumentsOpt = [ Arguments ]
  1512      */
  1513     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1514         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1515             mode = EXPR;
  1516             return arguments(typeArgs, t);
  1517         } else {
  1518             return t;
  1522     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1523      */
  1524     List<JCExpression> arguments() {
  1525         ListBuffer<JCExpression> args = lb();
  1526         if (token.kind == LPAREN) {
  1527             nextToken();
  1528             if (token.kind != RPAREN) {
  1529                 args.append(parseExpression());
  1530                 while (token.kind == COMMA) {
  1531                     nextToken();
  1532                     args.append(parseExpression());
  1535             accept(RPAREN);
  1536         } else {
  1537             syntaxError(token.pos, "expected", LPAREN);
  1539         return args.toList();
  1542     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1543         int pos = token.pos;
  1544         List<JCExpression> args = arguments();
  1545         return toP(F.at(pos).Apply(typeArgs, t, args));
  1548     /**  TypeArgumentsOpt = [ TypeArguments ]
  1549      */
  1550     JCExpression typeArgumentsOpt(JCExpression t) {
  1551         if (token.kind == LT &&
  1552             (mode & TYPE) != 0 &&
  1553             (mode & NOPARAMS) == 0) {
  1554             mode = TYPE;
  1555             checkGenerics();
  1556             return typeArguments(t, false);
  1557         } else {
  1558             return t;
  1561     List<JCExpression> typeArgumentsOpt() {
  1562         return typeArgumentsOpt(TYPE);
  1565     List<JCExpression> typeArgumentsOpt(int useMode) {
  1566         if (token.kind == LT) {
  1567             checkGenerics();
  1568             if ((mode & useMode) == 0 ||
  1569                 (mode & NOPARAMS) != 0) {
  1570                 illegal();
  1572             mode = useMode;
  1573             return typeArguments(false);
  1575         return null;
  1578     /**
  1579      *  {@literal
  1580      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1581      *  }
  1582      */
  1583     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1584         if (token.kind == LT) {
  1585             nextToken();
  1586             if (token.kind == GT && diamondAllowed) {
  1587                 checkDiamond();
  1588                 mode |= DIAMOND;
  1589                 nextToken();
  1590                 return List.nil();
  1591             } else {
  1592                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1593                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1594                 while (token.kind == COMMA) {
  1595                     nextToken();
  1596                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1598                 switch (token.kind) {
  1600                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1601                 case GTGTGT: case GTGT:
  1602                     token = S.split();
  1603                     break;
  1604                 case GT:
  1605                     nextToken();
  1606                     break;
  1607                 default:
  1608                     args.append(syntaxError(token.pos, "expected", GT));
  1609                     break;
  1611                 return args.toList();
  1613         } else {
  1614             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1618     /**
  1619      *  {@literal
  1620      *  TypeArgument = Type
  1621      *               | "?"
  1622      *               | "?" EXTENDS Type {"&" Type}
  1623      *               | "?" SUPER Type
  1624      *  }
  1625      */
  1626     JCExpression typeArgument() {
  1627         if (token.kind != QUES) return parseType();
  1628         int pos = token.pos;
  1629         nextToken();
  1630         if (token.kind == EXTENDS) {
  1631             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1632             nextToken();
  1633             JCExpression bound = parseType();
  1634             return F.at(pos).Wildcard(t, bound);
  1635         } else if (token.kind == SUPER) {
  1636             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1637             nextToken();
  1638             JCExpression bound = parseType();
  1639             return F.at(pos).Wildcard(t, bound);
  1640         } else if (LAX_IDENTIFIER.accepts(token.kind)) {
  1641             //error recovery
  1642             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1643             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1644             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1645             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1646             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1647             return err;
  1648         } else {
  1649             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1650             return toP(F.at(pos).Wildcard(t, null));
  1654     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1655         int pos = token.pos;
  1656         List<JCExpression> args = typeArguments(diamondAllowed);
  1657         return toP(F.at(pos).TypeApply(t, args));
  1660     /** BracketsOpt = {"[" "]"}
  1661      */
  1662     private JCExpression bracketsOpt(JCExpression t) {
  1663         if (token.kind == LBRACKET) {
  1664             int pos = token.pos;
  1665             nextToken();
  1666             t = bracketsOptCont(t, pos);
  1667             F.at(pos);
  1669         return t;
  1672     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1673         accept(RBRACKET);
  1674         t = bracketsOpt(t);
  1675         return toP(F.at(pos).TypeArray(t));
  1678     /** BracketsSuffixExpr = "." CLASS
  1679      *  BracketsSuffixType =
  1680      */
  1681     JCExpression bracketsSuffix(JCExpression t) {
  1682         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1683             mode = EXPR;
  1684             int pos = token.pos;
  1685             nextToken();
  1686             accept(CLASS);
  1687             if (token.pos == endPosTable.errorEndPos) {
  1688                 // error recovery
  1689                 Name name = null;
  1690                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  1691                     name = token.name();
  1692                     nextToken();
  1693                 } else {
  1694                     name = names.error;
  1696                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1697             } else {
  1698                 t = toP(F.at(pos).Select(t, names._class));
  1700         } else if ((mode & TYPE) != 0) {
  1701             if (token.kind != COLCOL) {
  1702                 mode = TYPE;
  1704         } else if (token.kind != COLCOL) {
  1705             syntaxError(token.pos, "dot.class.expected");
  1707         return t;
  1710     /**
  1711      * MemberReferenceSuffix = "::" [TypeArguments] Ident
  1712      *                       | "::" [TypeArguments] "new"
  1713      */
  1714     JCExpression memberReferenceSuffix(JCExpression t) {
  1715         int pos1 = token.pos;
  1716         accept(COLCOL);
  1717         return memberReferenceSuffix(pos1, t);
  1720     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1721         checkMethodReferences();
  1722         mode = EXPR;
  1723         List<JCExpression> typeArgs = null;
  1724         if (token.kind == LT) {
  1725             typeArgs = typeArguments(false);
  1727         Name refName = null;
  1728         ReferenceMode refMode = null;
  1729         if (token.kind == NEW) {
  1730             refMode = ReferenceMode.NEW;
  1731             refName = names.init;
  1732             nextToken();
  1733         } else {
  1734             refMode = ReferenceMode.INVOKE;
  1735             refName = ident();
  1737         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  1740     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1741      */
  1742     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1743         switch (token.kind) {
  1744         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1745         case DOUBLE: case BOOLEAN:
  1746             if (typeArgs == null)
  1747                 return arrayCreatorRest(newpos, basicType());
  1748             break;
  1749         default:
  1751         JCExpression t = qualident();
  1752         int oldmode = mode;
  1753         mode = TYPE;
  1754         boolean diamondFound = false;
  1755         int lastTypeargsPos = -1;
  1756         if (token.kind == LT) {
  1757             checkGenerics();
  1758             lastTypeargsPos = token.pos;
  1759             t = typeArguments(t, true);
  1760             diamondFound = (mode & DIAMOND) != 0;
  1762         while (token.kind == DOT) {
  1763             if (diamondFound) {
  1764                 //cannot select after a diamond
  1765                 illegal();
  1767             int pos = token.pos;
  1768             nextToken();
  1769             t = toP(F.at(pos).Select(t, ident()));
  1770             if (token.kind == LT) {
  1771                 lastTypeargsPos = token.pos;
  1772                 checkGenerics();
  1773                 t = typeArguments(t, true);
  1774                 diamondFound = (mode & DIAMOND) != 0;
  1777         mode = oldmode;
  1778         if (token.kind == LBRACKET) {
  1779             JCExpression e = arrayCreatorRest(newpos, t);
  1780             if (diamondFound) {
  1781                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1782                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1784             else if (typeArgs != null) {
  1785                 int pos = newpos;
  1786                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1787                     // note: this should always happen but we should
  1788                     // not rely on this as the parser is continuously
  1789                     // modified to improve error recovery.
  1790                     pos = typeArgs.head.pos;
  1792                 setErrorEndPos(S.prevToken().endPos);
  1793                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1794                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1795                 return toP(err);
  1797             return e;
  1798         } else if (token.kind == LPAREN) {
  1799             return classCreatorRest(newpos, null, typeArgs, t);
  1800         } else {
  1801             setErrorEndPos(token.pos);
  1802             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1803             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1804             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1808     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1809      */
  1810     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1811         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1812         if (token.kind == LT) {
  1813             int oldmode = mode;
  1814             checkGenerics();
  1815             t = typeArguments(t, true);
  1816             mode = oldmode;
  1818         return classCreatorRest(newpos, encl, typeArgs, t);
  1821     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1822      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1823      */
  1824     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1825         accept(LBRACKET);
  1826         if (token.kind == RBRACKET) {
  1827             accept(RBRACKET);
  1828             elemtype = bracketsOpt(elemtype);
  1829             if (token.kind == LBRACE) {
  1830                 return arrayInitializer(newpos, elemtype);
  1831             } else {
  1832                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1833                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1835         } else {
  1836             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1837             dims.append(parseExpression());
  1838             accept(RBRACKET);
  1839             while (token.kind == LBRACKET) {
  1840                 int pos = token.pos;
  1841                 nextToken();
  1842                 if (token.kind == RBRACKET) {
  1843                     elemtype = bracketsOptCont(elemtype, pos);
  1844                 } else {
  1845                     dims.append(parseExpression());
  1846                     accept(RBRACKET);
  1849             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1853     /** ClassCreatorRest = Arguments [ClassBody]
  1854      */
  1855     JCNewClass classCreatorRest(int newpos,
  1856                                   JCExpression encl,
  1857                                   List<JCExpression> typeArgs,
  1858                                   JCExpression t)
  1860         List<JCExpression> args = arguments();
  1861         JCClassDecl body = null;
  1862         if (token.kind == LBRACE) {
  1863             int pos = token.pos;
  1864             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1865             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1866             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1868         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1871     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1872      */
  1873     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1874         accept(LBRACE);
  1875         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1876         if (token.kind == COMMA) {
  1877             nextToken();
  1878         } else if (token.kind != RBRACE) {
  1879             elems.append(variableInitializer());
  1880             while (token.kind == COMMA) {
  1881                 nextToken();
  1882                 if (token.kind == RBRACE) break;
  1883                 elems.append(variableInitializer());
  1886         accept(RBRACE);
  1887         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1890     /** VariableInitializer = ArrayInitializer | Expression
  1891      */
  1892     public JCExpression variableInitializer() {
  1893         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1896     /** ParExpression = "(" Expression ")"
  1897      */
  1898     JCExpression parExpression() {
  1899         int pos = token.pos;
  1900         accept(LPAREN);
  1901         JCExpression t = parseExpression();
  1902         accept(RPAREN);
  1903         return toP(F.at(pos).Parens(t));
  1906     /** Block = "{" BlockStatements "}"
  1907      */
  1908     JCBlock block(int pos, long flags) {
  1909         accept(LBRACE);
  1910         List<JCStatement> stats = blockStatements();
  1911         JCBlock t = F.at(pos).Block(flags, stats);
  1912         while (token.kind == CASE || token.kind == DEFAULT) {
  1913             syntaxError("orphaned", token.kind);
  1914             switchBlockStatementGroups();
  1916         // the Block node has a field "endpos" for first char of last token, which is
  1917         // usually but not necessarily the last char of the last token.
  1918         t.endpos = token.pos;
  1919         accept(RBRACE);
  1920         return toP(t);
  1923     public JCBlock block() {
  1924         return block(token.pos, 0);
  1927     /** BlockStatements = { BlockStatement }
  1928      *  BlockStatement  = LocalVariableDeclarationStatement
  1929      *                  | ClassOrInterfaceOrEnumDeclaration
  1930      *                  | [Ident ":"] Statement
  1931      *  LocalVariableDeclarationStatement
  1932      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1933      */
  1934     @SuppressWarnings("fallthrough")
  1935     List<JCStatement> blockStatements() {
  1936         //todo: skip to anchor on error(?)
  1937         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1938         while (true) {
  1939             List<JCStatement> stat = blockStatement();
  1940             if (stat.isEmpty()) {
  1941                 return stats.toList();
  1942             } else {
  1943                 if (token.pos <= endPosTable.errorEndPos) {
  1944                     skip(false, true, true, true);
  1946                 stats.addAll(stat);
  1951     /*
  1952      * This method parses a statement treating it as a block, relaxing the
  1953      * JLS restrictions, allows us to parse more faulty code, doing so
  1954      * enables us to provide better and accurate diagnostics to the user.
  1955      */
  1956     JCStatement parseStatementAsBlock() {
  1957         int pos = token.pos;
  1958         List<JCStatement> stats = blockStatement();
  1959         if (stats.isEmpty()) {
  1960             JCErroneous e = F.at(pos).Erroneous();
  1961             error(e, "illegal.start.of.stmt");
  1962             return F.at(pos).Exec(e);
  1963         } else {
  1964             JCStatement first = stats.head;
  1965             String error = null;
  1966             switch (first.getTag()) {
  1967             case CLASSDEF:
  1968                 error = "class.not.allowed";
  1969                 break;
  1970             case VARDEF:
  1971                 error = "variable.not.allowed";
  1972                 break;
  1974             if (error != null) {
  1975                 error(first, error);
  1976                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  1977                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  1979             return first;
  1983     @SuppressWarnings("fallthrough")
  1984     List<JCStatement> blockStatement() {
  1985         //todo: skip to anchor on error(?)
  1986         int pos = token.pos;
  1987         switch (token.kind) {
  1988         case RBRACE: case CASE: case DEFAULT: case EOF:
  1989             return List.nil();
  1990         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1991         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1992         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1993             return List.of(parseStatement());
  1994         case MONKEYS_AT:
  1995         case FINAL: {
  1996             Comment dc = token.comment(CommentStyle.JAVADOC);
  1997             JCModifiers mods = modifiersOpt();
  1998             if (token.kind == INTERFACE ||
  1999                 token.kind == CLASS ||
  2000                 allowEnums && token.kind == ENUM) {
  2001                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2002             } else {
  2003                 JCExpression t = parseType();
  2004                 ListBuffer<JCStatement> stats =
  2005                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2006                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2007                 storeEnd(stats.last(), token.endPos);
  2008                 accept(SEMI);
  2009                 return stats.toList();
  2012         case ABSTRACT: case STRICTFP: {
  2013             Comment dc = token.comment(CommentStyle.JAVADOC);
  2014             JCModifiers mods = modifiersOpt();
  2015             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2017         case INTERFACE:
  2018         case CLASS:
  2019             Comment dc = token.comment(CommentStyle.JAVADOC);
  2020             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2021         case ENUM:
  2022         case ASSERT:
  2023             if (allowEnums && token.kind == ENUM) {
  2024                 error(token.pos, "local.enum");
  2025                 dc = token.comment(CommentStyle.JAVADOC);
  2026                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2027             } else if (allowAsserts && token.kind == ASSERT) {
  2028                 return List.of(parseStatement());
  2030             /* fall through to default */
  2031         default:
  2032             Token prevToken = token;
  2033             JCExpression t = term(EXPR | TYPE);
  2034             if (token.kind == COLON && t.hasTag(IDENT)) {
  2035                 nextToken();
  2036                 JCStatement stat = parseStatement();
  2037                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  2038             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2039                 pos = token.pos;
  2040                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2041                 F.at(pos);
  2042                 ListBuffer<JCStatement> stats =
  2043                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2044                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2045                 storeEnd(stats.last(), token.endPos);
  2046                 accept(SEMI);
  2047                 return stats.toList();
  2048             } else {
  2049                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2050                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  2051                 accept(SEMI);
  2052                 return List.<JCStatement>of(expr);
  2057     /** Statement =
  2058      *       Block
  2059      *     | IF ParExpression Statement [ELSE Statement]
  2060      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  2061      *     | FOR "(" FormalParameter : Expression ")" Statement
  2062      *     | WHILE ParExpression Statement
  2063      *     | DO Statement WHILE ParExpression ";"
  2064      *     | TRY Block ( Catches | [Catches] FinallyPart )
  2065      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  2066      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  2067      *     | SYNCHRONIZED ParExpression Block
  2068      *     | RETURN [Expression] ";"
  2069      *     | THROW Expression ";"
  2070      *     | BREAK [Ident] ";"
  2071      *     | CONTINUE [Ident] ";"
  2072      *     | ASSERT Expression [ ":" Expression ] ";"
  2073      *     | ";"
  2074      *     | ExpressionStatement
  2075      *     | Ident ":" Statement
  2076      */
  2077     @SuppressWarnings("fallthrough")
  2078     public JCStatement parseStatement() {
  2079         int pos = token.pos;
  2080         switch (token.kind) {
  2081         case LBRACE:
  2082             return block();
  2083         case IF: {
  2084             nextToken();
  2085             JCExpression cond = parExpression();
  2086             JCStatement thenpart = parseStatementAsBlock();
  2087             JCStatement elsepart = null;
  2088             if (token.kind == ELSE) {
  2089                 nextToken();
  2090                 elsepart = parseStatementAsBlock();
  2092             return F.at(pos).If(cond, thenpart, elsepart);
  2094         case FOR: {
  2095             nextToken();
  2096             accept(LPAREN);
  2097             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  2098             if (inits.length() == 1 &&
  2099                 inits.head.hasTag(VARDEF) &&
  2100                 ((JCVariableDecl) inits.head).init == null &&
  2101                 token.kind == COLON) {
  2102                 checkForeach();
  2103                 JCVariableDecl var = (JCVariableDecl)inits.head;
  2104                 accept(COLON);
  2105                 JCExpression expr = parseExpression();
  2106                 accept(RPAREN);
  2107                 JCStatement body = parseStatementAsBlock();
  2108                 return F.at(pos).ForeachLoop(var, expr, body);
  2109             } else {
  2110                 accept(SEMI);
  2111                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  2112                 accept(SEMI);
  2113                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2114                 accept(RPAREN);
  2115                 JCStatement body = parseStatementAsBlock();
  2116                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2119         case WHILE: {
  2120             nextToken();
  2121             JCExpression cond = parExpression();
  2122             JCStatement body = parseStatementAsBlock();
  2123             return F.at(pos).WhileLoop(cond, body);
  2125         case DO: {
  2126             nextToken();
  2127             JCStatement body = parseStatementAsBlock();
  2128             accept(WHILE);
  2129             JCExpression cond = parExpression();
  2130             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2131             accept(SEMI);
  2132             return t;
  2134         case TRY: {
  2135             nextToken();
  2136             List<JCTree> resources = List.<JCTree>nil();
  2137             if (token.kind == LPAREN) {
  2138                 checkTryWithResources();
  2139                 nextToken();
  2140                 resources = resources();
  2141                 accept(RPAREN);
  2143             JCBlock body = block();
  2144             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2145             JCBlock finalizer = null;
  2146             if (token.kind == CATCH || token.kind == FINALLY) {
  2147                 while (token.kind == CATCH) catchers.append(catchClause());
  2148                 if (token.kind == FINALLY) {
  2149                     nextToken();
  2150                     finalizer = block();
  2152             } else {
  2153                 if (allowTWR) {
  2154                     if (resources.isEmpty())
  2155                         error(pos, "try.without.catch.finally.or.resource.decls");
  2156                 } else
  2157                     error(pos, "try.without.catch.or.finally");
  2159             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2161         case SWITCH: {
  2162             nextToken();
  2163             JCExpression selector = parExpression();
  2164             accept(LBRACE);
  2165             List<JCCase> cases = switchBlockStatementGroups();
  2166             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2167             accept(RBRACE);
  2168             return t;
  2170         case SYNCHRONIZED: {
  2171             nextToken();
  2172             JCExpression lock = parExpression();
  2173             JCBlock body = block();
  2174             return F.at(pos).Synchronized(lock, body);
  2176         case RETURN: {
  2177             nextToken();
  2178             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2179             JCReturn t = to(F.at(pos).Return(result));
  2180             accept(SEMI);
  2181             return t;
  2183         case THROW: {
  2184             nextToken();
  2185             JCExpression exc = parseExpression();
  2186             JCThrow t = to(F.at(pos).Throw(exc));
  2187             accept(SEMI);
  2188             return t;
  2190         case BREAK: {
  2191             nextToken();
  2192             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2193             JCBreak t = to(F.at(pos).Break(label));
  2194             accept(SEMI);
  2195             return t;
  2197         case CONTINUE: {
  2198             nextToken();
  2199             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2200             JCContinue t =  to(F.at(pos).Continue(label));
  2201             accept(SEMI);
  2202             return t;
  2204         case SEMI:
  2205             nextToken();
  2206             return toP(F.at(pos).Skip());
  2207         case ELSE:
  2208             int elsePos = token.pos;
  2209             nextToken();
  2210             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
  2211         case FINALLY:
  2212             int finallyPos = token.pos;
  2213             nextToken();
  2214             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
  2215         case CATCH:
  2216             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
  2217         case ASSERT: {
  2218             if (allowAsserts && token.kind == ASSERT) {
  2219                 nextToken();
  2220                 JCExpression assertion = parseExpression();
  2221                 JCExpression message = null;
  2222                 if (token.kind == COLON) {
  2223                     nextToken();
  2224                     message = parseExpression();
  2226                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2227                 accept(SEMI);
  2228                 return t;
  2230             /* else fall through to default case */
  2232         case ENUM:
  2233         default:
  2234             Token prevToken = token;
  2235             JCExpression expr = parseExpression();
  2236             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2237                 nextToken();
  2238                 JCStatement stat = parseStatement();
  2239                 return F.at(pos).Labelled(prevToken.name(), stat);
  2240             } else {
  2241                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2242                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2243                 accept(SEMI);
  2244                 return stat;
  2249     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
  2250         int errPos = S.errPos();
  2251         JCTree stm = action.doRecover(this);
  2252         S.errPos(errPos);
  2253         return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
  2256     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2257      */
  2258     protected JCCatch catchClause() {
  2259         int pos = token.pos;
  2260         accept(CATCH);
  2261         accept(LPAREN);
  2262         JCModifiers mods = optFinal(Flags.PARAMETER);
  2263         List<JCExpression> catchTypes = catchTypes();
  2264         JCExpression paramType = catchTypes.size() > 1 ?
  2265                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2266                 catchTypes.head;
  2267         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2268         accept(RPAREN);
  2269         JCBlock body = block();
  2270         return F.at(pos).Catch(formal, body);
  2273     List<JCExpression> catchTypes() {
  2274         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2275         catchTypes.add(parseType());
  2276         while (token.kind == BAR) {
  2277             checkMulticatch();
  2278             nextToken();
  2279             catchTypes.add(qualident());
  2281         return catchTypes.toList();
  2284     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2285      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2286      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2287      */
  2288     List<JCCase> switchBlockStatementGroups() {
  2289         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2290         while (true) {
  2291             int pos = token.pos;
  2292             switch (token.kind) {
  2293             case CASE:
  2294             case DEFAULT:
  2295                 cases.append(switchBlockStatementGroup());
  2296                 break;
  2297             case RBRACE: case EOF:
  2298                 return cases.toList();
  2299             default:
  2300                 nextToken(); // to ensure progress
  2301                 syntaxError(pos, "expected3",
  2302                     CASE, DEFAULT, RBRACE);
  2307     protected JCCase switchBlockStatementGroup() {
  2308         int pos = token.pos;
  2309         List<JCStatement> stats;
  2310         JCCase c;
  2311         switch (token.kind) {
  2312         case CASE:
  2313             nextToken();
  2314             JCExpression pat = parseExpression();
  2315             accept(COLON);
  2316             stats = blockStatements();
  2317             c = F.at(pos).Case(pat, stats);
  2318             if (stats.isEmpty())
  2319                 storeEnd(c, S.prevToken().endPos);
  2320             return c;
  2321         case DEFAULT:
  2322             nextToken();
  2323             accept(COLON);
  2324             stats = blockStatements();
  2325             c = F.at(pos).Case(null, stats);
  2326             if (stats.isEmpty())
  2327                 storeEnd(c, S.prevToken().endPos);
  2328             return c;
  2330         throw new AssertionError("should not reach here");
  2333     /** MoreStatementExpressions = { COMMA StatementExpression }
  2334      */
  2335     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2336                                                                     JCExpression first,
  2337                                                                     T stats) {
  2338         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2339         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2340         while (token.kind == COMMA) {
  2341             nextToken();
  2342             pos = token.pos;
  2343             JCExpression t = parseExpression();
  2344             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2345             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2347         return stats;
  2350     /** ForInit = StatementExpression MoreStatementExpressions
  2351      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2352      */
  2353     List<JCStatement> forInit() {
  2354         ListBuffer<JCStatement> stats = lb();
  2355         int pos = token.pos;
  2356         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2357             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2358         } else {
  2359             JCExpression t = term(EXPR | TYPE);
  2360             if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2361                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2362             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2363                 error(pos, "bad.initializer", "for-loop");
  2364                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2365             } else {
  2366                 return moreStatementExpressions(pos, t, stats).toList();
  2371     /** ForUpdate = StatementExpression MoreStatementExpressions
  2372      */
  2373     List<JCExpressionStatement> forUpdate() {
  2374         return moreStatementExpressions(token.pos,
  2375                                         parseExpression(),
  2376                                         new ListBuffer<JCExpressionStatement>()).toList();
  2379     /** AnnotationsOpt = { '@' Annotation }
  2380      */
  2381     List<JCAnnotation> annotationsOpt() {
  2382         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2383         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2384         while (token.kind == MONKEYS_AT) {
  2385             int pos = token.pos;
  2386             nextToken();
  2387             buf.append(annotation(pos));
  2389         return buf.toList();
  2392     /** ModifiersOpt = { Modifier }
  2393      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2394      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2395      *           | "@" Annotation
  2396      */
  2397     JCModifiers modifiersOpt() {
  2398         return modifiersOpt(null);
  2400     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2401         long flags;
  2402         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2403         int pos;
  2404         if (partial == null) {
  2405             flags = 0;
  2406             pos = token.pos;
  2407         } else {
  2408             flags = partial.flags;
  2409             annotations.appendList(partial.annotations);
  2410             pos = partial.pos;
  2412         if (token.deprecatedFlag()) {
  2413             flags |= Flags.DEPRECATED;
  2415         int lastPos = Position.NOPOS;
  2416     loop:
  2417         while (true) {
  2418             long flag;
  2419             switch (token.kind) {
  2420             case PRIVATE     : flag = Flags.PRIVATE; break;
  2421             case PROTECTED   : flag = Flags.PROTECTED; break;
  2422             case PUBLIC      : flag = Flags.PUBLIC; break;
  2423             case STATIC      : flag = Flags.STATIC; break;
  2424             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2425             case FINAL       : flag = Flags.FINAL; break;
  2426             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2427             case NATIVE      : flag = Flags.NATIVE; break;
  2428             case VOLATILE    : flag = Flags.VOLATILE; break;
  2429             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2430             case STRICTFP    : flag = Flags.STRICTFP; break;
  2431             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2432             case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
  2433             case ERROR       : flag = 0; nextToken(); break;
  2434             default: break loop;
  2436             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2437             lastPos = token.pos;
  2438             nextToken();
  2439             if (flag == Flags.ANNOTATION) {
  2440                 checkAnnotations();
  2441                 if (token.kind != INTERFACE) {
  2442                     JCAnnotation ann = annotation(lastPos);
  2443                     // if first modifier is an annotation, set pos to annotation's.
  2444                     if (flags == 0 && annotations.isEmpty())
  2445                         pos = ann.pos;
  2446                     annotations.append(ann);
  2447                     lastPos = ann.pos;
  2448                     flag = 0;
  2451             flags |= flag;
  2453         switch (token.kind) {
  2454         case ENUM: flags |= Flags.ENUM; break;
  2455         case INTERFACE: flags |= Flags.INTERFACE; break;
  2456         default: break;
  2459         /* A modifiers tree with no modifier tokens or annotations
  2460          * has no text position. */
  2461         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2462             pos = Position.NOPOS;
  2464         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2465         if (pos != Position.NOPOS)
  2466             storeEnd(mods, S.prevToken().endPos);
  2467         return mods;
  2470     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2471      * @param pos position of "@" token
  2472      */
  2473     JCAnnotation annotation(int pos) {
  2474         // accept(AT); // AT consumed by caller
  2475         checkAnnotations();
  2476         JCTree ident = qualident();
  2477         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2478         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2479         storeEnd(ann, S.prevToken().endPos);
  2480         return ann;
  2483     List<JCExpression> annotationFieldValuesOpt() {
  2484         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2487     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2488     List<JCExpression> annotationFieldValues() {
  2489         accept(LPAREN);
  2490         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2491         if (token.kind != RPAREN) {
  2492             buf.append(annotationFieldValue());
  2493             while (token.kind == COMMA) {
  2494                 nextToken();
  2495                 buf.append(annotationFieldValue());
  2498         accept(RPAREN);
  2499         return buf.toList();
  2502     /** AnnotationFieldValue    = AnnotationValue
  2503      *                          | Identifier "=" AnnotationValue
  2504      */
  2505     JCExpression annotationFieldValue() {
  2506         if (token.kind == IDENTIFIER) {
  2507             mode = EXPR;
  2508             JCExpression t1 = term1();
  2509             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2510                 int pos = token.pos;
  2511                 accept(EQ);
  2512                 JCExpression v = annotationValue();
  2513                 return toP(F.at(pos).Assign(t1, v));
  2514             } else {
  2515                 return t1;
  2518         return annotationValue();
  2521     /* AnnotationValue          = ConditionalExpression
  2522      *                          | Annotation
  2523      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2524      */
  2525     JCExpression annotationValue() {
  2526         int pos;
  2527         switch (token.kind) {
  2528         case MONKEYS_AT:
  2529             pos = token.pos;
  2530             nextToken();
  2531             return annotation(pos);
  2532         case LBRACE:
  2533             pos = token.pos;
  2534             accept(LBRACE);
  2535             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2536             if (token.kind != RBRACE) {
  2537                 buf.append(annotationValue());
  2538                 while (token.kind == COMMA) {
  2539                     nextToken();
  2540                     if (token.kind == RBRACE) break;
  2541                     buf.append(annotationValue());
  2544             accept(RBRACE);
  2545             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2546         default:
  2547             mode = EXPR;
  2548             return term1();
  2552     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2553      */
  2554     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2555                                                                          JCExpression type,
  2556                                                                          T vdefs)
  2558         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2561     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2562      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2564      *  @param reqInit  Is an initializer always required?
  2565      *  @param dc       The documentation comment for the variable declarations, or null.
  2566      */
  2567     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2568                                                                      JCModifiers mods,
  2569                                                                      JCExpression type,
  2570                                                                      Name name,
  2571                                                                      boolean reqInit,
  2572                                                                      Comment dc,
  2573                                                                      T vdefs)
  2575         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2576         while (token.kind == COMMA) {
  2577             // All but last of multiple declarators subsume a comma
  2578             storeEnd((JCTree)vdefs.last(), token.endPos);
  2579             nextToken();
  2580             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2582         return vdefs;
  2585     /** VariableDeclarator = Ident VariableDeclaratorRest
  2586      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2587      */
  2588     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2589         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2592     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2593      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2595      *  @param reqInit  Is an initializer always required?
  2596      *  @param dc       The documentation comment for the variable declarations, or null.
  2597      */
  2598     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2599                                   boolean reqInit, Comment dc) {
  2600         type = bracketsOpt(type);
  2601         JCExpression init = null;
  2602         if (token.kind == EQ) {
  2603             nextToken();
  2604             init = variableInitializer();
  2606         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2607         JCVariableDecl result =
  2608             toP(F.at(pos).VarDef(mods, name, type, init));
  2609         attach(result, dc);
  2610         return result;
  2613     /** VariableDeclaratorId = Ident BracketsOpt
  2614      */
  2615     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2616         return variableDeclaratorId(mods, type, false);
  2618     //where
  2619     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
  2620         int pos = token.pos;
  2621         Name name;
  2622         if (lambdaParameter && token.kind == UNDERSCORE) {
  2623             syntaxError(pos, "expected", IDENTIFIER);
  2624             name = token.name();
  2625         } else {
  2626             name = ident();
  2628         if ((mods.flags & Flags.VARARGS) != 0 &&
  2629                 token.kind == LBRACKET) {
  2630             log.error(token.pos, "varargs.and.old.array.syntax");
  2632         type = bracketsOpt(type);
  2633         return toP(F.at(pos).VarDef(mods, name, type, null));
  2636     /** Resources = Resource { ";" Resources }
  2637      */
  2638     List<JCTree> resources() {
  2639         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2640         defs.append(resource());
  2641         while (token.kind == SEMI) {
  2642             // All but last of multiple declarators must subsume a semicolon
  2643             storeEnd(defs.last(), token.endPos);
  2644             int semiColonPos = token.pos;
  2645             nextToken();
  2646             if (token.kind == RPAREN) { // Optional trailing semicolon
  2647                                        // after last resource
  2648                 break;
  2650             defs.append(resource());
  2652         return defs.toList();
  2655     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2656      */
  2657     protected JCTree resource() {
  2658         JCModifiers optFinal = optFinal(Flags.FINAL);
  2659         JCExpression type = parseType();
  2660         int pos = token.pos;
  2661         Name ident = ident();
  2662         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2665     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2666      */
  2667     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2668         Token firstToken = token;
  2669         JCExpression pid = null;
  2670         JCModifiers mods = null;
  2671         boolean consumedToplevelDoc = false;
  2672         boolean seenImport = false;
  2673         boolean seenPackage = false;
  2674         List<JCAnnotation> packageAnnotations = List.nil();
  2675         if (token.kind == MONKEYS_AT)
  2676             mods = modifiersOpt();
  2678         if (token.kind == PACKAGE) {
  2679             seenPackage = true;
  2680             if (mods != null) {
  2681                 checkNoMods(mods.flags);
  2682                 packageAnnotations = mods.annotations;
  2683                 mods = null;
  2685             nextToken();
  2686             pid = qualident();
  2687             accept(SEMI);
  2689         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2690         boolean checkForImports = true;
  2691         boolean firstTypeDecl = true;
  2692         while (token.kind != EOF) {
  2693             if (token.pos <= endPosTable.errorEndPos) {
  2694                 // error recovery
  2695                 skip(checkForImports, false, false, false);
  2696                 if (token.kind == EOF)
  2697                     break;
  2699             if (checkForImports && mods == null && token.kind == IMPORT) {
  2700                 seenImport = true;
  2701                 defs.append(importDeclaration());
  2702             } else {
  2703                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  2704                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2705                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2706                     consumedToplevelDoc = true;
  2708                 JCTree def = typeDeclaration(mods, docComment);
  2709                 if (def instanceof JCExpressionStatement)
  2710                     def = ((JCExpressionStatement)def).expr;
  2711                 defs.append(def);
  2712                 if (def instanceof JCClassDecl)
  2713                     checkForImports = false;
  2714                 mods = null;
  2715                 firstTypeDecl = false;
  2718         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2719         if (!consumedToplevelDoc)
  2720             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2721         if (defs.isEmpty())
  2722             storeEnd(toplevel, S.prevToken().endPos);
  2723         if (keepDocComments)
  2724             toplevel.docComments = docComments;
  2725         if (keepLineMap)
  2726             toplevel.lineMap = S.getLineMap();
  2727         toplevel.endPositions = this.endPosTable;
  2728         return toplevel;
  2731     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2732      */
  2733     JCTree importDeclaration() {
  2734         int pos = token.pos;
  2735         nextToken();
  2736         boolean importStatic = false;
  2737         if (token.kind == STATIC) {
  2738             checkStaticImports();
  2739             importStatic = true;
  2740             nextToken();
  2742         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2743         do {
  2744             int pos1 = token.pos;
  2745             accept(DOT);
  2746             if (token.kind == STAR) {
  2747                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2748                 nextToken();
  2749                 break;
  2750             } else {
  2751                 pid = toP(F.at(pos1).Select(pid, ident()));
  2753         } while (token.kind == DOT);
  2754         accept(SEMI);
  2755         return toP(F.at(pos).Import(pid, importStatic));
  2758     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2759      *                  | ";"
  2760      */
  2761     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  2762         int pos = token.pos;
  2763         if (mods == null && token.kind == SEMI) {
  2764             nextToken();
  2765             return toP(F.at(pos).Skip());
  2766         } else {
  2767             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2771     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2772      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2773      *  @param mods     Any modifiers starting the class or interface declaration
  2774      *  @param dc       The documentation comment for the class, or null.
  2775      */
  2776     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  2777         if (token.kind == CLASS) {
  2778             return classDeclaration(mods, dc);
  2779         } else if (token.kind == INTERFACE) {
  2780             return interfaceDeclaration(mods, dc);
  2781         } else if (allowEnums) {
  2782             if (token.kind == ENUM) {
  2783                 return enumDeclaration(mods, dc);
  2784             } else {
  2785                 int pos = token.pos;
  2786                 List<JCTree> errs;
  2787                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  2788                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2789                     setErrorEndPos(token.pos);
  2790                 } else {
  2791                     errs = List.<JCTree>of(mods);
  2793                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2794                                               CLASS, INTERFACE, ENUM)));
  2796         } else {
  2797             if (token.kind == ENUM) {
  2798                 error(token.pos, "enums.not.supported.in.source", source.name);
  2799                 allowEnums = true;
  2800                 return enumDeclaration(mods, dc);
  2802             int pos = token.pos;
  2803             List<JCTree> errs;
  2804             if (LAX_IDENTIFIER.accepts(token.kind)) {
  2805                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2806                 setErrorEndPos(token.pos);
  2807             } else {
  2808                 errs = List.<JCTree>of(mods);
  2810             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2811                                           CLASS, INTERFACE)));
  2815     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2816      *                     [IMPLEMENTS TypeList] ClassBody
  2817      *  @param mods    The modifiers starting the class declaration
  2818      *  @param dc       The documentation comment for the class, or null.
  2819      */
  2820     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  2821         int pos = token.pos;
  2822         accept(CLASS);
  2823         Name name = ident();
  2825         List<JCTypeParameter> typarams = typeParametersOpt();
  2827         JCExpression extending = null;
  2828         if (token.kind == EXTENDS) {
  2829             nextToken();
  2830             extending = parseType();
  2832         List<JCExpression> implementing = List.nil();
  2833         if (token.kind == IMPLEMENTS) {
  2834             nextToken();
  2835             implementing = typeList();
  2837         List<JCTree> defs = classOrInterfaceBody(name, false);
  2838         JCClassDecl result = toP(F.at(pos).ClassDef(
  2839             mods, name, typarams, extending, implementing, defs));
  2840         attach(result, dc);
  2841         return result;
  2844     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2845      *                         [EXTENDS TypeList] InterfaceBody
  2846      *  @param mods    The modifiers starting the interface declaration
  2847      *  @param dc       The documentation comment for the interface, or null.
  2848      */
  2849     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  2850         int pos = token.pos;
  2851         accept(INTERFACE);
  2852         Name name = ident();
  2854         List<JCTypeParameter> typarams = typeParametersOpt();
  2856         List<JCExpression> extending = List.nil();
  2857         if (token.kind == EXTENDS) {
  2858             nextToken();
  2859             extending = typeList();
  2861         List<JCTree> defs = classOrInterfaceBody(name, true);
  2862         JCClassDecl result = toP(F.at(pos).ClassDef(
  2863             mods, name, typarams, null, extending, defs));
  2864         attach(result, dc);
  2865         return result;
  2868     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2869      *  @param mods    The modifiers starting the enum declaration
  2870      *  @param dc       The documentation comment for the enum, or null.
  2871      */
  2872     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  2873         int pos = token.pos;
  2874         accept(ENUM);
  2875         Name name = ident();
  2877         List<JCExpression> implementing = List.nil();
  2878         if (token.kind == IMPLEMENTS) {
  2879             nextToken();
  2880             implementing = typeList();
  2883         List<JCTree> defs = enumBody(name);
  2884         mods.flags |= Flags.ENUM;
  2885         JCClassDecl result = toP(F.at(pos).
  2886             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2887                 null, implementing, defs));
  2888         attach(result, dc);
  2889         return result;
  2892     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2893      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2894      */
  2895     List<JCTree> enumBody(Name enumName) {
  2896         accept(LBRACE);
  2897         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2898         if (token.kind == COMMA) {
  2899             nextToken();
  2900         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2901             defs.append(enumeratorDeclaration(enumName));
  2902             while (token.kind == COMMA) {
  2903                 nextToken();
  2904                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2905                 defs.append(enumeratorDeclaration(enumName));
  2907             if (token.kind != SEMI && token.kind != RBRACE) {
  2908                 defs.append(syntaxError(token.pos, "expected3",
  2909                                 COMMA, RBRACE, SEMI));
  2910                 nextToken();
  2913         if (token.kind == SEMI) {
  2914             nextToken();
  2915             while (token.kind != RBRACE && token.kind != EOF) {
  2916                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2917                                                                 false));
  2918                 if (token.pos <= endPosTable.errorEndPos) {
  2919                     // error recovery
  2920                    skip(false, true, true, false);
  2924         accept(RBRACE);
  2925         return defs.toList();
  2928     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2929      */
  2930     JCTree enumeratorDeclaration(Name enumName) {
  2931         Comment dc = token.comment(CommentStyle.JAVADOC);
  2932         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2933         if (token.deprecatedFlag()) {
  2934             flags |= Flags.DEPRECATED;
  2936         int pos = token.pos;
  2937         List<JCAnnotation> annotations = annotationsOpt();
  2938         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2939         List<JCExpression> typeArgs = typeArgumentsOpt();
  2940         int identPos = token.pos;
  2941         Name name = ident();
  2942         int createPos = token.pos;
  2943         List<JCExpression> args = (token.kind == LPAREN)
  2944             ? arguments() : List.<JCExpression>nil();
  2945         JCClassDecl body = null;
  2946         if (token.kind == LBRACE) {
  2947             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2948             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2949             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2951         if (args.isEmpty() && body == null)
  2952             createPos = identPos;
  2953         JCIdent ident = F.at(identPos).Ident(enumName);
  2954         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2955         if (createPos != identPos)
  2956             storeEnd(create, S.prevToken().endPos);
  2957         ident = F.at(identPos).Ident(enumName);
  2958         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2959         attach(result, dc);
  2960         return result;
  2963     /** TypeList = Type {"," Type}
  2964      */
  2965     List<JCExpression> typeList() {
  2966         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2967         ts.append(parseType());
  2968         while (token.kind == COMMA) {
  2969             nextToken();
  2970             ts.append(parseType());
  2972         return ts.toList();
  2975     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2976      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2977      */
  2978     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2979         accept(LBRACE);
  2980         if (token.pos <= endPosTable.errorEndPos) {
  2981             // error recovery
  2982             skip(false, true, false, false);
  2983             if (token.kind == LBRACE)
  2984                 nextToken();
  2986         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2987         while (token.kind != RBRACE && token.kind != EOF) {
  2988             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2989             if (token.pos <= endPosTable.errorEndPos) {
  2990                // error recovery
  2991                skip(false, true, true, false);
  2994         accept(RBRACE);
  2995         return defs.toList();
  2998     /** ClassBodyDeclaration =
  2999      *      ";"
  3000      *    | [STATIC] Block
  3001      *    | ModifiersOpt
  3002      *      ( Type Ident
  3003      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  3004      *      | VOID Ident MethodDeclaratorRest
  3005      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  3006      *      | Ident ConstructorDeclaratorRest
  3007      *      | TypeParameters Ident ConstructorDeclaratorRest
  3008      *      | ClassOrInterfaceOrEnumDeclaration
  3009      *      )
  3010      *  InterfaceBodyDeclaration =
  3011      *      ";"
  3012      *    | ModifiersOpt Type Ident
  3013      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  3014      */
  3015     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  3016         if (token.kind == SEMI) {
  3017             nextToken();
  3018             return List.<JCTree>nil();
  3019         } else {
  3020             Comment dc = token.comment(CommentStyle.JAVADOC);
  3021             int pos = token.pos;
  3022             JCModifiers mods = modifiersOpt();
  3023             if (token.kind == CLASS ||
  3024                 token.kind == INTERFACE ||
  3025                 allowEnums && token.kind == ENUM) {
  3026                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  3027             } else if (token.kind == LBRACE && !isInterface &&
  3028                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  3029                        mods.annotations.isEmpty()) {
  3030                 return List.<JCTree>of(block(pos, mods.flags));
  3031             } else {
  3032                 pos = token.pos;
  3033                 List<JCTypeParameter> typarams = typeParametersOpt();
  3034                 // if there are type parameters but no modifiers, save the start
  3035                 // position of the method in the modifiers.
  3036                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  3037                     mods.pos = pos;
  3038                     storeEnd(mods, pos);
  3040                 Token tk = token;
  3041                 pos = token.pos;
  3042                 JCExpression type;
  3043                 boolean isVoid = token.kind == VOID;
  3044                 if (isVoid) {
  3045                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
  3046                     nextToken();
  3047                 } else {
  3048                     type = parseType();
  3050                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  3051                     if (isInterface || tk.name() != className)
  3052                         error(pos, "invalid.meth.decl.ret.type.req");
  3053                     return List.of(methodDeclaratorRest(
  3054                         pos, mods, null, names.init, typarams,
  3055                         isInterface, true, dc));
  3056                 } else {
  3057                     pos = token.pos;
  3058                     Name name = ident();
  3059                     if (token.kind == LPAREN) {
  3060                         return List.of(methodDeclaratorRest(
  3061                             pos, mods, type, name, typarams,
  3062                             isInterface, isVoid, dc));
  3063                     } else if (!isVoid && typarams.isEmpty()) {
  3064                         List<JCTree> defs =
  3065                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  3066                                                     new ListBuffer<JCTree>()).toList();
  3067                         storeEnd(defs.last(), token.endPos);
  3068                         accept(SEMI);
  3069                         return defs;
  3070                     } else {
  3071                         pos = token.pos;
  3072                         List<JCTree> err = isVoid
  3073                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3074                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  3075                             : null;
  3076                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  3083     /** MethodDeclaratorRest =
  3084      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  3085      *  VoidMethodDeclaratorRest =
  3086      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  3087      *  InterfaceMethodDeclaratorRest =
  3088      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  3089      *  VoidInterfaceMethodDeclaratorRest =
  3090      *      FormalParameters [THROWS TypeList] ";"
  3091      *  ConstructorDeclaratorRest =
  3092      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  3093      */
  3094     protected JCTree methodDeclaratorRest(int pos,
  3095                               JCModifiers mods,
  3096                               JCExpression type,
  3097                               Name name,
  3098                               List<JCTypeParameter> typarams,
  3099                               boolean isInterface, boolean isVoid,
  3100                               Comment dc) {
  3101         if (isInterface && (mods.flags & Flags.STATIC) != 0) {
  3102             checkStaticInterfaceMethods();
  3104         List<JCVariableDecl> params = formalParameters();
  3105         if (!isVoid) type = bracketsOpt(type);
  3106         List<JCExpression> thrown = List.nil();
  3107         if (token.kind == THROWS) {
  3108             nextToken();
  3109             thrown = qualidentList();
  3111         JCBlock body = null;
  3112         JCExpression defaultValue;
  3113         if (token.kind == LBRACE) {
  3114             body = block();
  3115             defaultValue = null;
  3116         } else {
  3117             if (token.kind == DEFAULT) {
  3118                 accept(DEFAULT);
  3119                 defaultValue = annotationValue();
  3120             } else {
  3121                 defaultValue = null;
  3123             accept(SEMI);
  3124             if (token.pos <= endPosTable.errorEndPos) {
  3125                 // error recovery
  3126                 skip(false, true, false, false);
  3127                 if (token.kind == LBRACE) {
  3128                     body = block();
  3133         JCMethodDecl result =
  3134             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3135                                     params, thrown,
  3136                                     body, defaultValue));
  3137         attach(result, dc);
  3138         return result;
  3141     /** QualidentList = Qualident {"," Qualident}
  3142      */
  3143     List<JCExpression> qualidentList() {
  3144         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3145         ts.append(qualident());
  3146         while (token.kind == COMMA) {
  3147             nextToken();
  3148             ts.append(qualident());
  3150         return ts.toList();
  3153     /**
  3154      *  {@literal
  3155      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3156      *  }
  3157      */
  3158     List<JCTypeParameter> typeParametersOpt() {
  3159         if (token.kind == LT) {
  3160             checkGenerics();
  3161             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3162             nextToken();
  3163             typarams.append(typeParameter());
  3164             while (token.kind == COMMA) {
  3165                 nextToken();
  3166                 typarams.append(typeParameter());
  3168             accept(GT);
  3169             return typarams.toList();
  3170         } else {
  3171             return List.nil();
  3175     /**
  3176      *  {@literal
  3177      *  TypeParameter = TypeVariable [TypeParameterBound]
  3178      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3179      *  TypeVariable = Ident
  3180      *  }
  3181      */
  3182     JCTypeParameter typeParameter() {
  3183         int pos = token.pos;
  3184         Name name = ident();
  3185         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3186         if (token.kind == EXTENDS) {
  3187             nextToken();
  3188             bounds.append(parseType());
  3189             while (token.kind == AMP) {
  3190                 nextToken();
  3191                 bounds.append(parseType());
  3194         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  3197     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3198      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3199      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3200      */
  3201     List<JCVariableDecl> formalParameters() {
  3202         return formalParameters(false);
  3204     List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
  3205         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3206         JCVariableDecl lastParam = null;
  3207         accept(LPAREN);
  3208         if (token.kind != RPAREN) {
  3209             params.append(lastParam = formalParameter(lambdaParameters));
  3210             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3211                 nextToken();
  3212                 params.append(lastParam = formalParameter(lambdaParameters));
  3215         accept(RPAREN);
  3216         return params.toList();
  3219     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3220         if (hasParens) {
  3221             accept(LPAREN);
  3223         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3224         if (token.kind != RPAREN && token.kind != ARROW) {
  3225             params.append(implicitParameter());
  3226             while (token.kind == COMMA) {
  3227                 nextToken();
  3228                 params.append(implicitParameter());
  3231         if (hasParens) {
  3232             accept(RPAREN);
  3234         return params.toList();
  3237     JCModifiers optFinal(long flags) {
  3238         JCModifiers mods = modifiersOpt();
  3239         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3240         mods.flags |= flags;
  3241         return mods;
  3244     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3245      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3246      */
  3247     protected JCVariableDecl formalParameter() {
  3248         return formalParameter(false);
  3250     protected JCVariableDecl formalParameter(boolean lambdaParameter) {
  3251         JCModifiers mods = optFinal(Flags.PARAMETER);
  3252         JCExpression type = parseType();
  3253         if (token.kind == ELLIPSIS) {
  3254             checkVarargs();
  3255             mods.flags |= Flags.VARARGS;
  3256             type = to(F.at(token.pos).TypeArray(type));
  3257             nextToken();
  3259         return variableDeclaratorId(mods, type, lambdaParameter);
  3262     protected JCVariableDecl implicitParameter() {
  3263         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3264         return variableDeclaratorId(mods, null, true);
  3267 /* ---------- auxiliary methods -------------- */
  3269     void error(int pos, String key, Object ... args) {
  3270         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3273     void error(DiagnosticPosition pos, String key, Object ... args) {
  3274         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3277     void warning(int pos, String key, Object ... args) {
  3278         log.warning(pos, key, args);
  3281     /** Check that given tree is a legal expression statement.
  3282      */
  3283     protected JCExpression checkExprStat(JCExpression t) {
  3284         if (!TreeInfo.isExpressionStatement(t)) {
  3285             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3286             error(ret, "not.stmt");
  3287             return ret;
  3288         } else {
  3289             return t;
  3293     /** Return precedence of operator represented by token,
  3294      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3295      */
  3296     static int prec(TokenKind token) {
  3297         JCTree.Tag oc = optag(token);
  3298         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3301     /**
  3302      * Return the lesser of two positions, making allowance for either one
  3303      * being unset.
  3304      */
  3305     static int earlier(int pos1, int pos2) {
  3306         if (pos1 == Position.NOPOS)
  3307             return pos2;
  3308         if (pos2 == Position.NOPOS)
  3309             return pos1;
  3310         return (pos1 < pos2 ? pos1 : pos2);
  3313     /** Return operation tag of binary operator represented by token,
  3314      *  No_TAG if token is not a binary operator.
  3315      */
  3316     static JCTree.Tag optag(TokenKind token) {
  3317         switch (token) {
  3318         case BARBAR:
  3319             return OR;
  3320         case AMPAMP:
  3321             return AND;
  3322         case BAR:
  3323             return BITOR;
  3324         case BAREQ:
  3325             return BITOR_ASG;
  3326         case CARET:
  3327             return BITXOR;
  3328         case CARETEQ:
  3329             return BITXOR_ASG;
  3330         case AMP:
  3331             return BITAND;
  3332         case AMPEQ:
  3333             return BITAND_ASG;
  3334         case EQEQ:
  3335             return JCTree.Tag.EQ;
  3336         case BANGEQ:
  3337             return NE;
  3338         case LT:
  3339             return JCTree.Tag.LT;
  3340         case GT:
  3341             return JCTree.Tag.GT;
  3342         case LTEQ:
  3343             return LE;
  3344         case GTEQ:
  3345             return GE;
  3346         case LTLT:
  3347             return SL;
  3348         case LTLTEQ:
  3349             return SL_ASG;
  3350         case GTGT:
  3351             return SR;
  3352         case GTGTEQ:
  3353             return SR_ASG;
  3354         case GTGTGT:
  3355             return USR;
  3356         case GTGTGTEQ:
  3357             return USR_ASG;
  3358         case PLUS:
  3359             return JCTree.Tag.PLUS;
  3360         case PLUSEQ:
  3361             return PLUS_ASG;
  3362         case SUB:
  3363             return MINUS;
  3364         case SUBEQ:
  3365             return MINUS_ASG;
  3366         case STAR:
  3367             return MUL;
  3368         case STAREQ:
  3369             return MUL_ASG;
  3370         case SLASH:
  3371             return DIV;
  3372         case SLASHEQ:
  3373             return DIV_ASG;
  3374         case PERCENT:
  3375             return MOD;
  3376         case PERCENTEQ:
  3377             return MOD_ASG;
  3378         case INSTANCEOF:
  3379             return TYPETEST;
  3380         default:
  3381             return NO_TAG;
  3385     /** Return operation tag of unary operator represented by token,
  3386      *  No_TAG if token is not a binary operator.
  3387      */
  3388     static JCTree.Tag unoptag(TokenKind token) {
  3389         switch (token) {
  3390         case PLUS:
  3391             return POS;
  3392         case SUB:
  3393             return NEG;
  3394         case BANG:
  3395             return NOT;
  3396         case TILDE:
  3397             return COMPL;
  3398         case PLUSPLUS:
  3399             return PREINC;
  3400         case SUBSUB:
  3401             return PREDEC;
  3402         default:
  3403             return NO_TAG;
  3407     /** Return type tag of basic type represented by token,
  3408      *  NONE if token is not a basic type identifier.
  3409      */
  3410     static TypeTag typetag(TokenKind token) {
  3411         switch (token) {
  3412         case BYTE:
  3413             return TypeTag.BYTE;
  3414         case CHAR:
  3415             return TypeTag.CHAR;
  3416         case SHORT:
  3417             return TypeTag.SHORT;
  3418         case INT:
  3419             return TypeTag.INT;
  3420         case LONG:
  3421             return TypeTag.LONG;
  3422         case FLOAT:
  3423             return TypeTag.FLOAT;
  3424         case DOUBLE:
  3425             return TypeTag.DOUBLE;
  3426         case BOOLEAN:
  3427             return TypeTag.BOOLEAN;
  3428         default:
  3429             return TypeTag.NONE;
  3433     void checkGenerics() {
  3434         if (!allowGenerics) {
  3435             error(token.pos, "generics.not.supported.in.source", source.name);
  3436             allowGenerics = true;
  3439     void checkVarargs() {
  3440         if (!allowVarargs) {
  3441             error(token.pos, "varargs.not.supported.in.source", source.name);
  3442             allowVarargs = true;
  3445     void checkForeach() {
  3446         if (!allowForeach) {
  3447             error(token.pos, "foreach.not.supported.in.source", source.name);
  3448             allowForeach = true;
  3451     void checkStaticImports() {
  3452         if (!allowStaticImport) {
  3453             error(token.pos, "static.import.not.supported.in.source", source.name);
  3454             allowStaticImport = true;
  3457     void checkAnnotations() {
  3458         if (!allowAnnotations) {
  3459             error(token.pos, "annotations.not.supported.in.source", source.name);
  3460             allowAnnotations = true;
  3463     void checkDiamond() {
  3464         if (!allowDiamond) {
  3465             error(token.pos, "diamond.not.supported.in.source", source.name);
  3466             allowDiamond = true;
  3469     void checkMulticatch() {
  3470         if (!allowMulticatch) {
  3471             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3472             allowMulticatch = true;
  3475     void checkTryWithResources() {
  3476         if (!allowTWR) {
  3477             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3478             allowTWR = true;
  3481     void checkLambda() {
  3482         if (!allowLambda) {
  3483             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3484             allowLambda = true;
  3487     void checkMethodReferences() {
  3488         if (!allowMethodReferences) {
  3489             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3490             allowMethodReferences = true;
  3493     void checkDefaultMethods() {
  3494         if (!allowDefaultMethods) {
  3495             log.error(token.pos, "default.methods.not.supported.in.source", source.name);
  3496             allowDefaultMethods = true;
  3499     void checkIntersectionTypesInCast() {
  3500         if (!allowIntersectionTypesInCast) {
  3501             log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
  3502             allowIntersectionTypesInCast = true;
  3505     void checkStaticInterfaceMethods() {
  3506         if (!allowStaticInterfaceMethods) {
  3507             log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name);
  3508             allowStaticInterfaceMethods = true;
  3512     /*
  3513      * a functional source tree and end position mappings
  3514      */
  3515     protected class SimpleEndPosTable extends AbstractEndPosTable {
  3517         private final Map<JCTree, Integer> endPosMap;
  3519         SimpleEndPosTable() {
  3520             endPosMap = new HashMap<JCTree, Integer>();
  3523         protected void storeEnd(JCTree tree, int endpos) {
  3524             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  3527         protected <T extends JCTree> T to(T t) {
  3528             storeEnd(t, token.endPos);
  3529             return t;
  3532         protected <T extends JCTree> T toP(T t) {
  3533             storeEnd(t, S.prevToken().endPos);
  3534             return t;
  3537         public int getEndPos(JCTree tree) {
  3538             Integer value = endPosMap.get(tree);
  3539             return (value == null) ? Position.NOPOS : value;
  3542         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3543             Integer pos = endPosMap.remove(oldTree);
  3544             if (pos != null) {
  3545                 endPosMap.put(newTree, pos);
  3546                 return pos;
  3548             return Position.NOPOS;
  3552     /*
  3553      * a default skeletal implementation without any mapping overhead.
  3554      */
  3555     protected class EmptyEndPosTable extends AbstractEndPosTable {
  3557         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  3559         protected <T extends JCTree> T to(T t) {
  3560             return t;
  3563         protected <T extends JCTree> T toP(T t) {
  3564             return t;
  3567         public int getEndPos(JCTree tree) {
  3568             return Position.NOPOS;
  3571         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3572             return Position.NOPOS;
  3577     protected abstract class AbstractEndPosTable implements EndPosTable {
  3579         /**
  3580          * Store the last error position.
  3581          */
  3582         protected int errorEndPos;
  3584         /**
  3585          * Store ending position for a tree, the value of which is the greater
  3586          * of last error position and the given ending position.
  3587          * @param tree   The tree.
  3588          * @param endpos The ending position to associate with the tree.
  3589          */
  3590         protected abstract void storeEnd(JCTree tree, int endpos);
  3592         /**
  3593          * Store current token's ending position for a tree, the value of which
  3594          * will be the greater of last error position and the ending position of
  3595          * the current token.
  3596          * @param t The tree.
  3597          */
  3598         protected abstract <T extends JCTree> T to(T t);
  3600         /**
  3601          * Store current token's ending position for a tree, the value of which
  3602          * will be the greater of last error position and the ending position of
  3603          * the previous token.
  3604          * @param t The tree.
  3605          */
  3606         protected abstract <T extends JCTree> T toP(T t);
  3608         /**
  3609          * Set the error position during the parsing phases, the value of which
  3610          * will be set only if it is greater than the last stored error position.
  3611          * @param errPos The error position
  3612          */
  3613         protected void setErrorEndPos(int errPos) {
  3614             if (errPos > errorEndPos) {
  3615                 errorEndPos = errPos;

mercurial