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

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

     1 /*
     2  * Copyright (c) 1999, 2013, 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.*;
    52 /** The parser maps a token sequence into an abstract syntax
    53  *  tree. It operates by recursive descent, with code derived
    54  *  systematically from an LL(1) grammar. For efficiency reasons, an
    55  *  operator precedence scheme is used for parsing binary operation
    56  *  expressions.
    57  *
    58  *  <p><b>This is NOT part of any supported API.
    59  *  If you write code that depends on this, you do so at your own risk.
    60  *  This code and its internal interfaces are subject to change or
    61  *  deletion without notice.</b>
    62  */
    63 public class JavacParser implements Parser {
    65     /** The number of precedence levels of infix operators.
    66      */
    67     private static final int infixPrecedenceLevels = 10;
    69     /** The scanner used for lexical analysis.
    70      */
    71     protected Lexer S;
    73     /** The factory to be used for abstract syntax tree construction.
    74      */
    75     protected TreeMaker F;
    77     /** The log to be used for error diagnostics.
    78      */
    79     private Log log;
    81     /** The Source language setting. */
    82     private Source source;
    84     /** The name table. */
    85     private Names names;
    87     /** End position mappings container */
    88     private final AbstractEndPosTable endPosTable;
    90     // Because of javac's limited lookahead, some contexts are ambiguous in
    91     // the presence of type annotations even though they are not ambiguous
    92     // in the absence of type annotations.  Consider this code:
    93     //   void m(String [] m) { }
    94     //   void m(String ... m) { }
    95     // After parsing "String", javac calls bracketsOpt which immediately
    96     // returns if the next character is not '['.  Similarly, javac can see
    97     // if the next token is ... and in that case parse an ellipsis.  But in
    98     // the presence of type annotations:
    99     //   void m(String @A [] m) { }
   100     //   void m(String @A ... m) { }
   101     // no finite lookahead is enough to determine whether to read array
   102     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
   103     // bracketsOpt first reads all the leading annotations and only then
   104     // discovers that it needs to fail.  bracketsOpt needs a way to push
   105     // back the extra annotations that it read.  (But, bracketsOpt should
   106     // not *always* be allowed to push back extra annotations that it finds
   107     // -- in most contexts, any such extra annotation is an error.
   108     //
   109     // The following two variables permit type annotations that have
   110     // already been read to be stored for later use.  Alternate
   111     // implementations are possible but would cause much larger changes to
   112     // the parser.
   114     /** Type annotations that have already been read but have not yet been used. **/
   115     private List<JCAnnotation> typeAnnotationsPushedBack = List.nil();
   117     /**
   118      * If the parser notices extra annotations, then it either immediately
   119      * issues an error (if this variable is false) or places the extra
   120      * annotations in variable typeAnnotationsPushedBack (if this variable
   121      * is true).
   122      */
   123     private boolean permitTypeAnnotationsPushBack = false;
   125     interface ErrorRecoveryAction {
   126         JCTree doRecover(JavacParser parser);
   127     }
   129     enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
   130         BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
   131         CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
   132     }
   134     /** Construct a parser from a given scanner, tree factory and log.
   135      */
   136     protected JavacParser(ParserFactory fac,
   137                      Lexer S,
   138                      boolean keepDocComments,
   139                      boolean keepLineMap,
   140                      boolean keepEndPositions) {
   141         this.S = S;
   142         nextToken(); // prime the pump
   143         this.F = fac.F;
   144         this.log = fac.log;
   145         this.names = fac.names;
   146         this.source = fac.source;
   147         this.allowGenerics = source.allowGenerics();
   148         this.allowVarargs = source.allowVarargs();
   149         this.allowAsserts = source.allowAsserts();
   150         this.allowEnums = source.allowEnums();
   151         this.allowForeach = source.allowForeach();
   152         this.allowStaticImport = source.allowStaticImport();
   153         this.allowAnnotations = source.allowAnnotations();
   154         this.allowTWR = source.allowTryWithResources();
   155         this.allowDiamond = source.allowDiamond();
   156         this.allowMulticatch = source.allowMulticatch();
   157         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   158         this.allowLambda = source.allowLambda();
   159         this.allowMethodReferences = source.allowMethodReferences();
   160         this.allowDefaultMethods = source.allowDefaultMethods();
   161         this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
   162         this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
   163         this.allowTypeAnnotations = source.allowTypeAnnotations();
   164         this.allowAnnotationsAfterTypeParams = source.allowAnnotationsAfterTypeParams();
   165         this.keepDocComments = keepDocComments;
   166         docComments = newDocCommentTable(keepDocComments, fac);
   167         this.keepLineMap = keepLineMap;
   168         this.errorTree = F.Erroneous();
   169         endPosTable = newEndPosTable(keepEndPositions);
   170     }
   172     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
   173         return  keepEndPositions
   174                 ? new SimpleEndPosTable(this)
   175                 : new EmptyEndPosTable(this);
   176     }
   178     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
   179         return keepDocComments ? new LazyDocCommentTable(fac) : null;
   180     }
   182     /** Switch: Should generics be recognized?
   183      */
   184     boolean allowGenerics;
   186     /** Switch: Should diamond operator be recognized?
   187      */
   188     boolean allowDiamond;
   190     /** Switch: Should multicatch clause be accepted?
   191      */
   192     boolean allowMulticatch;
   194     /** Switch: Should varargs be recognized?
   195      */
   196     boolean allowVarargs;
   198     /** Switch: should we recognize assert statements, or just give a warning?
   199      */
   200     boolean allowAsserts;
   202     /** Switch: should we recognize enums, or just give a warning?
   203      */
   204     boolean allowEnums;
   206     /** Switch: should we recognize foreach?
   207      */
   208     boolean allowForeach;
   210     /** Switch: should we recognize foreach?
   211      */
   212     boolean allowStaticImport;
   214     /** Switch: should we recognize annotations?
   215      */
   216     boolean allowAnnotations;
   218     /** Switch: should we recognize try-with-resources?
   219      */
   220     boolean allowTWR;
   222     /** Switch: should we fold strings?
   223      */
   224     boolean allowStringFolding;
   226     /** Switch: should we recognize lambda expressions?
   227      */
   228     boolean allowLambda;
   230     /** Switch: should we allow method/constructor references?
   231      */
   232     boolean allowMethodReferences;
   234     /** Switch: should we allow default methods in interfaces?
   235      */
   236     boolean allowDefaultMethods;
   238     /** Switch: should we allow static methods in interfaces?
   239      */
   240     boolean allowStaticInterfaceMethods;
   242     /** Switch: should we allow intersection types in cast?
   243      */
   244     boolean allowIntersectionTypesInCast;
   246     /** Switch: should we keep docComments?
   247      */
   248     boolean keepDocComments;
   250     /** Switch: should we keep line table?
   251      */
   252     boolean keepLineMap;
   254     /** Switch: should we recognize type annotations?
   255      */
   256     boolean allowTypeAnnotations;
   258     /** Switch: should we allow annotations after the method type parameters?
   259      */
   260     boolean allowAnnotationsAfterTypeParams;
   262     /** Switch: is "this" allowed as an identifier?
   263      * This is needed to parse receiver types.
   264      */
   265     boolean allowThisIdent;
   267     /** The type of the method receiver, as specified by a first "this" parameter.
   268      */
   269     JCVariableDecl receiverParam;
   272     /** When terms are parsed, the mode determines which is expected:
   273      *     mode = EXPR        : an expression
   274      *     mode = TYPE        : a type
   275      *     mode = NOPARAMS    : no parameters allowed for type
   276      *     mode = TYPEARG     : type argument
   277      */
   278     static final int EXPR = 0x1;
   279     static final int TYPE = 0x2;
   280     static final int NOPARAMS = 0x4;
   281     static final int TYPEARG = 0x8;
   282     static final int DIAMOND = 0x10;
   284     /** The current mode.
   285      */
   286     private int mode = 0;
   288     /** The mode of the term that was parsed last.
   289      */
   290     private int lastmode = 0;
   292     /* ---------- token management -------------- */
   294     protected Token token;
   296     public Token token() {
   297         return token;
   298     }
   300     public void nextToken() {
   301         S.nextToken();
   302         token = S.token();
   303     }
   305     protected boolean peekToken(Filter<TokenKind> tk) {
   306         return peekToken(0, tk);
   307     }
   309     protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
   310         return tk.accepts(S.token(lookahead + 1).kind);
   311     }
   313     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   314         return peekToken(0, tk1, tk2);
   315     }
   317     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   318         return tk1.accepts(S.token(lookahead + 1).kind) &&
   319                 tk2.accepts(S.token(lookahead + 2).kind);
   320     }
   322     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   323         return peekToken(0, tk1, tk2, tk3);
   324     }
   326     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   327         return tk1.accepts(S.token(lookahead + 1).kind) &&
   328                 tk2.accepts(S.token(lookahead + 2).kind) &&
   329                 tk3.accepts(S.token(lookahead + 3).kind);
   330     }
   332     @SuppressWarnings("unchecked")
   333     protected boolean peekToken(Filter<TokenKind>... kinds) {
   334         return peekToken(0, kinds);
   335     }
   337     @SuppressWarnings("unchecked")
   338     protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
   339         for (; lookahead < kinds.length ; lookahead++) {
   340             if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
   341                 return false;
   342             }
   343         }
   344         return true;
   345     }
   347     /* ---------- error recovery -------------- */
   349     private JCErroneous errorTree;
   351     /** Skip forward until a suitable stop token is found.
   352      */
   353     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   354          while (true) {
   355              switch (token.kind) {
   356                 case SEMI:
   357                     nextToken();
   358                     return;
   359                 case PUBLIC:
   360                 case FINAL:
   361                 case ABSTRACT:
   362                 case MONKEYS_AT:
   363                 case EOF:
   364                 case CLASS:
   365                 case INTERFACE:
   366                 case ENUM:
   367                     return;
   368                 case IMPORT:
   369                     if (stopAtImport)
   370                         return;
   371                     break;
   372                 case LBRACE:
   373                 case RBRACE:
   374                 case PRIVATE:
   375                 case PROTECTED:
   376                 case STATIC:
   377                 case TRANSIENT:
   378                 case NATIVE:
   379                 case VOLATILE:
   380                 case SYNCHRONIZED:
   381                 case STRICTFP:
   382                 case LT:
   383                 case BYTE:
   384                 case SHORT:
   385                 case CHAR:
   386                 case INT:
   387                 case LONG:
   388                 case FLOAT:
   389                 case DOUBLE:
   390                 case BOOLEAN:
   391                 case VOID:
   392                     if (stopAtMemberDecl)
   393                         return;
   394                     break;
   395                 case UNDERSCORE:
   396                 case IDENTIFIER:
   397                    if (stopAtIdentifier)
   398                         return;
   399                     break;
   400                 case CASE:
   401                 case DEFAULT:
   402                 case IF:
   403                 case FOR:
   404                 case WHILE:
   405                 case DO:
   406                 case TRY:
   407                 case SWITCH:
   408                 case RETURN:
   409                 case THROW:
   410                 case BREAK:
   411                 case CONTINUE:
   412                 case ELSE:
   413                 case FINALLY:
   414                 case CATCH:
   415                     if (stopAtStatement)
   416                         return;
   417                     break;
   418             }
   419             nextToken();
   420         }
   421     }
   423     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   424         return syntaxError(pos, List.<JCTree>nil(), key, args);
   425     }
   427     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   428         setErrorEndPos(pos);
   429         JCErroneous err = F.at(pos).Erroneous(errs);
   430         reportSyntaxError(err, key, (Object[])args);
   431         if (errs != null) {
   432             JCTree last = errs.last();
   433             if (last != null)
   434                 storeEnd(last, pos);
   435         }
   436         return toP(err);
   437     }
   439     private int errorPos = Position.NOPOS;
   441     /**
   442      * Report a syntax using the given the position parameter and arguments,
   443      * unless one was already reported at the same position.
   444      */
   445     private void reportSyntaxError(int pos, String key, Object... args) {
   446         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   447         reportSyntaxError(diag, key, args);
   448     }
   450     /**
   451      * Report a syntax error using the given DiagnosticPosition object and
   452      * arguments, unless one was already reported at the same position.
   453      */
   454     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   455         int pos = diagPos.getPreferredPosition();
   456         if (pos > S.errPos() || pos == Position.NOPOS) {
   457             if (token.kind == EOF) {
   458                 error(diagPos, "premature.eof");
   459             } else {
   460                 error(diagPos, key, args);
   461             }
   462         }
   463         S.errPos(pos);
   464         if (token.pos == errorPos)
   465             nextToken(); // guarantee progress
   466         errorPos = token.pos;
   467     }
   470     /** Generate a syntax error at current position unless one was already
   471      *  reported at the same position.
   472      */
   473     private JCErroneous syntaxError(String key) {
   474         return syntaxError(token.pos, key);
   475     }
   477     /** Generate a syntax error at current position unless one was
   478      *  already reported at the same position.
   479      */
   480     private JCErroneous syntaxError(String key, TokenKind arg) {
   481         return syntaxError(token.pos, key, arg);
   482     }
   484     /** If next input token matches given token, skip it, otherwise report
   485      *  an error.
   486      */
   487     public void accept(TokenKind tk) {
   488         if (token.kind == tk) {
   489             nextToken();
   490         } else {
   491             setErrorEndPos(token.pos);
   492             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   493         }
   494     }
   496     /** Report an illegal start of expression/type error at given position.
   497      */
   498     JCExpression illegal(int pos) {
   499         setErrorEndPos(pos);
   500         if ((mode & EXPR) != 0)
   501             return syntaxError(pos, "illegal.start.of.expr");
   502         else
   503             return syntaxError(pos, "illegal.start.of.type");
   505     }
   507     /** Report an illegal start of expression/type error at current position.
   508      */
   509     JCExpression illegal() {
   510         return illegal(token.pos);
   511     }
   513     /** Diagnose a modifier flag from the set, if any. */
   514     void checkNoMods(long mods) {
   515         if (mods != 0) {
   516             long lowestMod = mods & -mods;
   517             error(token.pos, "mod.not.allowed.here",
   518                       Flags.asFlagSet(lowestMod));
   519         }
   520     }
   522 /* ---------- doc comments --------- */
   524     /** A table to store all documentation comments
   525      *  indexed by the tree nodes they refer to.
   526      *  defined only if option flag keepDocComment is set.
   527      */
   528     private final DocCommentTable docComments;
   530     /** Make an entry into docComments hashtable,
   531      *  provided flag keepDocComments is set and given doc comment is non-null.
   532      *  @param tree   The tree to be used as index in the hashtable
   533      *  @param dc     The doc comment to associate with the tree, or null.
   534      */
   535     void attach(JCTree tree, Comment dc) {
   536         if (keepDocComments && dc != null) {
   537 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   538             docComments.putComment(tree, dc);
   539         }
   540     }
   542 /* -------- source positions ------- */
   544     private void setErrorEndPos(int errPos) {
   545         endPosTable.setErrorEndPos(errPos);
   546     }
   548     private void storeEnd(JCTree tree, int endpos) {
   549         endPosTable.storeEnd(tree, endpos);
   550     }
   552     private <T extends JCTree> T to(T t) {
   553         return endPosTable.to(t);
   554     }
   556     private <T extends JCTree> T toP(T t) {
   557         return endPosTable.toP(t);
   558     }
   560     /** Get the start position for a tree node.  The start position is
   561      * defined to be the position of the first character of the first
   562      * token of the node's source text.
   563      * @param tree  The tree node
   564      */
   565     public int getStartPos(JCTree tree) {
   566         return TreeInfo.getStartPos(tree);
   567     }
   569     /**
   570      * Get the end position for a tree node.  The end position is
   571      * defined to be the position of the last character of the last
   572      * token of the node's source text.  Returns Position.NOPOS if end
   573      * positions are not generated or the position is otherwise not
   574      * found.
   575      * @param tree  The tree node
   576      */
   577     public int getEndPos(JCTree tree) {
   578         return endPosTable.getEndPos(tree);
   579     }
   583 /* ---------- parsing -------------- */
   585     /**
   586      * Ident = IDENTIFIER
   587      */
   588     Name ident() {
   589         if (token.kind == IDENTIFIER) {
   590             Name name = token.name();
   591             nextToken();
   592             return name;
   593         } else if (token.kind == ASSERT) {
   594             if (allowAsserts) {
   595                 error(token.pos, "assert.as.identifier");
   596                 nextToken();
   597                 return names.error;
   598             } else {
   599                 warning(token.pos, "assert.as.identifier");
   600                 Name name = token.name();
   601                 nextToken();
   602                 return name;
   603             }
   604         } else if (token.kind == ENUM) {
   605             if (allowEnums) {
   606                 error(token.pos, "enum.as.identifier");
   607                 nextToken();
   608                 return names.error;
   609             } else {
   610                 warning(token.pos, "enum.as.identifier");
   611                 Name name = token.name();
   612                 nextToken();
   613                 return name;
   614             }
   615         } else if (token.kind == THIS) {
   616             if (allowThisIdent) {
   617                 // Make sure we're using a supported source version.
   618                 checkTypeAnnotations();
   619                 Name name = token.name();
   620                 nextToken();
   621                 return name;
   622             } else {
   623                 error(token.pos, "this.as.identifier");
   624                 nextToken();
   625                 return names.error;
   626             }
   627         } else if (token.kind == UNDERSCORE) {
   628             warning(token.pos, "underscore.as.identifier");
   629             Name name = token.name();
   630             nextToken();
   631             return name;
   632         } else {
   633             accept(IDENTIFIER);
   634             return names.error;
   635         }
   636     }
   638     /**
   639      * Qualident = Ident { DOT [Annotations] Ident }
   640      */
   641     public JCExpression qualident(boolean allowAnnos) {
   642         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   643         while (token.kind == DOT) {
   644             int pos = token.pos;
   645             nextToken();
   646             List<JCAnnotation> tyannos = null;
   647             if (allowAnnos) {
   648                 tyannos = typeAnnotationsOpt();
   649             }
   650             t = toP(F.at(pos).Select(t, ident()));
   651             if (tyannos != null && tyannos.nonEmpty()) {
   652                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
   653             }
   654         }
   655         return t;
   656     }
   658     JCExpression literal(Name prefix) {
   659         return literal(prefix, token.pos);
   660     }
   662     /**
   663      * Literal =
   664      *     INTLITERAL
   665      *   | LONGLITERAL
   666      *   | FLOATLITERAL
   667      *   | DOUBLELITERAL
   668      *   | CHARLITERAL
   669      *   | STRINGLITERAL
   670      *   | TRUE
   671      *   | FALSE
   672      *   | NULL
   673      */
   674     JCExpression literal(Name prefix, int pos) {
   675         JCExpression t = errorTree;
   676         switch (token.kind) {
   677         case INTLITERAL:
   678             try {
   679                 t = F.at(pos).Literal(
   680                     TypeTag.INT,
   681                     Convert.string2int(strval(prefix), token.radix()));
   682             } catch (NumberFormatException ex) {
   683                 error(token.pos, "int.number.too.large", strval(prefix));
   684             }
   685             break;
   686         case LONGLITERAL:
   687             try {
   688                 t = F.at(pos).Literal(
   689                     TypeTag.LONG,
   690                     new Long(Convert.string2long(strval(prefix), token.radix())));
   691             } catch (NumberFormatException ex) {
   692                 error(token.pos, "int.number.too.large", strval(prefix));
   693             }
   694             break;
   695         case FLOATLITERAL: {
   696             String proper = token.radix() == 16 ?
   697                     ("0x"+ token.stringVal()) :
   698                     token.stringVal();
   699             Float n;
   700             try {
   701                 n = Float.valueOf(proper);
   702             } catch (NumberFormatException ex) {
   703                 // error already reported in scanner
   704                 n = Float.NaN;
   705             }
   706             if (n.floatValue() == 0.0f && !isZero(proper))
   707                 error(token.pos, "fp.number.too.small");
   708             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   709                 error(token.pos, "fp.number.too.large");
   710             else
   711                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
   712             break;
   713         }
   714         case DOUBLELITERAL: {
   715             String proper = token.radix() == 16 ?
   716                     ("0x"+ token.stringVal()) :
   717                     token.stringVal();
   718             Double n;
   719             try {
   720                 n = Double.valueOf(proper);
   721             } catch (NumberFormatException ex) {
   722                 // error already reported in scanner
   723                 n = Double.NaN;
   724             }
   725             if (n.doubleValue() == 0.0d && !isZero(proper))
   726                 error(token.pos, "fp.number.too.small");
   727             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   728                 error(token.pos, "fp.number.too.large");
   729             else
   730                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
   731             break;
   732         }
   733         case CHARLITERAL:
   734             t = F.at(pos).Literal(
   735                 TypeTag.CHAR,
   736                 token.stringVal().charAt(0) + 0);
   737             break;
   738         case STRINGLITERAL:
   739             t = F.at(pos).Literal(
   740                 TypeTag.CLASS,
   741                 token.stringVal());
   742             break;
   743         case TRUE: case FALSE:
   744             t = F.at(pos).Literal(
   745                 TypeTag.BOOLEAN,
   746                 (token.kind == TRUE ? 1 : 0));
   747             break;
   748         case NULL:
   749             t = F.at(pos).Literal(
   750                 TypeTag.BOT,
   751                 null);
   752             break;
   753         default:
   754             Assert.error();
   755         }
   756         if (t == errorTree)
   757             t = F.at(pos).Erroneous();
   758         storeEnd(t, token.endPos);
   759         nextToken();
   760         return t;
   761     }
   762     //where
   763         boolean isZero(String s) {
   764             char[] cs = s.toCharArray();
   765             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   766             int i = ((base==16) ? 2 : 0);
   767             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   768             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   769         }
   771         String strval(Name prefix) {
   772             String s = token.stringVal();
   773             return prefix.isEmpty() ? s : prefix + s;
   774         }
   776     /** terms can be either expressions or types.
   777      */
   778     public JCExpression parseExpression() {
   779         return term(EXPR);
   780     }
   782     /**
   783      * parses (optional) type annotations followed by a type. If the
   784      * annotations are present before the type and are not consumed during array
   785      * parsing, this method returns a {@link JCAnnotatedType} consisting of
   786      * these annotations and the underlying type. Otherwise, it returns the
   787      * underlying type.
   788      *
   789      * <p>
   790      *
   791      * Note that this method sets {@code mode} to {@code TYPE} first, before
   792      * parsing annotations.
   793      */
   794     public JCExpression parseType() {
   795         List<JCAnnotation> annotations = typeAnnotationsOpt();
   796         return parseType(annotations);
   797     }
   799     public JCExpression parseType(List<JCAnnotation> annotations) {
   800         JCExpression result = unannotatedType();
   802         if (annotations.nonEmpty()) {
   803             result = insertAnnotationsToMostInner(result, annotations, false);
   804         }
   806         return result;
   807     }
   809     public JCExpression unannotatedType() {
   810         return term(TYPE);
   811     }
   813     JCExpression term(int newmode) {
   814         int prevmode = mode;
   815         mode = newmode;
   816         JCExpression t = term();
   817         lastmode = mode;
   818         mode = prevmode;
   819         return t;
   820     }
   822     /**
   823      *  {@literal
   824      *  Expression = Expression1 [ExpressionRest]
   825      *  ExpressionRest = [AssignmentOperator Expression1]
   826      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   827      *                       "&=" | "|=" | "^=" |
   828      *                       "%=" | "<<=" | ">>=" | ">>>="
   829      *  Type = Type1
   830      *  TypeNoParams = TypeNoParams1
   831      *  StatementExpression = Expression
   832      *  ConstantExpression = Expression
   833      *  }
   834      */
   835     JCExpression term() {
   836         JCExpression t = term1();
   837         if ((mode & EXPR) != 0 &&
   838             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   839             return termRest(t);
   840         else
   841             return t;
   842     }
   844     JCExpression termRest(JCExpression t) {
   845         switch (token.kind) {
   846         case EQ: {
   847             int pos = token.pos;
   848             nextToken();
   849             mode = EXPR;
   850             JCExpression t1 = term();
   851             return toP(F.at(pos).Assign(t, t1));
   852         }
   853         case PLUSEQ:
   854         case SUBEQ:
   855         case STAREQ:
   856         case SLASHEQ:
   857         case PERCENTEQ:
   858         case AMPEQ:
   859         case BAREQ:
   860         case CARETEQ:
   861         case LTLTEQ:
   862         case GTGTEQ:
   863         case GTGTGTEQ:
   864             int pos = token.pos;
   865             TokenKind tk = token.kind;
   866             nextToken();
   867             mode = EXPR;
   868             JCExpression t1 = term();
   869             return F.at(pos).Assignop(optag(tk), t, t1);
   870         default:
   871             return t;
   872         }
   873     }
   875     /** Expression1   = Expression2 [Expression1Rest]
   876      *  Type1         = Type2
   877      *  TypeNoParams1 = TypeNoParams2
   878      */
   879     JCExpression term1() {
   880         JCExpression t = term2();
   881         if ((mode & EXPR) != 0 && token.kind == QUES) {
   882             mode = EXPR;
   883             return term1Rest(t);
   884         } else {
   885             return t;
   886         }
   887     }
   889     /** Expression1Rest = ["?" Expression ":" Expression1]
   890      */
   891     JCExpression term1Rest(JCExpression t) {
   892         if (token.kind == QUES) {
   893             int pos = token.pos;
   894             nextToken();
   895             JCExpression t1 = term();
   896             accept(COLON);
   897             JCExpression t2 = term1();
   898             return F.at(pos).Conditional(t, t1, t2);
   899         } else {
   900             return t;
   901         }
   902     }
   904     /** Expression2   = Expression3 [Expression2Rest]
   905      *  Type2         = Type3
   906      *  TypeNoParams2 = TypeNoParams3
   907      */
   908     JCExpression term2() {
   909         JCExpression t = term3();
   910         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   911             mode = EXPR;
   912             return term2Rest(t, TreeInfo.orPrec);
   913         } else {
   914             return t;
   915         }
   916     }
   918     /*  Expression2Rest = {infixop Expression3}
   919      *                  | Expression3 instanceof Type
   920      *  infixop         = "||"
   921      *                  | "&&"
   922      *                  | "|"
   923      *                  | "^"
   924      *                  | "&"
   925      *                  | "==" | "!="
   926      *                  | "<" | ">" | "<=" | ">="
   927      *                  | "<<" | ">>" | ">>>"
   928      *                  | "+" | "-"
   929      *                  | "*" | "/" | "%"
   930      */
   931     JCExpression term2Rest(JCExpression t, int minprec) {
   932         JCExpression[] odStack = newOdStack();
   933         Token[] opStack = newOpStack();
   935         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   936         int top = 0;
   937         odStack[0] = t;
   938         int startPos = token.pos;
   939         Token topOp = Tokens.DUMMY;
   940         while (prec(token.kind) >= minprec) {
   941             opStack[top] = topOp;
   942             top++;
   943             topOp = token;
   944             nextToken();
   945             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   946             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   947                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   948                                         odStack[top]);
   949                 top--;
   950                 topOp = opStack[top];
   951             }
   952         }
   953         Assert.check(top == 0);
   954         t = odStack[0];
   956         if (t.hasTag(JCTree.Tag.PLUS)) {
   957             StringBuilder buf = foldStrings(t);
   958             if (buf != null) {
   959                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
   960             }
   961         }
   963         odStackSupply.add(odStack);
   964         opStackSupply.add(opStack);
   965         return t;
   966     }
   967     //where
   968         /** Construct a binary or type test node.
   969          */
   970         private JCExpression makeOp(int pos,
   971                                     TokenKind topOp,
   972                                     JCExpression od1,
   973                                     JCExpression od2)
   974         {
   975             if (topOp == INSTANCEOF) {
   976                 return F.at(pos).TypeTest(od1, od2);
   977             } else {
   978                 return F.at(pos).Binary(optag(topOp), od1, od2);
   979             }
   980         }
   981         /** If tree is a concatenation of string literals, replace it
   982          *  by a single literal representing the concatenated string.
   983          */
   984         protected StringBuilder foldStrings(JCTree tree) {
   985             if (!allowStringFolding)
   986                 return null;
   987             List<String> buf = List.nil();
   988             while (true) {
   989                 if (tree.hasTag(LITERAL)) {
   990                     JCLiteral lit = (JCLiteral) tree;
   991                     if (lit.typetag == TypeTag.CLASS) {
   992                         StringBuilder sbuf =
   993                             new StringBuilder((String)lit.value);
   994                         while (buf.nonEmpty()) {
   995                             sbuf.append(buf.head);
   996                             buf = buf.tail;
   997                         }
   998                         return sbuf;
   999                     }
  1000                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
  1001                     JCBinary op = (JCBinary)tree;
  1002                     if (op.rhs.hasTag(LITERAL)) {
  1003                         JCLiteral lit = (JCLiteral) op.rhs;
  1004                         if (lit.typetag == TypeTag.CLASS) {
  1005                             buf = buf.prepend((String) lit.value);
  1006                             tree = op.lhs;
  1007                             continue;
  1011                 return null;
  1015         /** optimization: To save allocating a new operand/operator stack
  1016          *  for every binary operation, we use supplys.
  1017          */
  1018         ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>();
  1019         ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>();
  1021         private JCExpression[] newOdStack() {
  1022             if (odStackSupply.isEmpty())
  1023                 return new JCExpression[infixPrecedenceLevels + 1];
  1024             return odStackSupply.remove(odStackSupply.size() - 1);
  1027         private Token[] newOpStack() {
  1028             if (opStackSupply.isEmpty())
  1029                 return new Token[infixPrecedenceLevels + 1];
  1030             return opStackSupply.remove(opStackSupply.size() - 1);
  1033     /**
  1034      *  Expression3    = PrefixOp Expression3
  1035      *                 | "(" Expr | TypeNoParams ")" Expression3
  1036      *                 | Primary {Selector} {PostfixOp}
  1038      *  {@literal
  1039      *  Primary        = "(" Expression ")"
  1040      *                 | Literal
  1041      *                 | [TypeArguments] THIS [Arguments]
  1042      *                 | [TypeArguments] SUPER SuperSuffix
  1043      *                 | NEW [TypeArguments] Creator
  1044      *                 | "(" Arguments ")" "->" ( Expression | Block )
  1045      *                 | Ident "->" ( Expression | Block )
  1046      *                 | [Annotations] Ident { "." [Annotations] Ident }
  1047      *                 | Expression3 MemberReferenceSuffix
  1048      *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
  1049      *                   | Arguments
  1050      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
  1051      *                   ]
  1052      *                 | BasicType BracketsOpt "." CLASS
  1053      *  }
  1055      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
  1056      *  PostfixOp      = "++" | "--"
  1057      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
  1058      *                 | BasicType
  1059      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
  1060      *  Selector       = "." [TypeArguments] Ident [Arguments]
  1061      *                 | "." THIS
  1062      *                 | "." [TypeArguments] SUPER SuperSuffix
  1063      *                 | "." NEW [TypeArguments] InnerCreator
  1064      *                 | "[" Expression "]"
  1065      *  TypeSelector   = "." Ident [TypeArguments]
  1066      *  SuperSuffix    = Arguments | "." Ident [Arguments]
  1067      */
  1068     protected JCExpression term3() {
  1069         int pos = token.pos;
  1070         JCExpression t;
  1071         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
  1072         switch (token.kind) {
  1073         case QUES:
  1074             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
  1075                 mode = TYPE;
  1076                 return typeArgument();
  1077             } else
  1078                 return illegal();
  1079         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
  1080             if (typeArgs == null && (mode & EXPR) != 0) {
  1081                 TokenKind tk = token.kind;
  1082                 nextToken();
  1083                 mode = EXPR;
  1084                 if (tk == SUB &&
  1085                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
  1086                     token.radix() == 10) {
  1087                     mode = EXPR;
  1088                     t = literal(names.hyphen, pos);
  1089                 } else {
  1090                     t = term3();
  1091                     return F.at(pos).Unary(unoptag(tk), t);
  1093             } else return illegal();
  1094             break;
  1095         case LPAREN:
  1096             if (typeArgs == null && (mode & EXPR) != 0) {
  1097                 ParensResult pres = analyzeParens();
  1098                 switch (pres) {
  1099                     case CAST:
  1100                        accept(LPAREN);
  1101                        mode = TYPE;
  1102                        int pos1 = pos;
  1103                        List<JCExpression> targets = List.of(t = term3());
  1104                        while (token.kind == AMP) {
  1105                            checkIntersectionTypesInCast();
  1106                            accept(AMP);
  1107                            targets = targets.prepend(term3());
  1109                        if (targets.length() > 1) {
  1110                            t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
  1112                        accept(RPAREN);
  1113                        mode = EXPR;
  1114                        JCExpression t1 = term3();
  1115                        return F.at(pos).TypeCast(t, t1);
  1116                     case IMPLICIT_LAMBDA:
  1117                     case EXPLICIT_LAMBDA:
  1118                         t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
  1119                         break;
  1120                     default: //PARENS
  1121                         accept(LPAREN);
  1122                         mode = EXPR;
  1123                         t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
  1124                         accept(RPAREN);
  1125                         t = toP(F.at(pos).Parens(t));
  1126                         break;
  1128             } else {
  1129                 return illegal();
  1131             break;
  1132         case THIS:
  1133             if ((mode & EXPR) != 0) {
  1134                 mode = EXPR;
  1135                 t = to(F.at(pos).Ident(names._this));
  1136                 nextToken();
  1137                 if (typeArgs == null)
  1138                     t = argumentsOpt(null, t);
  1139                 else
  1140                     t = arguments(typeArgs, t);
  1141                 typeArgs = null;
  1142             } else return illegal();
  1143             break;
  1144         case SUPER:
  1145             if ((mode & EXPR) != 0) {
  1146                 mode = EXPR;
  1147                 t = to(F.at(pos).Ident(names._super));
  1148                 t = superSuffix(typeArgs, t);
  1149                 typeArgs = null;
  1150             } else return illegal();
  1151             break;
  1152         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1153         case CHARLITERAL: case STRINGLITERAL:
  1154         case TRUE: case FALSE: case NULL:
  1155             if (typeArgs == null && (mode & EXPR) != 0) {
  1156                 mode = EXPR;
  1157                 t = literal(names.empty);
  1158             } else return illegal();
  1159             break;
  1160         case NEW:
  1161             if (typeArgs != null) return illegal();
  1162             if ((mode & EXPR) != 0) {
  1163                 mode = EXPR;
  1164                 nextToken();
  1165                 if (token.kind == LT) typeArgs = typeArguments(false);
  1166                 t = creator(pos, typeArgs);
  1167                 typeArgs = null;
  1168             } else return illegal();
  1169             break;
  1170         case MONKEYS_AT:
  1171             // Only annotated cast types and method references are valid
  1172             List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
  1173             if (typeAnnos.isEmpty()) {
  1174                 // else there would be no '@'
  1175                 throw new AssertionError("Expected type annotations, but found none!");
  1178             JCExpression expr = term3();
  1180             if ((mode & TYPE) == 0) {
  1181                 // Type annotations on class literals no longer legal
  1182                 switch (expr.getTag()) {
  1183                 case REFERENCE: {
  1184                     JCMemberReference mref = (JCMemberReference) expr;
  1185                     mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
  1186                     t = mref;
  1187                     break;
  1189                 case SELECT: {
  1190                     JCFieldAccess sel = (JCFieldAccess) expr;
  1192                     if (sel.name != names._class) {
  1193                         return illegal();
  1194                     } else {
  1195                         log.error(token.pos, "no.annotations.on.dot.class");
  1196                         return expr;
  1199                 default:
  1200                     return illegal(typeAnnos.head.pos);
  1203             } else {
  1204                 // Type annotations targeting a cast
  1205                 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
  1207             break;
  1208         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
  1209             if (typeArgs != null) return illegal();
  1210             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1211                 t = lambdaExpressionOrStatement(false, false, pos);
  1212             } else {
  1213                 t = toP(F.at(token.pos).Ident(ident()));
  1214                 loop: while (true) {
  1215                     pos = token.pos;
  1216                     final List<JCAnnotation> annos = typeAnnotationsOpt();
  1218                     // need to report an error later if LBRACKET is for array
  1219                     // index access rather than array creation level
  1220                     if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
  1221                         return illegal(annos.head.pos);
  1223                     switch (token.kind) {
  1224                     case LBRACKET:
  1225                         nextToken();
  1226                         if (token.kind == RBRACKET) {
  1227                             nextToken();
  1228                             t = bracketsOpt(t);
  1229                             t = toP(F.at(pos).TypeArray(t));
  1230                             if (annos.nonEmpty()) {
  1231                                 t = toP(F.at(pos).AnnotatedType(annos, t));
  1233                             // .class is only allowed if there were no annotations
  1234                             JCExpression nt = bracketsSuffix(t);
  1235                             if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) {
  1236                                 // t and nt are different if bracketsSuffix parsed a .class.
  1237                                 // The check for nonEmpty covers the case when the whole array is annotated.
  1238                                 // Helper method isAnnotated looks for annos deeply within t.
  1239                                 syntaxError("no.annotations.on.dot.class");
  1241                             t = nt;
  1242                         } else {
  1243                             if ((mode & EXPR) != 0) {
  1244                                 mode = EXPR;
  1245                                 JCExpression t1 = term();
  1246                                 if (!annos.isEmpty()) t = illegal(annos.head.pos);
  1247                                 t = to(F.at(pos).Indexed(t, t1));
  1249                             accept(RBRACKET);
  1251                         break loop;
  1252                     case LPAREN:
  1253                         if ((mode & EXPR) != 0) {
  1254                             mode = EXPR;
  1255                             t = arguments(typeArgs, t);
  1256                             if (!annos.isEmpty()) t = illegal(annos.head.pos);
  1257                             typeArgs = null;
  1259                         break loop;
  1260                     case DOT:
  1261                         nextToken();
  1262                         int oldmode = mode;
  1263                         mode &= ~NOPARAMS;
  1264                         typeArgs = typeArgumentsOpt(EXPR);
  1265                         mode = oldmode;
  1266                         if ((mode & EXPR) != 0) {
  1267                             switch (token.kind) {
  1268                             case CLASS:
  1269                                 if (typeArgs != null) return illegal();
  1270                                 mode = EXPR;
  1271                                 t = to(F.at(pos).Select(t, names._class));
  1272                                 nextToken();
  1273                                 break loop;
  1274                             case THIS:
  1275                                 if (typeArgs != null) return illegal();
  1276                                 mode = EXPR;
  1277                                 t = to(F.at(pos).Select(t, names._this));
  1278                                 nextToken();
  1279                                 break loop;
  1280                             case SUPER:
  1281                                 mode = EXPR;
  1282                                 t = to(F.at(pos).Select(t, names._super));
  1283                                 t = superSuffix(typeArgs, t);
  1284                                 typeArgs = null;
  1285                                 break loop;
  1286                             case NEW:
  1287                                 if (typeArgs != null) return illegal();
  1288                                 mode = EXPR;
  1289                                 int pos1 = token.pos;
  1290                                 nextToken();
  1291                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1292                                 t = innerCreator(pos1, typeArgs, t);
  1293                                 typeArgs = null;
  1294                                 break loop;
  1298                         List<JCAnnotation> tyannos = null;
  1299                         if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
  1300                             tyannos = typeAnnotationsOpt();
  1302                         // typeArgs saved for next loop iteration.
  1303                         t = toP(F.at(pos).Select(t, ident()));
  1304                         if (tyannos != null && tyannos.nonEmpty()) {
  1305                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
  1307                         break;
  1308                     case ELLIPSIS:
  1309                         if (this.permitTypeAnnotationsPushBack) {
  1310                             this.typeAnnotationsPushedBack = annos;
  1311                         } else if (annos.nonEmpty()) {
  1312                             // Don't return here -- error recovery attempt
  1313                             illegal(annos.head.pos);
  1315                         break loop;
  1316                     case LT:
  1317                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1318                             //this is an unbound method reference whose qualifier
  1319                             //is a generic type i.e. A<S>::m
  1320                             int pos1 = token.pos;
  1321                             accept(LT);
  1322                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1323                             args.append(typeArgument());
  1324                             while (token.kind == COMMA) {
  1325                                 nextToken();
  1326                                 args.append(typeArgument());
  1328                             accept(GT);
  1329                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1330                             checkGenerics();
  1331                             while (token.kind == DOT) {
  1332                                 nextToken();
  1333                                 mode = TYPE;
  1334                                 t = toP(F.at(token.pos).Select(t, ident()));
  1335                                 t = typeArgumentsOpt(t);
  1337                             t = bracketsOpt(t);
  1338                             if (token.kind != COLCOL) {
  1339                                 //method reference expected here
  1340                                 t = illegal();
  1342                             mode = EXPR;
  1343                             return term3Rest(t, typeArgs);
  1345                         break loop;
  1346                     default:
  1347                         break loop;
  1351             if (typeArgs != null) illegal();
  1352             t = typeArgumentsOpt(t);
  1353             break;
  1354         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1355         case DOUBLE: case BOOLEAN:
  1356             if (typeArgs != null) illegal();
  1357             t = bracketsSuffix(bracketsOpt(basicType()));
  1358             break;
  1359         case VOID:
  1360             if (typeArgs != null) illegal();
  1361             if ((mode & EXPR) != 0) {
  1362                 nextToken();
  1363                 if (token.kind == DOT) {
  1364                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
  1365                     t = bracketsSuffix(ti);
  1366                 } else {
  1367                     return illegal(pos);
  1369             } else {
  1370                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1371                 // a void type (like other primitive types) to the next phase.
  1372                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1373                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
  1374                 nextToken();
  1375                 return ti;
  1376                 //return illegal();
  1378             break;
  1379         default:
  1380             return illegal();
  1382         return term3Rest(t, typeArgs);
  1385     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1386         if (typeArgs != null) illegal();
  1387         while (true) {
  1388             int pos1 = token.pos;
  1389             final List<JCAnnotation> annos = typeAnnotationsOpt();
  1391             if (token.kind == LBRACKET) {
  1392                 nextToken();
  1393                 if ((mode & TYPE) != 0) {
  1394                     int oldmode = mode;
  1395                     mode = TYPE;
  1396                     if (token.kind == RBRACKET) {
  1397                         nextToken();
  1398                         t = bracketsOpt(t);
  1399                         t = toP(F.at(pos1).TypeArray(t));
  1400                         if (token.kind == COLCOL) {
  1401                             mode = EXPR;
  1402                             continue;
  1404                         if (annos.nonEmpty()) {
  1405                             t = toP(F.at(pos1).AnnotatedType(annos, t));
  1407                         return t;
  1409                     mode = oldmode;
  1411                 if ((mode & EXPR) != 0) {
  1412                     mode = EXPR;
  1413                     JCExpression t1 = term();
  1414                     t = to(F.at(pos1).Indexed(t, t1));
  1416                 accept(RBRACKET);
  1417             } else if (token.kind == DOT) {
  1418                 nextToken();
  1419                 typeArgs = typeArgumentsOpt(EXPR);
  1420                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1421                     mode = EXPR;
  1422                     t = to(F.at(pos1).Select(t, names._super));
  1423                     nextToken();
  1424                     t = arguments(typeArgs, t);
  1425                     typeArgs = null;
  1426                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1427                     if (typeArgs != null) return illegal();
  1428                     mode = EXPR;
  1429                     int pos2 = token.pos;
  1430                     nextToken();
  1431                     if (token.kind == LT) typeArgs = typeArguments(false);
  1432                     t = innerCreator(pos2, typeArgs, t);
  1433                     typeArgs = null;
  1434                 } else {
  1435                     List<JCAnnotation> tyannos = null;
  1436                     if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
  1437                         // is the mode check needed?
  1438                         tyannos = typeAnnotationsOpt();
  1440                     t = toP(F.at(pos1).Select(t, ident()));
  1441                     if (tyannos != null && tyannos.nonEmpty()) {
  1442                         t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
  1444                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1445                     typeArgs = null;
  1447             } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
  1448                 mode = EXPR;
  1449                 if (typeArgs != null) return illegal();
  1450                 accept(COLCOL);
  1451                 t = memberReferenceSuffix(pos1, t);
  1452             } else {
  1453                 if (!annos.isEmpty()) {
  1454                     if (permitTypeAnnotationsPushBack)
  1455                         typeAnnotationsPushedBack = annos;
  1456                     else
  1457                         return illegal(annos.head.pos);
  1459                 break;
  1462         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1463             mode = EXPR;
  1464             t = to(F.at(token.pos).Unary(
  1465                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1466             nextToken();
  1468         return toP(t);
  1471     /**
  1472      * If we see an identifier followed by a '&lt;' it could be an unbound
  1473      * method reference or a binary expression. To disambiguate, look for a
  1474      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
  1475      */
  1476     @SuppressWarnings("fallthrough")
  1477     boolean isUnboundMemberRef() {
  1478         int pos = 0, depth = 0;
  1479         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1480             switch (t.kind) {
  1481                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
  1482                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1483                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1484                 case DOUBLE: case BOOLEAN: case CHAR:
  1485                 case MONKEYS_AT:
  1486                     break;
  1488                 case LPAREN:
  1489                     // skip annotation values
  1490                     int nesting = 0;
  1491                     for (; ; pos++) {
  1492                         TokenKind tk2 = S.token(pos).kind;
  1493                         switch (tk2) {
  1494                             case EOF:
  1495                                 return false;
  1496                             case LPAREN:
  1497                                 nesting++;
  1498                                 break;
  1499                             case RPAREN:
  1500                                 nesting--;
  1501                                 if (nesting == 0) {
  1502                                     continue outer;
  1504                                 break;
  1508                 case LT:
  1509                     depth++; break;
  1510                 case GTGTGT:
  1511                     depth--;
  1512                 case GTGT:
  1513                     depth--;
  1514                 case GT:
  1515                     depth--;
  1516                     if (depth == 0) {
  1517                         TokenKind nextKind = S.token(pos + 1).kind;
  1518                         return
  1519                             nextKind == TokenKind.DOT ||
  1520                             nextKind == TokenKind.LBRACKET ||
  1521                             nextKind == TokenKind.COLCOL;
  1523                     break;
  1524                 default:
  1525                     return false;
  1530     /**
  1531      * If we see an identifier followed by a '&lt;' it could be an unbound
  1532      * method reference or a binary expression. To disambiguate, look for a
  1533      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
  1534      */
  1535     @SuppressWarnings("fallthrough")
  1536     ParensResult analyzeParens() {
  1537         int depth = 0;
  1538         boolean type = false;
  1539         outer: for (int lookahead = 0 ; ; lookahead++) {
  1540             TokenKind tk = S.token(lookahead).kind;
  1541             switch (tk) {
  1542                 case COMMA:
  1543                     type = true;
  1544                 case EXTENDS: case SUPER: case DOT: case AMP:
  1545                     //skip
  1546                     break;
  1547                 case QUES:
  1548                     if (peekToken(lookahead, EXTENDS) ||
  1549                             peekToken(lookahead, SUPER)) {
  1550                         //wildcards
  1551                         type = true;
  1553                     break;
  1554                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1555                 case DOUBLE: case BOOLEAN: case CHAR:
  1556                     if (peekToken(lookahead, RPAREN)) {
  1557                         //Type, ')' -> cast
  1558                         return ParensResult.CAST;
  1559                     } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1560                         //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1561                         return ParensResult.EXPLICIT_LAMBDA;
  1563                     break;
  1564                 case LPAREN:
  1565                     if (lookahead != 0) {
  1566                         // '(' in a non-starting position -> parens
  1567                         return ParensResult.PARENS;
  1568                     } else if (peekToken(lookahead, RPAREN)) {
  1569                         // '(', ')' -> explicit lambda
  1570                         return ParensResult.EXPLICIT_LAMBDA;
  1572                     break;
  1573                 case RPAREN:
  1574                     // if we have seen something that looks like a type,
  1575                     // then it's a cast expression
  1576                     if (type) return ParensResult.CAST;
  1577                     // otherwise, disambiguate cast vs. parenthesized expression
  1578                     // based on subsequent token.
  1579                     switch (S.token(lookahead + 1).kind) {
  1580                         /*case PLUSPLUS: case SUBSUB: */
  1581                         case BANG: case TILDE:
  1582                         case LPAREN: case THIS: case SUPER:
  1583                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1584                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1585                         case TRUE: case FALSE: case NULL:
  1586                         case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
  1587                         case BYTE: case SHORT: case CHAR: case INT:
  1588                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1589                             return ParensResult.CAST;
  1590                         default:
  1591                             return ParensResult.PARENS;
  1593                 case UNDERSCORE:
  1594                 case ASSERT:
  1595                 case ENUM:
  1596                 case IDENTIFIER:
  1597                     if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1598                         // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1599                         return ParensResult.EXPLICIT_LAMBDA;
  1600                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
  1601                         // Identifier, ')' '->' -> implicit lambda
  1602                         return ParensResult.IMPLICIT_LAMBDA;
  1604                     type = false;
  1605                     break;
  1606                 case FINAL:
  1607                 case ELLIPSIS:
  1608                     //those can only appear in explicit lambdas
  1609                     return ParensResult.EXPLICIT_LAMBDA;
  1610                 case MONKEYS_AT:
  1611                     type = true;
  1612                     lookahead += 1; //skip '@'
  1613                     while (peekToken(lookahead, DOT)) {
  1614                         lookahead += 2;
  1616                     if (peekToken(lookahead, LPAREN)) {
  1617                         lookahead++;
  1618                         //skip annotation values
  1619                         int nesting = 0;
  1620                         for (; ; lookahead++) {
  1621                             TokenKind tk2 = S.token(lookahead).kind;
  1622                             switch (tk2) {
  1623                                 case EOF:
  1624                                     return ParensResult.PARENS;
  1625                                 case LPAREN:
  1626                                     nesting++;
  1627                                     break;
  1628                                 case RPAREN:
  1629                                     nesting--;
  1630                                     if (nesting == 0) {
  1631                                         continue outer;
  1633                                 break;
  1637                     break;
  1638                 case LBRACKET:
  1639                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
  1640                         // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
  1641                         return ParensResult.EXPLICIT_LAMBDA;
  1642                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
  1643                             peekToken(lookahead, RBRACKET, AMP)) {
  1644                         // '[', ']', ')' -> cast
  1645                         // '[', ']', '&' -> cast (intersection type)
  1646                         return ParensResult.CAST;
  1647                     } else if (peekToken(lookahead, RBRACKET)) {
  1648                         //consume the ']' and skip
  1649                         type = true;
  1650                         lookahead++;
  1651                         break;
  1652                     } else {
  1653                         return ParensResult.PARENS;
  1655                 case LT:
  1656                     depth++; break;
  1657                 case GTGTGT:
  1658                     depth--;
  1659                 case GTGT:
  1660                     depth--;
  1661                 case GT:
  1662                     depth--;
  1663                     if (depth == 0) {
  1664                         if (peekToken(lookahead, RPAREN) ||
  1665                                 peekToken(lookahead, AMP)) {
  1666                             // '>', ')' -> cast
  1667                             // '>', '&' -> cast
  1668                             return ParensResult.CAST;
  1669                         } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
  1670                                 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
  1671                                 peekToken(lookahead, ELLIPSIS)) {
  1672                             // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
  1673                             // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
  1674                             // '>', '...' -> explicit lambda
  1675                             return ParensResult.EXPLICIT_LAMBDA;
  1677                         //it looks a type, but could still be (i) a cast to generic type,
  1678                         //(ii) an unbound method reference or (iii) an explicit lambda
  1679                         type = true;
  1680                         break;
  1681                     } else if (depth < 0) {
  1682                         //unbalanced '<', '>' - not a generic type
  1683                         return ParensResult.PARENS;
  1685                     break;
  1686                 default:
  1687                     //this includes EOF
  1688                     return ParensResult.PARENS;
  1693     /** Accepts all identifier-like tokens */
  1694     Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
  1695         public boolean accepts(TokenKind t) {
  1696             return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
  1698     };
  1700     enum ParensResult {
  1701         CAST,
  1702         EXPLICIT_LAMBDA,
  1703         IMPLICIT_LAMBDA,
  1704         PARENS;
  1707     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1708         List<JCVariableDecl> params = explicitParams ?
  1709                 formalParameters(true) :
  1710                 implicitParameters(hasParens);
  1712         return lambdaExpressionOrStatementRest(params, pos);
  1715     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1716         checkLambda();
  1717         accept(ARROW);
  1719         return token.kind == LBRACE ?
  1720             lambdaStatement(args, pos, pos) :
  1721             lambdaExpression(args, pos);
  1724     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1725         JCBlock block = block(pos2, 0);
  1726         return toP(F.at(pos).Lambda(args, block));
  1729     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1730         JCTree expr = parseExpression();
  1731         return toP(F.at(pos).Lambda(args, expr));
  1734     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1735      */
  1736     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1737         nextToken();
  1738         if (token.kind == LPAREN || typeArgs != null) {
  1739             t = arguments(typeArgs, t);
  1740         } else if (token.kind == COLCOL) {
  1741             if (typeArgs != null) return illegal();
  1742             t = memberReferenceSuffix(t);
  1743         } else {
  1744             int pos = token.pos;
  1745             accept(DOT);
  1746             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1747             t = toP(F.at(pos).Select(t, ident()));
  1748             t = argumentsOpt(typeArgs, t);
  1750         return t;
  1753     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1754      */
  1755     JCPrimitiveTypeTree basicType() {
  1756         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1757         nextToken();
  1758         return t;
  1761     /** ArgumentsOpt = [ Arguments ]
  1762      */
  1763     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1764         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1765             mode = EXPR;
  1766             return arguments(typeArgs, t);
  1767         } else {
  1768             return t;
  1772     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1773      */
  1774     List<JCExpression> arguments() {
  1775         ListBuffer<JCExpression> args = new ListBuffer<>();
  1776         if (token.kind == LPAREN) {
  1777             nextToken();
  1778             if (token.kind != RPAREN) {
  1779                 args.append(parseExpression());
  1780                 while (token.kind == COMMA) {
  1781                     nextToken();
  1782                     args.append(parseExpression());
  1785             accept(RPAREN);
  1786         } else {
  1787             syntaxError(token.pos, "expected", LPAREN);
  1789         return args.toList();
  1792     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1793         int pos = token.pos;
  1794         List<JCExpression> args = arguments();
  1795         return toP(F.at(pos).Apply(typeArgs, t, args));
  1798     /**  TypeArgumentsOpt = [ TypeArguments ]
  1799      */
  1800     JCExpression typeArgumentsOpt(JCExpression t) {
  1801         if (token.kind == LT &&
  1802             (mode & TYPE) != 0 &&
  1803             (mode & NOPARAMS) == 0) {
  1804             mode = TYPE;
  1805             checkGenerics();
  1806             return typeArguments(t, false);
  1807         } else {
  1808             return t;
  1811     List<JCExpression> typeArgumentsOpt() {
  1812         return typeArgumentsOpt(TYPE);
  1815     List<JCExpression> typeArgumentsOpt(int useMode) {
  1816         if (token.kind == LT) {
  1817             checkGenerics();
  1818             if ((mode & useMode) == 0 ||
  1819                 (mode & NOPARAMS) != 0) {
  1820                 illegal();
  1822             mode = useMode;
  1823             return typeArguments(false);
  1825         return null;
  1828     /**
  1829      *  {@literal
  1830      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1831      *  }
  1832      */
  1833     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1834         if (token.kind == LT) {
  1835             nextToken();
  1836             if (token.kind == GT && diamondAllowed) {
  1837                 checkDiamond();
  1838                 mode |= DIAMOND;
  1839                 nextToken();
  1840                 return List.nil();
  1841             } else {
  1842                 ListBuffer<JCExpression> args = new ListBuffer<>();
  1843                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1844                 while (token.kind == COMMA) {
  1845                     nextToken();
  1846                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1848                 switch (token.kind) {
  1850                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1851                 case GTGTGT: case GTGT:
  1852                     token = S.split();
  1853                     break;
  1854                 case GT:
  1855                     nextToken();
  1856                     break;
  1857                 default:
  1858                     args.append(syntaxError(token.pos, "expected", GT));
  1859                     break;
  1861                 return args.toList();
  1863         } else {
  1864             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1868     /**
  1869      *  {@literal
  1870      *  TypeArgument = Type
  1871      *               | [Annotations] "?"
  1872      *               | [Annotations] "?" EXTENDS Type {"&" Type}
  1873      *               | [Annotations] "?" SUPER Type
  1874      *  }
  1875      */
  1876     JCExpression typeArgument() {
  1877         List<JCAnnotation> annotations = typeAnnotationsOpt();
  1878         if (token.kind != QUES) return parseType(annotations);
  1879         int pos = token.pos;
  1880         nextToken();
  1881         JCExpression result;
  1882         if (token.kind == EXTENDS) {
  1883             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1884             nextToken();
  1885             JCExpression bound = parseType();
  1886             result = F.at(pos).Wildcard(t, bound);
  1887         } else if (token.kind == SUPER) {
  1888             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1889             nextToken();
  1890             JCExpression bound = parseType();
  1891             result = F.at(pos).Wildcard(t, bound);
  1892         } else if (LAX_IDENTIFIER.accepts(token.kind)) {
  1893             //error recovery
  1894             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1895             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1896             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1897             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1898             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1899             result = err;
  1900         } else {
  1901             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1902             result = toP(F.at(pos).Wildcard(t, null));
  1904         if (!annotations.isEmpty()) {
  1905             result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
  1907         return result;
  1910     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1911         int pos = token.pos;
  1912         List<JCExpression> args = typeArguments(diamondAllowed);
  1913         return toP(F.at(pos).TypeApply(t, args));
  1916     /**
  1917      * BracketsOpt = { [Annotations] "[" "]" }*
  1919      * <p>
  1921      * <code>annotations</code> is the list of annotations targeting
  1922      * the expression <code>t</code>.
  1923      */
  1924     private JCExpression bracketsOpt(JCExpression t,
  1925             List<JCAnnotation> annotations) {
  1926         List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
  1928         if (token.kind == LBRACKET) {
  1929             int pos = token.pos;
  1930             nextToken();
  1931             t = bracketsOptCont(t, pos, nextLevelAnnotations);
  1932         } else if (!nextLevelAnnotations.isEmpty()) {
  1933             if (permitTypeAnnotationsPushBack) {
  1934                 this.typeAnnotationsPushedBack = nextLevelAnnotations;
  1935             } else {
  1936                 return illegal(nextLevelAnnotations.head.pos);
  1940         if (!annotations.isEmpty()) {
  1941             t = toP(F.at(token.pos).AnnotatedType(annotations, t));
  1943         return t;
  1946     /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ]
  1947      */
  1948     private JCExpression bracketsOpt(JCExpression t) {
  1949         return bracketsOpt(t, List.<JCAnnotation>nil());
  1952     private JCExpression bracketsOptCont(JCExpression t, int pos,
  1953             List<JCAnnotation> annotations) {
  1954         accept(RBRACKET);
  1955         t = bracketsOpt(t);
  1956         t = toP(F.at(pos).TypeArray(t));
  1957         if (annotations.nonEmpty()) {
  1958             t = toP(F.at(pos).AnnotatedType(annotations, t));
  1960         return t;
  1963     /** BracketsSuffixExpr = "." CLASS
  1964      *  BracketsSuffixType =
  1965      */
  1966     JCExpression bracketsSuffix(JCExpression t) {
  1967         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1968             mode = EXPR;
  1969             int pos = token.pos;
  1970             nextToken();
  1971             accept(CLASS);
  1972             if (token.pos == endPosTable.errorEndPos) {
  1973                 // error recovery
  1974                 Name name;
  1975                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  1976                     name = token.name();
  1977                     nextToken();
  1978                 } else {
  1979                     name = names.error;
  1981                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1982             } else {
  1983                 t = toP(F.at(pos).Select(t, names._class));
  1985         } else if ((mode & TYPE) != 0) {
  1986             if (token.kind != COLCOL) {
  1987                 mode = TYPE;
  1989         } else if (token.kind != COLCOL) {
  1990             syntaxError(token.pos, "dot.class.expected");
  1992         return t;
  1995     /**
  1996      * MemberReferenceSuffix = "::" [TypeArguments] Ident
  1997      *                       | "::" [TypeArguments] "new"
  1998      */
  1999     JCExpression memberReferenceSuffix(JCExpression t) {
  2000         int pos1 = token.pos;
  2001         accept(COLCOL);
  2002         return memberReferenceSuffix(pos1, t);
  2005     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  2006         checkMethodReferences();
  2007         mode = EXPR;
  2008         List<JCExpression> typeArgs = null;
  2009         if (token.kind == LT) {
  2010             typeArgs = typeArguments(false);
  2012         Name refName;
  2013         ReferenceMode refMode;
  2014         if (token.kind == NEW) {
  2015             refMode = ReferenceMode.NEW;
  2016             refName = names.init;
  2017             nextToken();
  2018         } else {
  2019             refMode = ReferenceMode.INVOKE;
  2020             refName = ident();
  2022         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  2025     /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  2026      */
  2027     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  2028         List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
  2030         switch (token.kind) {
  2031         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  2032         case DOUBLE: case BOOLEAN:
  2033             if (typeArgs == null) {
  2034                 if (newAnnotations.isEmpty()) {
  2035                     return arrayCreatorRest(newpos, basicType());
  2036                 } else {
  2037                     return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
  2040             break;
  2041         default:
  2043         JCExpression t = qualident(true);
  2045         int oldmode = mode;
  2046         mode = TYPE;
  2047         boolean diamondFound = false;
  2048         int lastTypeargsPos = -1;
  2049         if (token.kind == LT) {
  2050             checkGenerics();
  2051             lastTypeargsPos = token.pos;
  2052             t = typeArguments(t, true);
  2053             diamondFound = (mode & DIAMOND) != 0;
  2055         while (token.kind == DOT) {
  2056             if (diamondFound) {
  2057                 //cannot select after a diamond
  2058                 illegal();
  2060             int pos = token.pos;
  2061             nextToken();
  2062             List<JCAnnotation> tyannos = typeAnnotationsOpt();
  2063             t = toP(F.at(pos).Select(t, ident()));
  2065             if (tyannos != null && tyannos.nonEmpty()) {
  2066                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
  2069             if (token.kind == LT) {
  2070                 lastTypeargsPos = token.pos;
  2071                 checkGenerics();
  2072                 t = typeArguments(t, true);
  2073                 diamondFound = (mode & DIAMOND) != 0;
  2076         mode = oldmode;
  2077         if (token.kind == LBRACKET || token.kind == MONKEYS_AT) {
  2078             // handle type annotations for non primitive arrays
  2079             if (newAnnotations.nonEmpty()) {
  2080                 t = insertAnnotationsToMostInner(t, newAnnotations, false);
  2083             JCExpression e = arrayCreatorRest(newpos, t);
  2084             if (diamondFound) {
  2085                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  2086                 return toP(F.at(newpos).Erroneous(List.of(e)));
  2088             else if (typeArgs != null) {
  2089                 int pos = newpos;
  2090                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  2091                     // note: this should always happen but we should
  2092                     // not rely on this as the parser is continuously
  2093                     // modified to improve error recovery.
  2094                     pos = typeArgs.head.pos;
  2096                 setErrorEndPos(S.prevToken().endPos);
  2097                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  2098                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  2099                 return toP(err);
  2101             return e;
  2102         } else if (token.kind == LPAREN) {
  2103             JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
  2104             if (newClass.def != null) {
  2105                 assert newClass.def.mods.annotations.isEmpty();
  2106                 if (newAnnotations.nonEmpty()) {
  2107                     // Add type and declaration annotations to the new class;
  2108                     // com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitNewClass(JCNewClass)
  2109                     // will later remove all type annotations and only leave the
  2110                     // declaration annotations.
  2111                     newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
  2112                     newClass.def.mods.annotations = newAnnotations;
  2114             } else {
  2115                 // handle type annotations for instantiations
  2116                 if (newAnnotations.nonEmpty()) {
  2117                     t = insertAnnotationsToMostInner(t, newAnnotations, false);
  2118                     newClass.clazz = t;
  2121             return newClass;
  2122         } else {
  2123             setErrorEndPos(token.pos);
  2124             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  2125             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  2126             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  2130     /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
  2131      */
  2132     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  2133         List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
  2135         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  2137         if (newAnnotations.nonEmpty()) {
  2138             t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
  2141         if (token.kind == LT) {
  2142             int oldmode = mode;
  2143             checkGenerics();
  2144             t = typeArguments(t, true);
  2145             mode = oldmode;
  2147         return classCreatorRest(newpos, encl, typeArgs, t);
  2150     /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
  2151      *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
  2152      */
  2153     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  2154         List<JCAnnotation> annos = typeAnnotationsOpt();
  2156         accept(LBRACKET);
  2157         if (token.kind == RBRACKET) {
  2158             accept(RBRACKET);
  2159             elemtype = bracketsOpt(elemtype, annos);
  2160             if (token.kind == LBRACE) {
  2161                 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
  2162                 if (annos.nonEmpty()) {
  2163                     // when an array initializer is present then
  2164                     // the parsed annotations should target the
  2165                     // new array tree
  2166                     // bracketsOpt inserts the annotation in
  2167                     // elemtype, and it needs to be corrected
  2168                     //
  2169                     JCAnnotatedType annotated = (JCAnnotatedType)elemtype;
  2170                     assert annotated.annotations == annos;
  2171                     na.annotations = annotated.annotations;
  2172                     na.elemtype = annotated.underlyingType;
  2174                 return na;
  2175             } else {
  2176                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  2177                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  2179         } else {
  2180             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  2182             // maintain array dimension type annotations
  2183             ListBuffer<List<JCAnnotation>> dimAnnotations = new ListBuffer<>();
  2184             dimAnnotations.append(annos);
  2186             dims.append(parseExpression());
  2187             accept(RBRACKET);
  2188             while (token.kind == LBRACKET
  2189                     || token.kind == MONKEYS_AT) {
  2190                 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt();
  2191                 int pos = token.pos;
  2192                 nextToken();
  2193                 if (token.kind == RBRACKET) {
  2194                     elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  2195                 } else {
  2196                     if (token.kind == RBRACKET) { // no dimension
  2197                         elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  2198                     } else {
  2199                         dimAnnotations.append(maybeDimAnnos);
  2200                         dims.append(parseExpression());
  2201                         accept(RBRACKET);
  2206             JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  2207             na.dimAnnotations = dimAnnotations.toList();
  2208             return na;
  2212     /** ClassCreatorRest = Arguments [ClassBody]
  2213      */
  2214     JCNewClass classCreatorRest(int newpos,
  2215                                   JCExpression encl,
  2216                                   List<JCExpression> typeArgs,
  2217                                   JCExpression t)
  2219         List<JCExpression> args = arguments();
  2220         JCClassDecl body = null;
  2221         if (token.kind == LBRACE) {
  2222             int pos = token.pos;
  2223             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2224             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2225             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  2227         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  2230     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  2231      */
  2232     JCExpression arrayInitializer(int newpos, JCExpression t) {
  2233         accept(LBRACE);
  2234         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  2235         if (token.kind == COMMA) {
  2236             nextToken();
  2237         } else if (token.kind != RBRACE) {
  2238             elems.append(variableInitializer());
  2239             while (token.kind == COMMA) {
  2240                 nextToken();
  2241                 if (token.kind == RBRACE) break;
  2242                 elems.append(variableInitializer());
  2245         accept(RBRACE);
  2246         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  2249     /** VariableInitializer = ArrayInitializer | Expression
  2250      */
  2251     public JCExpression variableInitializer() {
  2252         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  2255     /** ParExpression = "(" Expression ")"
  2256      */
  2257     JCExpression parExpression() {
  2258         int pos = token.pos;
  2259         accept(LPAREN);
  2260         JCExpression t = parseExpression();
  2261         accept(RPAREN);
  2262         return toP(F.at(pos).Parens(t));
  2265     /** Block = "{" BlockStatements "}"
  2266      */
  2267     JCBlock block(int pos, long flags) {
  2268         accept(LBRACE);
  2269         List<JCStatement> stats = blockStatements();
  2270         JCBlock t = F.at(pos).Block(flags, stats);
  2271         while (token.kind == CASE || token.kind == DEFAULT) {
  2272             syntaxError("orphaned", token.kind);
  2273             switchBlockStatementGroups();
  2275         // the Block node has a field "endpos" for first char of last token, which is
  2276         // usually but not necessarily the last char of the last token.
  2277         t.endpos = token.pos;
  2278         accept(RBRACE);
  2279         return toP(t);
  2282     public JCBlock block() {
  2283         return block(token.pos, 0);
  2286     /** BlockStatements = { BlockStatement }
  2287      *  BlockStatement  = LocalVariableDeclarationStatement
  2288      *                  | ClassOrInterfaceOrEnumDeclaration
  2289      *                  | [Ident ":"] Statement
  2290      *  LocalVariableDeclarationStatement
  2291      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  2292      */
  2293     @SuppressWarnings("fallthrough")
  2294     List<JCStatement> blockStatements() {
  2295         //todo: skip to anchor on error(?)
  2296         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  2297         while (true) {
  2298             List<JCStatement> stat = blockStatement();
  2299             if (stat.isEmpty()) {
  2300                 return stats.toList();
  2301             } else {
  2302                 if (token.pos <= endPosTable.errorEndPos) {
  2303                     skip(false, true, true, true);
  2305                 stats.addAll(stat);
  2310     /*
  2311      * This method parses a statement treating it as a block, relaxing the
  2312      * JLS restrictions, allows us to parse more faulty code, doing so
  2313      * enables us to provide better and accurate diagnostics to the user.
  2314      */
  2315     JCStatement parseStatementAsBlock() {
  2316         int pos = token.pos;
  2317         List<JCStatement> stats = blockStatement();
  2318         if (stats.isEmpty()) {
  2319             JCErroneous e = F.at(pos).Erroneous();
  2320             error(e, "illegal.start.of.stmt");
  2321             return F.at(pos).Exec(e);
  2322         } else {
  2323             JCStatement first = stats.head;
  2324             String error = null;
  2325             switch (first.getTag()) {
  2326             case CLASSDEF:
  2327                 error = "class.not.allowed";
  2328                 break;
  2329             case VARDEF:
  2330                 error = "variable.not.allowed";
  2331                 break;
  2333             if (error != null) {
  2334                 error(first, error);
  2335                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  2336                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  2338             return first;
  2342     @SuppressWarnings("fallthrough")
  2343     List<JCStatement> blockStatement() {
  2344         //todo: skip to anchor on error(?)
  2345         int pos = token.pos;
  2346         switch (token.kind) {
  2347         case RBRACE: case CASE: case DEFAULT: case EOF:
  2348             return List.nil();
  2349         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  2350         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  2351         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  2352             return List.of(parseStatement());
  2353         case MONKEYS_AT:
  2354         case FINAL: {
  2355             Comment dc = token.comment(CommentStyle.JAVADOC);
  2356             JCModifiers mods = modifiersOpt();
  2357             if (token.kind == INTERFACE ||
  2358                 token.kind == CLASS ||
  2359                 allowEnums && token.kind == ENUM) {
  2360                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2361             } else {
  2362                 JCExpression t = parseType();
  2363                 ListBuffer<JCStatement> stats =
  2364                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2365                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2366                 storeEnd(stats.last(), token.endPos);
  2367                 accept(SEMI);
  2368                 return stats.toList();
  2371         case ABSTRACT: case STRICTFP: {
  2372             Comment dc = token.comment(CommentStyle.JAVADOC);
  2373             JCModifiers mods = modifiersOpt();
  2374             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2376         case INTERFACE:
  2377         case CLASS:
  2378             Comment dc = token.comment(CommentStyle.JAVADOC);
  2379             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2380         case ENUM:
  2381         case ASSERT:
  2382             if (allowEnums && token.kind == ENUM) {
  2383                 error(token.pos, "local.enum");
  2384                 dc = token.comment(CommentStyle.JAVADOC);
  2385                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2386             } else if (allowAsserts && token.kind == ASSERT) {
  2387                 return List.of(parseStatement());
  2389             /* fall through to default */
  2390         default:
  2391             Token prevToken = token;
  2392             JCExpression t = term(EXPR | TYPE);
  2393             if (token.kind == COLON && t.hasTag(IDENT)) {
  2394                 nextToken();
  2395                 JCStatement stat = parseStatement();
  2396                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  2397             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2398                 pos = token.pos;
  2399                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2400                 F.at(pos);
  2401                 ListBuffer<JCStatement> stats =
  2402                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2403                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2404                 storeEnd(stats.last(), token.endPos);
  2405                 accept(SEMI);
  2406                 return stats.toList();
  2407             } else {
  2408                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2409                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  2410                 accept(SEMI);
  2411                 return List.<JCStatement>of(expr);
  2416     /** Statement =
  2417      *       Block
  2418      *     | IF ParExpression Statement [ELSE Statement]
  2419      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  2420      *     | FOR "(" FormalParameter : Expression ")" Statement
  2421      *     | WHILE ParExpression Statement
  2422      *     | DO Statement WHILE ParExpression ";"
  2423      *     | TRY Block ( Catches | [Catches] FinallyPart )
  2424      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  2425      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  2426      *     | SYNCHRONIZED ParExpression Block
  2427      *     | RETURN [Expression] ";"
  2428      *     | THROW Expression ";"
  2429      *     | BREAK [Ident] ";"
  2430      *     | CONTINUE [Ident] ";"
  2431      *     | ASSERT Expression [ ":" Expression ] ";"
  2432      *     | ";"
  2433      *     | ExpressionStatement
  2434      *     | Ident ":" Statement
  2435      */
  2436     @SuppressWarnings("fallthrough")
  2437     public JCStatement parseStatement() {
  2438         int pos = token.pos;
  2439         switch (token.kind) {
  2440         case LBRACE:
  2441             return block();
  2442         case IF: {
  2443             nextToken();
  2444             JCExpression cond = parExpression();
  2445             JCStatement thenpart = parseStatementAsBlock();
  2446             JCStatement elsepart = null;
  2447             if (token.kind == ELSE) {
  2448                 nextToken();
  2449                 elsepart = parseStatementAsBlock();
  2451             return F.at(pos).If(cond, thenpart, elsepart);
  2453         case FOR: {
  2454             nextToken();
  2455             accept(LPAREN);
  2456             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  2457             if (inits.length() == 1 &&
  2458                 inits.head.hasTag(VARDEF) &&
  2459                 ((JCVariableDecl) inits.head).init == null &&
  2460                 token.kind == COLON) {
  2461                 checkForeach();
  2462                 JCVariableDecl var = (JCVariableDecl)inits.head;
  2463                 accept(COLON);
  2464                 JCExpression expr = parseExpression();
  2465                 accept(RPAREN);
  2466                 JCStatement body = parseStatementAsBlock();
  2467                 return F.at(pos).ForeachLoop(var, expr, body);
  2468             } else {
  2469                 accept(SEMI);
  2470                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  2471                 accept(SEMI);
  2472                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2473                 accept(RPAREN);
  2474                 JCStatement body = parseStatementAsBlock();
  2475                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2478         case WHILE: {
  2479             nextToken();
  2480             JCExpression cond = parExpression();
  2481             JCStatement body = parseStatementAsBlock();
  2482             return F.at(pos).WhileLoop(cond, body);
  2484         case DO: {
  2485             nextToken();
  2486             JCStatement body = parseStatementAsBlock();
  2487             accept(WHILE);
  2488             JCExpression cond = parExpression();
  2489             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2490             accept(SEMI);
  2491             return t;
  2493         case TRY: {
  2494             nextToken();
  2495             List<JCTree> resources = List.<JCTree>nil();
  2496             if (token.kind == LPAREN) {
  2497                 checkTryWithResources();
  2498                 nextToken();
  2499                 resources = resources();
  2500                 accept(RPAREN);
  2502             JCBlock body = block();
  2503             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2504             JCBlock finalizer = null;
  2505             if (token.kind == CATCH || token.kind == FINALLY) {
  2506                 while (token.kind == CATCH) catchers.append(catchClause());
  2507                 if (token.kind == FINALLY) {
  2508                     nextToken();
  2509                     finalizer = block();
  2511             } else {
  2512                 if (allowTWR) {
  2513                     if (resources.isEmpty())
  2514                         error(pos, "try.without.catch.finally.or.resource.decls");
  2515                 } else
  2516                     error(pos, "try.without.catch.or.finally");
  2518             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2520         case SWITCH: {
  2521             nextToken();
  2522             JCExpression selector = parExpression();
  2523             accept(LBRACE);
  2524             List<JCCase> cases = switchBlockStatementGroups();
  2525             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2526             accept(RBRACE);
  2527             return t;
  2529         case SYNCHRONIZED: {
  2530             nextToken();
  2531             JCExpression lock = parExpression();
  2532             JCBlock body = block();
  2533             return F.at(pos).Synchronized(lock, body);
  2535         case RETURN: {
  2536             nextToken();
  2537             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2538             JCReturn t = to(F.at(pos).Return(result));
  2539             accept(SEMI);
  2540             return t;
  2542         case THROW: {
  2543             nextToken();
  2544             JCExpression exc = parseExpression();
  2545             JCThrow t = to(F.at(pos).Throw(exc));
  2546             accept(SEMI);
  2547             return t;
  2549         case BREAK: {
  2550             nextToken();
  2551             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2552             JCBreak t = to(F.at(pos).Break(label));
  2553             accept(SEMI);
  2554             return t;
  2556         case CONTINUE: {
  2557             nextToken();
  2558             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2559             JCContinue t =  to(F.at(pos).Continue(label));
  2560             accept(SEMI);
  2561             return t;
  2563         case SEMI:
  2564             nextToken();
  2565             return toP(F.at(pos).Skip());
  2566         case ELSE:
  2567             int elsePos = token.pos;
  2568             nextToken();
  2569             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
  2570         case FINALLY:
  2571             int finallyPos = token.pos;
  2572             nextToken();
  2573             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
  2574         case CATCH:
  2575             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
  2576         case ASSERT: {
  2577             if (allowAsserts && token.kind == ASSERT) {
  2578                 nextToken();
  2579                 JCExpression assertion = parseExpression();
  2580                 JCExpression message = null;
  2581                 if (token.kind == COLON) {
  2582                     nextToken();
  2583                     message = parseExpression();
  2585                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2586                 accept(SEMI);
  2587                 return t;
  2589             /* else fall through to default case */
  2591         case ENUM:
  2592         default:
  2593             Token prevToken = token;
  2594             JCExpression expr = parseExpression();
  2595             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2596                 nextToken();
  2597                 JCStatement stat = parseStatement();
  2598                 return F.at(pos).Labelled(prevToken.name(), stat);
  2599             } else {
  2600                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2601                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2602                 accept(SEMI);
  2603                 return stat;
  2608     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
  2609         int errPos = S.errPos();
  2610         JCTree stm = action.doRecover(this);
  2611         S.errPos(errPos);
  2612         return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
  2615     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2616      * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below.
  2617      */
  2618     protected JCCatch catchClause() {
  2619         int pos = token.pos;
  2620         accept(CATCH);
  2621         accept(LPAREN);
  2622         JCModifiers mods = optFinal(Flags.PARAMETER);
  2623         List<JCExpression> catchTypes = catchTypes();
  2624         JCExpression paramType = catchTypes.size() > 1 ?
  2625                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2626                 catchTypes.head;
  2627         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2628         accept(RPAREN);
  2629         JCBlock body = block();
  2630         return F.at(pos).Catch(formal, body);
  2633     List<JCExpression> catchTypes() {
  2634         ListBuffer<JCExpression> catchTypes = new ListBuffer<>();
  2635         catchTypes.add(parseType());
  2636         while (token.kind == BAR) {
  2637             checkMulticatch();
  2638             nextToken();
  2639             // Instead of qualident this is now parseType.
  2640             // But would that allow too much, e.g. arrays or generics?
  2641             catchTypes.add(parseType());
  2643         return catchTypes.toList();
  2646     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2647      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2648      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2649      */
  2650     List<JCCase> switchBlockStatementGroups() {
  2651         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2652         while (true) {
  2653             int pos = token.pos;
  2654             switch (token.kind) {
  2655             case CASE:
  2656             case DEFAULT:
  2657                 cases.append(switchBlockStatementGroup());
  2658                 break;
  2659             case RBRACE: case EOF:
  2660                 return cases.toList();
  2661             default:
  2662                 nextToken(); // to ensure progress
  2663                 syntaxError(pos, "expected3",
  2664                     CASE, DEFAULT, RBRACE);
  2669     protected JCCase switchBlockStatementGroup() {
  2670         int pos = token.pos;
  2671         List<JCStatement> stats;
  2672         JCCase c;
  2673         switch (token.kind) {
  2674         case CASE:
  2675             nextToken();
  2676             JCExpression pat = parseExpression();
  2677             accept(COLON);
  2678             stats = blockStatements();
  2679             c = F.at(pos).Case(pat, stats);
  2680             if (stats.isEmpty())
  2681                 storeEnd(c, S.prevToken().endPos);
  2682             return c;
  2683         case DEFAULT:
  2684             nextToken();
  2685             accept(COLON);
  2686             stats = blockStatements();
  2687             c = F.at(pos).Case(null, stats);
  2688             if (stats.isEmpty())
  2689                 storeEnd(c, S.prevToken().endPos);
  2690             return c;
  2692         throw new AssertionError("should not reach here");
  2695     /** MoreStatementExpressions = { COMMA StatementExpression }
  2696      */
  2697     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2698                                                                     JCExpression first,
  2699                                                                     T stats) {
  2700         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2701         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2702         while (token.kind == COMMA) {
  2703             nextToken();
  2704             pos = token.pos;
  2705             JCExpression t = parseExpression();
  2706             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2707             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2709         return stats;
  2712     /** ForInit = StatementExpression MoreStatementExpressions
  2713      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2714      */
  2715     List<JCStatement> forInit() {
  2716         ListBuffer<JCStatement> stats = new ListBuffer<>();
  2717         int pos = token.pos;
  2718         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2719             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2720         } else {
  2721             JCExpression t = term(EXPR | TYPE);
  2722             if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2723                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2724             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2725                 error(pos, "bad.initializer", "for-loop");
  2726                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2727             } else {
  2728                 return moreStatementExpressions(pos, t, stats).toList();
  2733     /** ForUpdate = StatementExpression MoreStatementExpressions
  2734      */
  2735     List<JCExpressionStatement> forUpdate() {
  2736         return moreStatementExpressions(token.pos,
  2737                                         parseExpression(),
  2738                                         new ListBuffer<JCExpressionStatement>()).toList();
  2741     /** AnnotationsOpt = { '@' Annotation }
  2743      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
  2744      */
  2745     List<JCAnnotation> annotationsOpt(Tag kind) {
  2746         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2747         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2748         int prevmode = mode;
  2749         while (token.kind == MONKEYS_AT) {
  2750             int pos = token.pos;
  2751             nextToken();
  2752             buf.append(annotation(pos, kind));
  2754         lastmode = mode;
  2755         mode = prevmode;
  2756         List<JCAnnotation> annotations = buf.toList();
  2758         return annotations;
  2761     List<JCAnnotation> typeAnnotationsOpt() {
  2762         List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
  2763         return annotations;
  2766     /** ModifiersOpt = { Modifier }
  2767      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2768      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2769      *           | "@" Annotation
  2770      */
  2771     JCModifiers modifiersOpt() {
  2772         return modifiersOpt(null);
  2774     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2775         long flags;
  2776         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2777         int pos;
  2778         if (partial == null) {
  2779             flags = 0;
  2780             pos = token.pos;
  2781         } else {
  2782             flags = partial.flags;
  2783             annotations.appendList(partial.annotations);
  2784             pos = partial.pos;
  2786         if (token.deprecatedFlag()) {
  2787             flags |= Flags.DEPRECATED;
  2789         int lastPos;
  2790     loop:
  2791         while (true) {
  2792             long flag;
  2793             switch (token.kind) {
  2794             case PRIVATE     : flag = Flags.PRIVATE; break;
  2795             case PROTECTED   : flag = Flags.PROTECTED; break;
  2796             case PUBLIC      : flag = Flags.PUBLIC; break;
  2797             case STATIC      : flag = Flags.STATIC; break;
  2798             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2799             case FINAL       : flag = Flags.FINAL; break;
  2800             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2801             case NATIVE      : flag = Flags.NATIVE; break;
  2802             case VOLATILE    : flag = Flags.VOLATILE; break;
  2803             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2804             case STRICTFP    : flag = Flags.STRICTFP; break;
  2805             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2806             case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
  2807             case ERROR       : flag = 0; nextToken(); break;
  2808             default: break loop;
  2810             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2811             lastPos = token.pos;
  2812             nextToken();
  2813             if (flag == Flags.ANNOTATION) {
  2814                 checkAnnotations();
  2815                 if (token.kind != INTERFACE) {
  2816                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
  2817                     // if first modifier is an annotation, set pos to annotation's.
  2818                     if (flags == 0 && annotations.isEmpty())
  2819                         pos = ann.pos;
  2820                     annotations.append(ann);
  2821                     flag = 0;
  2824             flags |= flag;
  2826         switch (token.kind) {
  2827         case ENUM: flags |= Flags.ENUM; break;
  2828         case INTERFACE: flags |= Flags.INTERFACE; break;
  2829         default: break;
  2832         /* A modifiers tree with no modifier tokens or annotations
  2833          * has no text position. */
  2834         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2835             pos = Position.NOPOS;
  2837         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2838         if (pos != Position.NOPOS)
  2839             storeEnd(mods, S.prevToken().endPos);
  2840         return mods;
  2843     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2845      * @param pos position of "@" token
  2846      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
  2847      */
  2848     JCAnnotation annotation(int pos, Tag kind) {
  2849         // accept(AT); // AT consumed by caller
  2850         checkAnnotations();
  2851         if (kind == Tag.TYPE_ANNOTATION) {
  2852             checkTypeAnnotations();
  2854         JCTree ident = qualident(false);
  2855         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2856         JCAnnotation ann;
  2857         if (kind == Tag.ANNOTATION) {
  2858             ann = F.at(pos).Annotation(ident, fieldValues);
  2859         } else if (kind == Tag.TYPE_ANNOTATION) {
  2860             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
  2861         } else {
  2862             throw new AssertionError("Unhandled annotation kind: " + kind);
  2865         storeEnd(ann, S.prevToken().endPos);
  2866         return ann;
  2869     List<JCExpression> annotationFieldValuesOpt() {
  2870         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2873     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2874     List<JCExpression> annotationFieldValues() {
  2875         accept(LPAREN);
  2876         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2877         if (token.kind != RPAREN) {
  2878             buf.append(annotationFieldValue());
  2879             while (token.kind == COMMA) {
  2880                 nextToken();
  2881                 buf.append(annotationFieldValue());
  2884         accept(RPAREN);
  2885         return buf.toList();
  2888     /** AnnotationFieldValue    = AnnotationValue
  2889      *                          | Identifier "=" AnnotationValue
  2890      */
  2891     JCExpression annotationFieldValue() {
  2892         if (LAX_IDENTIFIER.accepts(token.kind)) {
  2893             mode = EXPR;
  2894             JCExpression t1 = term1();
  2895             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2896                 int pos = token.pos;
  2897                 accept(EQ);
  2898                 JCExpression v = annotationValue();
  2899                 return toP(F.at(pos).Assign(t1, v));
  2900             } else {
  2901                 return t1;
  2904         return annotationValue();
  2907     /* AnnotationValue          = ConditionalExpression
  2908      *                          | Annotation
  2909      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2910      */
  2911     JCExpression annotationValue() {
  2912         int pos;
  2913         switch (token.kind) {
  2914         case MONKEYS_AT:
  2915             pos = token.pos;
  2916             nextToken();
  2917             return annotation(pos, Tag.ANNOTATION);
  2918         case LBRACE:
  2919             pos = token.pos;
  2920             accept(LBRACE);
  2921             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2922             if (token.kind == COMMA) {
  2923                 nextToken();
  2924             } else if (token.kind != RBRACE) {
  2925                 buf.append(annotationValue());
  2926                 while (token.kind == COMMA) {
  2927                     nextToken();
  2928                     if (token.kind == RBRACE) break;
  2929                     buf.append(annotationValue());
  2932             accept(RBRACE);
  2933             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2934         default:
  2935             mode = EXPR;
  2936             return term1();
  2940     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2941      */
  2942     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2943                                                                          JCExpression type,
  2944                                                                          T vdefs)
  2946         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2949     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2950      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2952      *  @param reqInit  Is an initializer always required?
  2953      *  @param dc       The documentation comment for the variable declarations, or null.
  2954      */
  2955     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2956                                                                      JCModifiers mods,
  2957                                                                      JCExpression type,
  2958                                                                      Name name,
  2959                                                                      boolean reqInit,
  2960                                                                      Comment dc,
  2961                                                                      T vdefs)
  2963         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2964         while (token.kind == COMMA) {
  2965             // All but last of multiple declarators subsume a comma
  2966             storeEnd((JCTree)vdefs.last(), token.endPos);
  2967             nextToken();
  2968             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2970         return vdefs;
  2973     /** VariableDeclarator = Ident VariableDeclaratorRest
  2974      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2975      */
  2976     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2977         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2980     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2981      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2983      *  @param reqInit  Is an initializer always required?
  2984      *  @param dc       The documentation comment for the variable declarations, or null.
  2985      */
  2986     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2987                                   boolean reqInit, Comment dc) {
  2988         type = bracketsOpt(type);
  2989         JCExpression init = null;
  2990         if (token.kind == EQ) {
  2991             nextToken();
  2992             init = variableInitializer();
  2994         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2995         JCVariableDecl result =
  2996             toP(F.at(pos).VarDef(mods, name, type, init));
  2997         attach(result, dc);
  2998         return result;
  3001     /** VariableDeclaratorId = Ident BracketsOpt
  3002      */
  3003     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  3004         return variableDeclaratorId(mods, type, false);
  3006     //where
  3007     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
  3008         int pos = token.pos;
  3009         Name name;
  3010         if (lambdaParameter && token.kind == UNDERSCORE) {
  3011             log.error(pos, "underscore.as.identifier.in.lambda");
  3012             name = token.name();
  3013             nextToken();
  3014         } else {
  3015             if (allowThisIdent) {
  3016                 JCExpression pn = qualident(false);
  3017                 if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
  3018                     name = ((JCIdent)pn).name;
  3019                 } else {
  3020                     if ((mods.flags & Flags.VARARGS) != 0) {
  3021                         log.error(token.pos, "varargs.and.receiver");
  3023                     if (token.kind == LBRACKET) {
  3024                         log.error(token.pos, "array.and.receiver");
  3026                     return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
  3028             } else {
  3029                 name = ident();
  3032         if ((mods.flags & Flags.VARARGS) != 0 &&
  3033                 token.kind == LBRACKET) {
  3034             log.error(token.pos, "varargs.and.old.array.syntax");
  3036         type = bracketsOpt(type);
  3037         return toP(F.at(pos).VarDef(mods, name, type, null));
  3040     /** Resources = Resource { ";" Resources }
  3041      */
  3042     List<JCTree> resources() {
  3043         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3044         defs.append(resource());
  3045         while (token.kind == SEMI) {
  3046             // All but last of multiple declarators must subsume a semicolon
  3047             storeEnd(defs.last(), token.endPos);
  3048             int semiColonPos = token.pos;
  3049             nextToken();
  3050             if (token.kind == RPAREN) { // Optional trailing semicolon
  3051                                        // after last resource
  3052                 break;
  3054             defs.append(resource());
  3056         return defs.toList();
  3059     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  3060      */
  3061     protected JCTree resource() {
  3062         JCModifiers optFinal = optFinal(Flags.FINAL);
  3063         JCExpression type = parseType();
  3064         int pos = token.pos;
  3065         Name ident = ident();
  3066         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  3069     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  3070      */
  3071     public JCTree.JCCompilationUnit parseCompilationUnit() {
  3072         Token firstToken = token;
  3073         JCExpression pid = null;
  3074         JCModifiers mods = null;
  3075         boolean consumedToplevelDoc = false;
  3076         boolean seenImport = false;
  3077         boolean seenPackage = false;
  3078         List<JCAnnotation> packageAnnotations = List.nil();
  3079         if (token.kind == MONKEYS_AT)
  3080             mods = modifiersOpt();
  3082         if (token.kind == PACKAGE) {
  3083             seenPackage = true;
  3084             if (mods != null) {
  3085                 checkNoMods(mods.flags);
  3086                 packageAnnotations = mods.annotations;
  3087                 mods = null;
  3089             nextToken();
  3090             pid = qualident(false);
  3091             accept(SEMI);
  3093         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3094         boolean checkForImports = true;
  3095         boolean firstTypeDecl = true;
  3096         while (token.kind != EOF) {
  3097             if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
  3098                 // error recovery
  3099                 skip(checkForImports, false, false, false);
  3100                 if (token.kind == EOF)
  3101                     break;
  3103             if (checkForImports && mods == null && token.kind == IMPORT) {
  3104                 seenImport = true;
  3105                 defs.append(importDeclaration());
  3106             } else {
  3107                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  3108                 if (firstTypeDecl && !seenImport && !seenPackage) {
  3109                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  3110                     consumedToplevelDoc = true;
  3112                 JCTree def = typeDeclaration(mods, docComment);
  3113                 if (def instanceof JCExpressionStatement)
  3114                     def = ((JCExpressionStatement)def).expr;
  3115                 defs.append(def);
  3116                 if (def instanceof JCClassDecl)
  3117                     checkForImports = false;
  3118                 mods = null;
  3119                 firstTypeDecl = false;
  3122         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  3123         if (!consumedToplevelDoc)
  3124             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  3125         if (defs.isEmpty())
  3126             storeEnd(toplevel, S.prevToken().endPos);
  3127         if (keepDocComments)
  3128             toplevel.docComments = docComments;
  3129         if (keepLineMap)
  3130             toplevel.lineMap = S.getLineMap();
  3131         this.endPosTable.setParser(null); // remove reference to parser
  3132         toplevel.endPositions = this.endPosTable;
  3133         return toplevel;
  3136     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  3137      */
  3138     JCTree importDeclaration() {
  3139         int pos = token.pos;
  3140         nextToken();
  3141         boolean importStatic = false;
  3142         if (token.kind == STATIC) {
  3143             checkStaticImports();
  3144             importStatic = true;
  3145             nextToken();
  3147         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  3148         do {
  3149             int pos1 = token.pos;
  3150             accept(DOT);
  3151             if (token.kind == STAR) {
  3152                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  3153                 nextToken();
  3154                 break;
  3155             } else {
  3156                 pid = toP(F.at(pos1).Select(pid, ident()));
  3158         } while (token.kind == DOT);
  3159         accept(SEMI);
  3160         return toP(F.at(pos).Import(pid, importStatic));
  3163     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  3164      *                  | ";"
  3165      */
  3166     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  3167         int pos = token.pos;
  3168         if (mods == null && token.kind == SEMI) {
  3169             nextToken();
  3170             return toP(F.at(pos).Skip());
  3171         } else {
  3172             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  3176     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  3177      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  3178      *  @param mods     Any modifiers starting the class or interface declaration
  3179      *  @param dc       The documentation comment for the class, or null.
  3180      */
  3181     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  3182         if (token.kind == CLASS) {
  3183             return classDeclaration(mods, dc);
  3184         } else if (token.kind == INTERFACE) {
  3185             return interfaceDeclaration(mods, dc);
  3186         } else if (allowEnums) {
  3187             if (token.kind == ENUM) {
  3188                 return enumDeclaration(mods, dc);
  3189             } else {
  3190                 int pos = token.pos;
  3191                 List<JCTree> errs;
  3192                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  3193                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  3194                     setErrorEndPos(token.pos);
  3195                 } else {
  3196                     errs = List.<JCTree>of(mods);
  3198                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  3199                                               CLASS, INTERFACE, ENUM)));
  3201         } else {
  3202             if (token.kind == ENUM) {
  3203                 error(token.pos, "enums.not.supported.in.source", source.name);
  3204                 allowEnums = true;
  3205                 return enumDeclaration(mods, dc);
  3207             int pos = token.pos;
  3208             List<JCTree> errs;
  3209             if (LAX_IDENTIFIER.accepts(token.kind)) {
  3210                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  3211                 setErrorEndPos(token.pos);
  3212             } else {
  3213                 errs = List.<JCTree>of(mods);
  3215             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  3216                                           CLASS, INTERFACE)));
  3220     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  3221      *                     [IMPLEMENTS TypeList] ClassBody
  3222      *  @param mods    The modifiers starting the class declaration
  3223      *  @param dc       The documentation comment for the class, or null.
  3224      */
  3225     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  3226         int pos = token.pos;
  3227         accept(CLASS);
  3228         Name name = ident();
  3230         List<JCTypeParameter> typarams = typeParametersOpt();
  3232         JCExpression extending = null;
  3233         if (token.kind == EXTENDS) {
  3234             nextToken();
  3235             extending = parseType();
  3237         List<JCExpression> implementing = List.nil();
  3238         if (token.kind == IMPLEMENTS) {
  3239             nextToken();
  3240             implementing = typeList();
  3242         List<JCTree> defs = classOrInterfaceBody(name, false);
  3243         JCClassDecl result = toP(F.at(pos).ClassDef(
  3244             mods, name, typarams, extending, implementing, defs));
  3245         attach(result, dc);
  3246         return result;
  3249     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  3250      *                         [EXTENDS TypeList] InterfaceBody
  3251      *  @param mods    The modifiers starting the interface declaration
  3252      *  @param dc       The documentation comment for the interface, or null.
  3253      */
  3254     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  3255         int pos = token.pos;
  3256         accept(INTERFACE);
  3257         Name name = ident();
  3259         List<JCTypeParameter> typarams = typeParametersOpt();
  3261         List<JCExpression> extending = List.nil();
  3262         if (token.kind == EXTENDS) {
  3263             nextToken();
  3264             extending = typeList();
  3266         List<JCTree> defs = classOrInterfaceBody(name, true);
  3267         JCClassDecl result = toP(F.at(pos).ClassDef(
  3268             mods, name, typarams, null, extending, defs));
  3269         attach(result, dc);
  3270         return result;
  3273     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  3274      *  @param mods    The modifiers starting the enum declaration
  3275      *  @param dc       The documentation comment for the enum, or null.
  3276      */
  3277     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  3278         int pos = token.pos;
  3279         accept(ENUM);
  3280         Name name = ident();
  3282         List<JCExpression> implementing = List.nil();
  3283         if (token.kind == IMPLEMENTS) {
  3284             nextToken();
  3285             implementing = typeList();
  3288         List<JCTree> defs = enumBody(name);
  3289         mods.flags |= Flags.ENUM;
  3290         JCClassDecl result = toP(F.at(pos).
  3291             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  3292                 null, implementing, defs));
  3293         attach(result, dc);
  3294         return result;
  3297     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  3298      *                  [ ";" {ClassBodyDeclaration} ] "}"
  3299      */
  3300     List<JCTree> enumBody(Name enumName) {
  3301         accept(LBRACE);
  3302         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3303         if (token.kind == COMMA) {
  3304             nextToken();
  3305         } else if (token.kind != RBRACE && token.kind != SEMI) {
  3306             defs.append(enumeratorDeclaration(enumName));
  3307             while (token.kind == COMMA) {
  3308                 nextToken();
  3309                 if (token.kind == RBRACE || token.kind == SEMI) break;
  3310                 defs.append(enumeratorDeclaration(enumName));
  3312             if (token.kind != SEMI && token.kind != RBRACE) {
  3313                 defs.append(syntaxError(token.pos, "expected3",
  3314                                 COMMA, RBRACE, SEMI));
  3315                 nextToken();
  3318         if (token.kind == SEMI) {
  3319             nextToken();
  3320             while (token.kind != RBRACE && token.kind != EOF) {
  3321                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  3322                                                                 false));
  3323                 if (token.pos <= endPosTable.errorEndPos) {
  3324                     // error recovery
  3325                    skip(false, true, true, false);
  3329         accept(RBRACE);
  3330         return defs.toList();
  3333     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  3334      */
  3335     JCTree enumeratorDeclaration(Name enumName) {
  3336         Comment dc = token.comment(CommentStyle.JAVADOC);
  3337         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  3338         if (token.deprecatedFlag()) {
  3339             flags |= Flags.DEPRECATED;
  3341         int pos = token.pos;
  3342         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
  3343         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  3344         List<JCExpression> typeArgs = typeArgumentsOpt();
  3345         int identPos = token.pos;
  3346         Name name = ident();
  3347         int createPos = token.pos;
  3348         List<JCExpression> args = (token.kind == LPAREN)
  3349             ? arguments() : List.<JCExpression>nil();
  3350         JCClassDecl body = null;
  3351         if (token.kind == LBRACE) {
  3352             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  3353             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  3354             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  3356         if (args.isEmpty() && body == null)
  3357             createPos = identPos;
  3358         JCIdent ident = F.at(identPos).Ident(enumName);
  3359         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  3360         if (createPos != identPos)
  3361             storeEnd(create, S.prevToken().endPos);
  3362         ident = F.at(identPos).Ident(enumName);
  3363         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  3364         attach(result, dc);
  3365         return result;
  3368     /** TypeList = Type {"," Type}
  3369      */
  3370     List<JCExpression> typeList() {
  3371         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3372         ts.append(parseType());
  3373         while (token.kind == COMMA) {
  3374             nextToken();
  3375             ts.append(parseType());
  3377         return ts.toList();
  3380     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  3381      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  3382      */
  3383     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  3384         accept(LBRACE);
  3385         if (token.pos <= endPosTable.errorEndPos) {
  3386             // error recovery
  3387             skip(false, true, false, false);
  3388             if (token.kind == LBRACE)
  3389                 nextToken();
  3391         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3392         while (token.kind != RBRACE && token.kind != EOF) {
  3393             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  3394             if (token.pos <= endPosTable.errorEndPos) {
  3395                // error recovery
  3396                skip(false, true, true, false);
  3399         accept(RBRACE);
  3400         return defs.toList();
  3403     /** ClassBodyDeclaration =
  3404      *      ";"
  3405      *    | [STATIC] Block
  3406      *    | ModifiersOpt
  3407      *      ( Type Ident
  3408      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  3409      *      | VOID Ident VoidMethodDeclaratorRest
  3410      *      | TypeParameters [Annotations]
  3411      *        ( Type Ident MethodDeclaratorRest
  3412      *        | VOID Ident VoidMethodDeclaratorRest
  3413      *        )
  3414      *      | Ident ConstructorDeclaratorRest
  3415      *      | TypeParameters Ident ConstructorDeclaratorRest
  3416      *      | ClassOrInterfaceOrEnumDeclaration
  3417      *      )
  3418      *  InterfaceBodyDeclaration =
  3419      *      ";"
  3420      *    | ModifiersOpt
  3421      *      ( Type Ident
  3422      *        ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
  3423      *      | VOID Ident MethodDeclaratorRest
  3424      *      | TypeParameters [Annotations]
  3425      *        ( Type Ident MethodDeclaratorRest
  3426      *        | VOID Ident VoidMethodDeclaratorRest
  3427      *        )
  3428      *      | ClassOrInterfaceOrEnumDeclaration
  3429      *      )
  3431      */
  3432     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  3433         if (token.kind == SEMI) {
  3434             nextToken();
  3435             return List.<JCTree>nil();
  3436         } else {
  3437             Comment dc = token.comment(CommentStyle.JAVADOC);
  3438             int pos = token.pos;
  3439             JCModifiers mods = modifiersOpt();
  3440             if (token.kind == CLASS ||
  3441                 token.kind == INTERFACE ||
  3442                 allowEnums && token.kind == ENUM) {
  3443                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  3444             } else if (token.kind == LBRACE && !isInterface &&
  3445                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  3446                        mods.annotations.isEmpty()) {
  3447                 return List.<JCTree>of(block(pos, mods.flags));
  3448             } else {
  3449                 pos = token.pos;
  3450                 List<JCTypeParameter> typarams = typeParametersOpt();
  3451                 // if there are type parameters but no modifiers, save the start
  3452                 // position of the method in the modifiers.
  3453                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  3454                     mods.pos = pos;
  3455                     storeEnd(mods, pos);
  3457                 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
  3459                 if (annosAfterParams.nonEmpty()) {
  3460                     checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
  3461                     mods.annotations = mods.annotations.appendList(annosAfterParams);
  3462                     if (mods.pos == Position.NOPOS)
  3463                         mods.pos = mods.annotations.head.pos;
  3466                 Token tk = token;
  3467                 pos = token.pos;
  3468                 JCExpression type;
  3469                 boolean isVoid = token.kind == VOID;
  3470                 if (isVoid) {
  3471                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
  3472                     nextToken();
  3473                 } else {
  3474                     // method returns types are un-annotated types
  3475                     type = unannotatedType();
  3477                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  3478                     if (isInterface || tk.name() != className)
  3479                         error(pos, "invalid.meth.decl.ret.type.req");
  3480                     else if (annosAfterParams.nonEmpty())
  3481                         illegal(annosAfterParams.head.pos);
  3482                     return List.of(methodDeclaratorRest(
  3483                         pos, mods, null, names.init, typarams,
  3484                         isInterface, true, dc));
  3485                 } else {
  3486                     pos = token.pos;
  3487                     Name name = ident();
  3488                     if (token.kind == LPAREN) {
  3489                         return List.of(methodDeclaratorRest(
  3490                             pos, mods, type, name, typarams,
  3491                             isInterface, isVoid, dc));
  3492                     } else if (!isVoid && typarams.isEmpty()) {
  3493                         List<JCTree> defs =
  3494                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  3495                                                     new ListBuffer<JCTree>()).toList();
  3496                         storeEnd(defs.last(), token.endPos);
  3497                         accept(SEMI);
  3498                         return defs;
  3499                     } else {
  3500                         pos = token.pos;
  3501                         List<JCTree> err = isVoid
  3502                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3503                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  3504                             : null;
  3505                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  3512     /** MethodDeclaratorRest =
  3513      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  3514      *  VoidMethodDeclaratorRest =
  3515      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
  3516      *  ConstructorDeclaratorRest =
  3517      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  3518      */
  3519     protected JCTree methodDeclaratorRest(int pos,
  3520                               JCModifiers mods,
  3521                               JCExpression type,
  3522                               Name name,
  3523                               List<JCTypeParameter> typarams,
  3524                               boolean isInterface, boolean isVoid,
  3525                               Comment dc) {
  3526         if (isInterface && (mods.flags & Flags.STATIC) != 0) {
  3527             checkStaticInterfaceMethods();
  3529         JCVariableDecl prevReceiverParam = this.receiverParam;
  3530         try {
  3531             this.receiverParam = null;
  3532             // Parsing formalParameters sets the receiverParam, if present
  3533             List<JCVariableDecl> params = formalParameters();
  3534             if (!isVoid) type = bracketsOpt(type);
  3535             List<JCExpression> thrown = List.nil();
  3536             if (token.kind == THROWS) {
  3537                 nextToken();
  3538                 thrown = qualidentList();
  3540             JCBlock body = null;
  3541             JCExpression defaultValue;
  3542             if (token.kind == LBRACE) {
  3543                 body = block();
  3544                 defaultValue = null;
  3545             } else {
  3546                 if (token.kind == DEFAULT) {
  3547                     accept(DEFAULT);
  3548                     defaultValue = annotationValue();
  3549                 } else {
  3550                     defaultValue = null;
  3552                 accept(SEMI);
  3553                 if (token.pos <= endPosTable.errorEndPos) {
  3554                     // error recovery
  3555                     skip(false, true, false, false);
  3556                     if (token.kind == LBRACE) {
  3557                         body = block();
  3562             JCMethodDecl result =
  3563                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3564                                             receiverParam, params, thrown,
  3565                                             body, defaultValue));
  3566             attach(result, dc);
  3567             return result;
  3568         } finally {
  3569             this.receiverParam = prevReceiverParam;
  3573     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
  3574      */
  3575     List<JCExpression> qualidentList() {
  3576         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3578         List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
  3579         JCExpression qi = qualident(true);
  3580         if (!typeAnnos.isEmpty()) {
  3581             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
  3582             ts.append(at);
  3583         } else {
  3584             ts.append(qi);
  3586         while (token.kind == COMMA) {
  3587             nextToken();
  3589             typeAnnos = typeAnnotationsOpt();
  3590             qi = qualident(true);
  3591             if (!typeAnnos.isEmpty()) {
  3592                 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
  3593                 ts.append(at);
  3594             } else {
  3595                 ts.append(qi);
  3598         return ts.toList();
  3601     /**
  3602      *  {@literal
  3603      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3604      *  }
  3605      */
  3606     List<JCTypeParameter> typeParametersOpt() {
  3607         if (token.kind == LT) {
  3608             checkGenerics();
  3609             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3610             nextToken();
  3611             typarams.append(typeParameter());
  3612             while (token.kind == COMMA) {
  3613                 nextToken();
  3614                 typarams.append(typeParameter());
  3616             accept(GT);
  3617             return typarams.toList();
  3618         } else {
  3619             return List.nil();
  3623     /**
  3624      *  {@literal
  3625      *  TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
  3626      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3627      *  TypeVariable = Ident
  3628      *  }
  3629      */
  3630     JCTypeParameter typeParameter() {
  3631         int pos = token.pos;
  3632         List<JCAnnotation> annos = typeAnnotationsOpt();
  3633         Name name = ident();
  3634         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3635         if (token.kind == EXTENDS) {
  3636             nextToken();
  3637             bounds.append(parseType());
  3638             while (token.kind == AMP) {
  3639                 nextToken();
  3640                 bounds.append(parseType());
  3643         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
  3646     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3647      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3648      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3649      */
  3650     List<JCVariableDecl> formalParameters() {
  3651         return formalParameters(false);
  3653     List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
  3654         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3655         JCVariableDecl lastParam;
  3656         accept(LPAREN);
  3657         if (token.kind != RPAREN) {
  3658             this.allowThisIdent = true;
  3659             lastParam = formalParameter(lambdaParameters);
  3660             if (lastParam.nameexpr != null) {
  3661                 this.receiverParam = lastParam;
  3662             } else {
  3663                 params.append(lastParam);
  3665             this.allowThisIdent = false;
  3666             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3667                 nextToken();
  3668                 params.append(lastParam = formalParameter(lambdaParameters));
  3671         accept(RPAREN);
  3672         return params.toList();
  3675     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3676         if (hasParens) {
  3677             accept(LPAREN);
  3679         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3680         if (token.kind != RPAREN && token.kind != ARROW) {
  3681             params.append(implicitParameter());
  3682             while (token.kind == COMMA) {
  3683                 nextToken();
  3684                 params.append(implicitParameter());
  3687         if (hasParens) {
  3688             accept(RPAREN);
  3690         return params.toList();
  3693     JCModifiers optFinal(long flags) {
  3694         JCModifiers mods = modifiersOpt();
  3695         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3696         mods.flags |= flags;
  3697         return mods;
  3700     /**
  3701      * Inserts the annotations (and possibly a new array level)
  3702      * to the left-most type in an array or nested type.
  3704      * When parsing a type like {@code @B Outer.Inner @A []}, the
  3705      * {@code @A} annotation should target the array itself, while
  3706      * {@code @B} targets the nested type {@code Outer}.
  3708      * Currently the parser parses the annotation first, then
  3709      * the array, and then inserts the annotation to the left-most
  3710      * nested type.
  3712      * When {@code createNewLevel} is true, then a new array
  3713      * level is inserted as the most inner type, and have the
  3714      * annotations target it.  This is useful in the case of
  3715      * varargs, e.g. {@code String @A [] @B ...}, as the parser
  3716      * first parses the type {@code String @A []} then inserts
  3717      * a new array level with {@code @B} annotation.
  3718      */
  3719     private JCExpression insertAnnotationsToMostInner(
  3720             JCExpression type, List<JCAnnotation> annos,
  3721             boolean createNewLevel) {
  3722         int origEndPos = getEndPos(type);
  3723         JCExpression mostInnerType = type;
  3724         JCArrayTypeTree mostInnerArrayType = null;
  3725         while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
  3726             mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
  3727             mostInnerType = mostInnerArrayType.elemtype;
  3730         if (createNewLevel) {
  3731             mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
  3734         JCExpression mostInnerTypeToReturn = mostInnerType;
  3735         if (annos.nonEmpty()) {
  3736             JCExpression lastToModify = mostInnerType;
  3738             while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
  3739                     TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
  3740                 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
  3741                     lastToModify = mostInnerType;
  3742                     mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
  3744                 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
  3745                     lastToModify = mostInnerType;
  3746                     mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
  3750             mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
  3752             if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
  3753                 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
  3754             } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
  3755                 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
  3756             } else {
  3757                 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
  3758                 mostInnerTypeToReturn = mostInnerType;
  3762         if (mostInnerArrayType == null) {
  3763             return mostInnerTypeToReturn;
  3764         } else {
  3765             mostInnerArrayType.elemtype = mostInnerTypeToReturn;
  3766             storeEnd(type, origEndPos);
  3767             return type;
  3771     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3772      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3773      */
  3774     protected JCVariableDecl formalParameter() {
  3775         return formalParameter(false);
  3777     protected JCVariableDecl formalParameter(boolean lambdaParameter) {
  3778         JCModifiers mods = optFinal(Flags.PARAMETER);
  3779         // need to distinguish between vararg annos and array annos
  3780         // look at typeAnnotationsPushedBack comment
  3781         this.permitTypeAnnotationsPushBack = true;
  3782         JCExpression type = parseType();
  3783         this.permitTypeAnnotationsPushBack = false;
  3785         if (token.kind == ELLIPSIS) {
  3786             List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
  3787             typeAnnotationsPushedBack = List.nil();
  3788             checkVarargs();
  3789             mods.flags |= Flags.VARARGS;
  3790             // insert var arg type annotations
  3791             type = insertAnnotationsToMostInner(type, varargsAnnos, true);
  3792             nextToken();
  3793         } else {
  3794             // if not a var arg, then typeAnnotationsPushedBack should be null
  3795             if (typeAnnotationsPushedBack.nonEmpty()) {
  3796                 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
  3797                         "illegal.start.of.type");
  3799             typeAnnotationsPushedBack = List.nil();
  3801         return variableDeclaratorId(mods, type, lambdaParameter);
  3804     protected JCVariableDecl implicitParameter() {
  3805         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3806         return variableDeclaratorId(mods, null, true);
  3809 /* ---------- auxiliary methods -------------- */
  3811     void error(int pos, String key, Object ... args) {
  3812         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3815     void error(DiagnosticPosition pos, String key, Object ... args) {
  3816         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3819     void warning(int pos, String key, Object ... args) {
  3820         log.warning(pos, key, args);
  3823     /** Check that given tree is a legal expression statement.
  3824      */
  3825     protected JCExpression checkExprStat(JCExpression t) {
  3826         if (!TreeInfo.isExpressionStatement(t)) {
  3827             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3828             error(ret, "not.stmt");
  3829             return ret;
  3830         } else {
  3831             return t;
  3835     /** Return precedence of operator represented by token,
  3836      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3837      */
  3838     static int prec(TokenKind token) {
  3839         JCTree.Tag oc = optag(token);
  3840         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3843     /**
  3844      * Return the lesser of two positions, making allowance for either one
  3845      * being unset.
  3846      */
  3847     static int earlier(int pos1, int pos2) {
  3848         if (pos1 == Position.NOPOS)
  3849             return pos2;
  3850         if (pos2 == Position.NOPOS)
  3851             return pos1;
  3852         return (pos1 < pos2 ? pos1 : pos2);
  3855     /** Return operation tag of binary operator represented by token,
  3856      *  No_TAG if token is not a binary operator.
  3857      */
  3858     static JCTree.Tag optag(TokenKind token) {
  3859         switch (token) {
  3860         case BARBAR:
  3861             return OR;
  3862         case AMPAMP:
  3863             return AND;
  3864         case BAR:
  3865             return BITOR;
  3866         case BAREQ:
  3867             return BITOR_ASG;
  3868         case CARET:
  3869             return BITXOR;
  3870         case CARETEQ:
  3871             return BITXOR_ASG;
  3872         case AMP:
  3873             return BITAND;
  3874         case AMPEQ:
  3875             return BITAND_ASG;
  3876         case EQEQ:
  3877             return JCTree.Tag.EQ;
  3878         case BANGEQ:
  3879             return NE;
  3880         case LT:
  3881             return JCTree.Tag.LT;
  3882         case GT:
  3883             return JCTree.Tag.GT;
  3884         case LTEQ:
  3885             return LE;
  3886         case GTEQ:
  3887             return GE;
  3888         case LTLT:
  3889             return SL;
  3890         case LTLTEQ:
  3891             return SL_ASG;
  3892         case GTGT:
  3893             return SR;
  3894         case GTGTEQ:
  3895             return SR_ASG;
  3896         case GTGTGT:
  3897             return USR;
  3898         case GTGTGTEQ:
  3899             return USR_ASG;
  3900         case PLUS:
  3901             return JCTree.Tag.PLUS;
  3902         case PLUSEQ:
  3903             return PLUS_ASG;
  3904         case SUB:
  3905             return MINUS;
  3906         case SUBEQ:
  3907             return MINUS_ASG;
  3908         case STAR:
  3909             return MUL;
  3910         case STAREQ:
  3911             return MUL_ASG;
  3912         case SLASH:
  3913             return DIV;
  3914         case SLASHEQ:
  3915             return DIV_ASG;
  3916         case PERCENT:
  3917             return MOD;
  3918         case PERCENTEQ:
  3919             return MOD_ASG;
  3920         case INSTANCEOF:
  3921             return TYPETEST;
  3922         default:
  3923             return NO_TAG;
  3927     /** Return operation tag of unary operator represented by token,
  3928      *  No_TAG if token is not a binary operator.
  3929      */
  3930     static JCTree.Tag unoptag(TokenKind token) {
  3931         switch (token) {
  3932         case PLUS:
  3933             return POS;
  3934         case SUB:
  3935             return NEG;
  3936         case BANG:
  3937             return NOT;
  3938         case TILDE:
  3939             return COMPL;
  3940         case PLUSPLUS:
  3941             return PREINC;
  3942         case SUBSUB:
  3943             return PREDEC;
  3944         default:
  3945             return NO_TAG;
  3949     /** Return type tag of basic type represented by token,
  3950      *  NONE if token is not a basic type identifier.
  3951      */
  3952     static TypeTag typetag(TokenKind token) {
  3953         switch (token) {
  3954         case BYTE:
  3955             return TypeTag.BYTE;
  3956         case CHAR:
  3957             return TypeTag.CHAR;
  3958         case SHORT:
  3959             return TypeTag.SHORT;
  3960         case INT:
  3961             return TypeTag.INT;
  3962         case LONG:
  3963             return TypeTag.LONG;
  3964         case FLOAT:
  3965             return TypeTag.FLOAT;
  3966         case DOUBLE:
  3967             return TypeTag.DOUBLE;
  3968         case BOOLEAN:
  3969             return TypeTag.BOOLEAN;
  3970         default:
  3971             return TypeTag.NONE;
  3975     void checkGenerics() {
  3976         if (!allowGenerics) {
  3977             error(token.pos, "generics.not.supported.in.source", source.name);
  3978             allowGenerics = true;
  3981     void checkVarargs() {
  3982         if (!allowVarargs) {
  3983             error(token.pos, "varargs.not.supported.in.source", source.name);
  3984             allowVarargs = true;
  3987     void checkForeach() {
  3988         if (!allowForeach) {
  3989             error(token.pos, "foreach.not.supported.in.source", source.name);
  3990             allowForeach = true;
  3993     void checkStaticImports() {
  3994         if (!allowStaticImport) {
  3995             error(token.pos, "static.import.not.supported.in.source", source.name);
  3996             allowStaticImport = true;
  3999     void checkAnnotations() {
  4000         if (!allowAnnotations) {
  4001             error(token.pos, "annotations.not.supported.in.source", source.name);
  4002             allowAnnotations = true;
  4005     void checkDiamond() {
  4006         if (!allowDiamond) {
  4007             error(token.pos, "diamond.not.supported.in.source", source.name);
  4008             allowDiamond = true;
  4011     void checkMulticatch() {
  4012         if (!allowMulticatch) {
  4013             error(token.pos, "multicatch.not.supported.in.source", source.name);
  4014             allowMulticatch = true;
  4017     void checkTryWithResources() {
  4018         if (!allowTWR) {
  4019             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  4020             allowTWR = true;
  4023     void checkLambda() {
  4024         if (!allowLambda) {
  4025             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  4026             allowLambda = true;
  4029     void checkMethodReferences() {
  4030         if (!allowMethodReferences) {
  4031             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  4032             allowMethodReferences = true;
  4035     void checkDefaultMethods() {
  4036         if (!allowDefaultMethods) {
  4037             log.error(token.pos, "default.methods.not.supported.in.source", source.name);
  4038             allowDefaultMethods = true;
  4041     void checkIntersectionTypesInCast() {
  4042         if (!allowIntersectionTypesInCast) {
  4043             log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
  4044             allowIntersectionTypesInCast = true;
  4047     void checkStaticInterfaceMethods() {
  4048         if (!allowStaticInterfaceMethods) {
  4049             log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name);
  4050             allowStaticInterfaceMethods = true;
  4053     void checkTypeAnnotations() {
  4054         if (!allowTypeAnnotations) {
  4055             log.error(token.pos, "type.annotations.not.supported.in.source", source.name);
  4056             allowTypeAnnotations = true;
  4059     void checkAnnotationsAfterTypeParams(int pos) {
  4060         if (!allowAnnotationsAfterTypeParams) {
  4061             log.error(pos, "annotations.after.type.params.not.supported.in.source", source.name);
  4062             allowAnnotationsAfterTypeParams = true;
  4066     /*
  4067      * a functional source tree and end position mappings
  4068      */
  4069     protected static class SimpleEndPosTable extends AbstractEndPosTable {
  4071         private final IntHashTable endPosMap;
  4073         SimpleEndPosTable(JavacParser parser) {
  4074             super(parser);
  4075             endPosMap = new IntHashTable();
  4078         public void storeEnd(JCTree tree, int endpos) {
  4079             endPosMap.putAtIndex(tree, errorEndPos > endpos ? errorEndPos : endpos,
  4080                                  endPosMap.lookup(tree));
  4083         protected <T extends JCTree> T to(T t) {
  4084             storeEnd(t, parser.token.endPos);
  4085             return t;
  4088         protected <T extends JCTree> T toP(T t) {
  4089             storeEnd(t, parser.S.prevToken().endPos);
  4090             return t;
  4093         public int getEndPos(JCTree tree) {
  4094             int value = endPosMap.getFromIndex(endPosMap.lookup(tree));
  4095             // As long as Position.NOPOS==-1, this just returns value.
  4096             return (value == -1) ? Position.NOPOS : value;
  4099         public int replaceTree(JCTree oldTree, JCTree newTree) {
  4100             int pos = endPosMap.remove(oldTree);
  4101             if (pos != -1) {
  4102                 storeEnd(newTree, pos);
  4103                 return pos;
  4105             return Position.NOPOS;
  4109     /*
  4110      * a default skeletal implementation without any mapping overhead.
  4111      */
  4112     protected static class EmptyEndPosTable extends AbstractEndPosTable {
  4114         EmptyEndPosTable(JavacParser parser) {
  4115             super(parser);
  4118         public void storeEnd(JCTree tree, int endpos) { /* empty */ }
  4120         protected <T extends JCTree> T to(T t) {
  4121             return t;
  4124         protected <T extends JCTree> T toP(T t) {
  4125             return t;
  4128         public int getEndPos(JCTree tree) {
  4129             return Position.NOPOS;
  4132         public int replaceTree(JCTree oldTree, JCTree newTree) {
  4133             return Position.NOPOS;
  4138     protected static abstract class AbstractEndPosTable implements EndPosTable {
  4139         /**
  4140          * The current parser.
  4141          */
  4142         protected JavacParser parser;
  4144         /**
  4145          * Store the last error position.
  4146          */
  4147         protected int errorEndPos;
  4149         public AbstractEndPosTable(JavacParser parser) {
  4150             this.parser = parser;
  4153         /**
  4154          * Store current token's ending position for a tree, the value of which
  4155          * will be the greater of last error position and the ending position of
  4156          * the current token.
  4157          * @param t The tree.
  4158          */
  4159         protected abstract <T extends JCTree> T to(T t);
  4161         /**
  4162          * Store current token's ending position for a tree, the value of which
  4163          * will be the greater of last error position and the ending position of
  4164          * the previous token.
  4165          * @param t The tree.
  4166          */
  4167         protected abstract <T extends JCTree> T toP(T t);
  4169         /**
  4170          * Set the error position during the parsing phases, the value of which
  4171          * will be set only if it is greater than the last stored error position.
  4172          * @param errPos The error position
  4173          */
  4174         protected void setErrorEndPos(int errPos) {
  4175             if (errPos > errorEndPos) {
  4176                 errorEndPos = errPos;
  4180         protected void setParser(JavacParser parser) {
  4181             this.parser = parser;

mercurial