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

Sun, 17 Feb 2013 16:44:55 -0500

author
dholmes
date
Sun, 17 Feb 2013 16:44:55 -0500
changeset 1571
af8417e590f4
parent 1563
bc456436c613
child 1583
186023614cd3
permissions
-rw-r--r--

Merge

     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.*;
    51 import static com.sun.tools.javac.util.ListBuffer.lb;
    53 /** The parser maps a token sequence into an abstract syntax
    54  *  tree. It operates by recursive descent, with code derived
    55  *  systematically from an LL(1) grammar. For efficiency reasons, an
    56  *  operator precedence scheme is used for parsing binary operation
    57  *  expressions.
    58  *
    59  *  <p><b>This is NOT part of any supported API.
    60  *  If you write code that depends on this, you do so at your own risk.
    61  *  This code and its internal interfaces are subject to change or
    62  *  deletion without notice.</b>
    63  */
    64 public class JavacParser implements Parser {
    66     /** The number of precedence levels of infix operators.
    67      */
    68     private static final int infixPrecedenceLevels = 10;
    70     /** The scanner used for lexical analysis.
    71      */
    72     protected Lexer S;
    74     /** The factory to be used for abstract syntax tree construction.
    75      */
    76     protected TreeMaker F;
    78     /** The log to be used for error diagnostics.
    79      */
    80     private Log log;
    82     /** The Source language setting. */
    83     private Source source;
    85     /** The name table. */
    86     private Names names;
    88     /** End position mappings container */
    89     private final AbstractEndPosTable endPosTable;
    91     // Because of javac's limited lookahead, some contexts are ambiguous in
    92     // the presence of type annotations even though they are not ambiguous
    93     // in the absence of type annotations.  Consider this code:
    94     //   void m(String [] m) { }
    95     //   void m(String ... m) { }
    96     // After parsing "String", javac calls bracketsOpt which immediately
    97     // returns if the next character is not '['.  Similarly, javac can see
    98     // if the next token is ... and in that case parse an ellipsis.  But in
    99     // the presence of type annotations:
   100     //   void m(String @A [] m) { }
   101     //   void m(String @A ... m) { }
   102     // no finite lookahead is enough to determine whether to read array
   103     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
   104     // bracketsOpt first reads all the leading annotations and only then
   105     // discovers that it needs to fail.  bracketsOpt needs a way to push
   106     // back the extra annotations that it read.  (But, bracketsOpt should
   107     // not *always* be allowed to push back extra annotations that it finds
   108     // -- in most contexts, any such extra annotation is an error.
   109     //
   110     // The following two variables permit type annotations that have
   111     // already been read to be stored for later use.  Alternate
   112     // implementations are possible but would cause much larger changes to
   113     // the parser.
   115     /** Type annotations that have already been read but have not yet been used. **/
   116     private List<JCAnnotation> typeAnnotationsPushedBack = List.nil();
   118     /**
   119      * If the parser notices extra annotations, then it either immediately
   120      * issues an error (if this variable is false) or places the extra
   121      * annotations in variable typeAnnotationsPushedBack (if this variable
   122      * is true).
   123      */
   124     private boolean permitTypeAnnotationsPushBack = false;
   126     interface ErrorRecoveryAction {
   127         JCTree doRecover(JavacParser parser);
   128     }
   130     enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
   131         BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
   132         CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
   133     }
   135     /** Construct a parser from a given scanner, tree factory and log.
   136      */
   137     protected JavacParser(ParserFactory fac,
   138                      Lexer S,
   139                      boolean keepDocComments,
   140                      boolean keepLineMap,
   141                      boolean keepEndPositions) {
   142         this.S = S;
   143         nextToken(); // prime the pump
   144         this.F = fac.F;
   145         this.log = fac.log;
   146         this.names = fac.names;
   147         this.source = fac.source;
   148         this.allowGenerics = source.allowGenerics();
   149         this.allowVarargs = source.allowVarargs();
   150         this.allowAsserts = source.allowAsserts();
   151         this.allowEnums = source.allowEnums();
   152         this.allowForeach = source.allowForeach();
   153         this.allowStaticImport = source.allowStaticImport();
   154         this.allowAnnotations = source.allowAnnotations();
   155         this.allowTWR = source.allowTryWithResources();
   156         this.allowDiamond = source.allowDiamond();
   157         this.allowMulticatch = source.allowMulticatch();
   158         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   159         this.allowLambda = source.allowLambda();
   160         this.allowMethodReferences = source.allowMethodReferences();
   161         this.allowDefaultMethods = source.allowDefaultMethods();
   162         this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
   163         this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
   164         this.allowTypeAnnotations = source.allowTypeAnnotations();
   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()
   175                 : new EmptyEndPosTable();
   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: is "this" allowed as an identifier?
   259      * This is needed to parse receiver types.
   260      */
   261     boolean allowThisIdent;
   263     /** The type of the method receiver, as specified by a first "this" parameter.
   264      */
   265     JCVariableDecl receiverParam;
   268     /** When terms are parsed, the mode determines which is expected:
   269      *     mode = EXPR        : an expression
   270      *     mode = TYPE        : a type
   271      *     mode = NOPARAMS    : no parameters allowed for type
   272      *     mode = TYPEARG     : type argument
   273      */
   274     static final int EXPR = 0x1;
   275     static final int TYPE = 0x2;
   276     static final int NOPARAMS = 0x4;
   277     static final int TYPEARG = 0x8;
   278     static final int DIAMOND = 0x10;
   280     /** The current mode.
   281      */
   282     private int mode = 0;
   284     /** The mode of the term that was parsed last.
   285      */
   286     private int lastmode = 0;
   288     /* ---------- token management -------------- */
   290     protected Token token;
   292     public Token token() {
   293         return token;
   294     }
   296     public void nextToken() {
   297         S.nextToken();
   298         token = S.token();
   299     }
   301     protected boolean peekToken(Filter<TokenKind> tk) {
   302         return peekToken(0, tk);
   303     }
   305     protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
   306         return tk.accepts(S.token(lookahead + 1).kind);
   307     }
   309     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   310         return peekToken(0, tk1, tk2);
   311     }
   313     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   314         return tk1.accepts(S.token(lookahead + 1).kind) &&
   315                 tk2.accepts(S.token(lookahead + 2).kind);
   316     }
   318     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   319         return peekToken(0, tk1, tk2, tk3);
   320     }
   322     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   323         return tk1.accepts(S.token(lookahead + 1).kind) &&
   324                 tk2.accepts(S.token(lookahead + 2).kind) &&
   325                 tk3.accepts(S.token(lookahead + 3).kind);
   326     }
   328     @SuppressWarnings("unchecked")
   329     protected boolean peekToken(Filter<TokenKind>... kinds) {
   330         return peekToken(0, kinds);
   331     }
   333     @SuppressWarnings("unchecked")
   334     protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
   335         for (; lookahead < kinds.length ; lookahead++) {
   336             if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
   337                 return false;
   338             }
   339         }
   340         return true;
   341     }
   343     /* ---------- error recovery -------------- */
   345     private JCErroneous errorTree;
   347     /** Skip forward until a suitable stop token is found.
   348      */
   349     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   350          while (true) {
   351              switch (token.kind) {
   352                 case SEMI:
   353                     nextToken();
   354                     return;
   355                 case PUBLIC:
   356                 case FINAL:
   357                 case ABSTRACT:
   358                 case MONKEYS_AT:
   359                 case EOF:
   360                 case CLASS:
   361                 case INTERFACE:
   362                 case ENUM:
   363                     return;
   364                 case IMPORT:
   365                     if (stopAtImport)
   366                         return;
   367                     break;
   368                 case LBRACE:
   369                 case RBRACE:
   370                 case PRIVATE:
   371                 case PROTECTED:
   372                 case STATIC:
   373                 case TRANSIENT:
   374                 case NATIVE:
   375                 case VOLATILE:
   376                 case SYNCHRONIZED:
   377                 case STRICTFP:
   378                 case LT:
   379                 case BYTE:
   380                 case SHORT:
   381                 case CHAR:
   382                 case INT:
   383                 case LONG:
   384                 case FLOAT:
   385                 case DOUBLE:
   386                 case BOOLEAN:
   387                 case VOID:
   388                     if (stopAtMemberDecl)
   389                         return;
   390                     break;
   391                 case UNDERSCORE:
   392                 case IDENTIFIER:
   393                    if (stopAtIdentifier)
   394                         return;
   395                     break;
   396                 case CASE:
   397                 case DEFAULT:
   398                 case IF:
   399                 case FOR:
   400                 case WHILE:
   401                 case DO:
   402                 case TRY:
   403                 case SWITCH:
   404                 case RETURN:
   405                 case THROW:
   406                 case BREAK:
   407                 case CONTINUE:
   408                 case ELSE:
   409                 case FINALLY:
   410                 case CATCH:
   411                     if (stopAtStatement)
   412                         return;
   413                     break;
   414             }
   415             nextToken();
   416         }
   417     }
   419     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   420         return syntaxError(pos, List.<JCTree>nil(), key, args);
   421     }
   423     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   424         setErrorEndPos(pos);
   425         JCErroneous err = F.at(pos).Erroneous(errs);
   426         reportSyntaxError(err, key, (Object[])args);
   427         if (errs != null) {
   428             JCTree last = errs.last();
   429             if (last != null)
   430                 storeEnd(last, pos);
   431         }
   432         return toP(err);
   433     }
   435     private int errorPos = Position.NOPOS;
   437     /**
   438      * Report a syntax using the given the position parameter and arguments,
   439      * unless one was already reported at the same position.
   440      */
   441     private void reportSyntaxError(int pos, String key, Object... args) {
   442         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   443         reportSyntaxError(diag, key, args);
   444     }
   446     /**
   447      * Report a syntax error using the given DiagnosticPosition object and
   448      * arguments, unless one was already reported at the same position.
   449      */
   450     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   451         int pos = diagPos.getPreferredPosition();
   452         if (pos > S.errPos() || pos == Position.NOPOS) {
   453             if (token.kind == EOF) {
   454                 error(diagPos, "premature.eof");
   455             } else {
   456                 error(diagPos, key, args);
   457             }
   458         }
   459         S.errPos(pos);
   460         if (token.pos == errorPos)
   461             nextToken(); // guarantee progress
   462         errorPos = token.pos;
   463     }
   466     /** Generate a syntax error at current position unless one was already
   467      *  reported at the same position.
   468      */
   469     private JCErroneous syntaxError(String key) {
   470         return syntaxError(token.pos, key);
   471     }
   473     /** Generate a syntax error at current position unless one was
   474      *  already reported at the same position.
   475      */
   476     private JCErroneous syntaxError(String key, TokenKind arg) {
   477         return syntaxError(token.pos, key, arg);
   478     }
   480     /** If next input token matches given token, skip it, otherwise report
   481      *  an error.
   482      */
   483     public void accept(TokenKind tk) {
   484         if (token.kind == tk) {
   485             nextToken();
   486         } else {
   487             setErrorEndPos(token.pos);
   488             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   489         }
   490     }
   492     /** Report an illegal start of expression/type error at given position.
   493      */
   494     JCExpression illegal(int pos) {
   495         setErrorEndPos(pos);
   496         if ((mode & EXPR) != 0)
   497             return syntaxError(pos, "illegal.start.of.expr");
   498         else
   499             return syntaxError(pos, "illegal.start.of.type");
   501     }
   503     /** Report an illegal start of expression/type error at current position.
   504      */
   505     JCExpression illegal() {
   506         return illegal(token.pos);
   507     }
   509     /** Diagnose a modifier flag from the set, if any. */
   510     void checkNoMods(long mods) {
   511         if (mods != 0) {
   512             long lowestMod = mods & -mods;
   513             error(token.pos, "mod.not.allowed.here",
   514                       Flags.asFlagSet(lowestMod));
   515         }
   516     }
   518 /* ---------- doc comments --------- */
   520     /** A table to store all documentation comments
   521      *  indexed by the tree nodes they refer to.
   522      *  defined only if option flag keepDocComment is set.
   523      */
   524     private final DocCommentTable docComments;
   526     /** Make an entry into docComments hashtable,
   527      *  provided flag keepDocComments is set and given doc comment is non-null.
   528      *  @param tree   The tree to be used as index in the hashtable
   529      *  @param dc     The doc comment to associate with the tree, or null.
   530      */
   531     void attach(JCTree tree, Comment dc) {
   532         if (keepDocComments && dc != null) {
   533 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   534             docComments.putComment(tree, dc);
   535         }
   536     }
   538 /* -------- source positions ------- */
   540     private void setErrorEndPos(int errPos) {
   541         endPosTable.setErrorEndPos(errPos);
   542     }
   544     private void storeEnd(JCTree tree, int endpos) {
   545         endPosTable.storeEnd(tree, endpos);
   546     }
   548     private <T extends JCTree> T to(T t) {
   549         return endPosTable.to(t);
   550     }
   552     private <T extends JCTree> T toP(T t) {
   553         return endPosTable.toP(t);
   554     }
   556     /** Get the start position for a tree node.  The start position is
   557      * defined to be the position of the first character of the first
   558      * token of the node's source text.
   559      * @param tree  The tree node
   560      */
   561     public int getStartPos(JCTree tree) {
   562         return TreeInfo.getStartPos(tree);
   563     }
   565     /**
   566      * Get the end position for a tree node.  The end position is
   567      * defined to be the position of the last character of the last
   568      * token of the node's source text.  Returns Position.NOPOS if end
   569      * positions are not generated or the position is otherwise not
   570      * found.
   571      * @param tree  The tree node
   572      */
   573     public int getEndPos(JCTree tree) {
   574         return endPosTable.getEndPos(tree);
   575     }
   579 /* ---------- parsing -------------- */
   581     /**
   582      * Ident = IDENTIFIER
   583      */
   584     Name ident() {
   585         if (token.kind == IDENTIFIER) {
   586             Name name = token.name();
   587             nextToken();
   588             return name;
   589         } else if (token.kind == ASSERT) {
   590             if (allowAsserts) {
   591                 error(token.pos, "assert.as.identifier");
   592                 nextToken();
   593                 return names.error;
   594             } else {
   595                 warning(token.pos, "assert.as.identifier");
   596                 Name name = token.name();
   597                 nextToken();
   598                 return name;
   599             }
   600         } else if (token.kind == ENUM) {
   601             if (allowEnums) {
   602                 error(token.pos, "enum.as.identifier");
   603                 nextToken();
   604                 return names.error;
   605             } else {
   606                 warning(token.pos, "enum.as.identifier");
   607                 Name name = token.name();
   608                 nextToken();
   609                 return name;
   610             }
   611         } else if (token.kind == THIS) {
   612             if (allowThisIdent) {
   613                 // Make sure we're using a supported source version.
   614                 checkTypeAnnotations();
   615                 Name name = token.name();
   616                 nextToken();
   617                 return name;
   618             } else {
   619                 error(token.pos, "this.as.identifier");
   620                 nextToken();
   621                 return names.error;
   622             }
   623         } else if (token.kind == UNDERSCORE) {
   624             warning(token.pos, "underscore.as.identifier");
   625             Name name = token.name();
   626             nextToken();
   627             return name;
   628         } else {
   629             accept(IDENTIFIER);
   630             return names.error;
   631         }
   632     }
   634     /**
   635      * Qualident = Ident { DOT [Annotations] Ident }
   636      */
   637     public JCExpression qualident(boolean allowAnnos) {
   638         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   639         while (token.kind == DOT) {
   640             int pos = token.pos;
   641             nextToken();
   642             List<JCAnnotation> tyannos = null;
   643             if (allowAnnos) {
   644                 tyannos = typeAnnotationsOpt();
   645             }
   646             t = toP(F.at(pos).Select(t, ident()));
   647             if (tyannos != null && tyannos.nonEmpty()) {
   648                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
   649             }
   650         }
   651         return t;
   652     }
   654     JCExpression literal(Name prefix) {
   655         return literal(prefix, token.pos);
   656     }
   658     /**
   659      * Literal =
   660      *     INTLITERAL
   661      *   | LONGLITERAL
   662      *   | FLOATLITERAL
   663      *   | DOUBLELITERAL
   664      *   | CHARLITERAL
   665      *   | STRINGLITERAL
   666      *   | TRUE
   667      *   | FALSE
   668      *   | NULL
   669      */
   670     JCExpression literal(Name prefix, int pos) {
   671         JCExpression t = errorTree;
   672         switch (token.kind) {
   673         case INTLITERAL:
   674             try {
   675                 t = F.at(pos).Literal(
   676                     TypeTag.INT,
   677                     Convert.string2int(strval(prefix), token.radix()));
   678             } catch (NumberFormatException ex) {
   679                 error(token.pos, "int.number.too.large", strval(prefix));
   680             }
   681             break;
   682         case LONGLITERAL:
   683             try {
   684                 t = F.at(pos).Literal(
   685                     TypeTag.LONG,
   686                     new Long(Convert.string2long(strval(prefix), token.radix())));
   687             } catch (NumberFormatException ex) {
   688                 error(token.pos, "int.number.too.large", strval(prefix));
   689             }
   690             break;
   691         case FLOATLITERAL: {
   692             String proper = token.radix() == 16 ?
   693                     ("0x"+ token.stringVal()) :
   694                     token.stringVal();
   695             Float n;
   696             try {
   697                 n = Float.valueOf(proper);
   698             } catch (NumberFormatException ex) {
   699                 // error already reported in scanner
   700                 n = Float.NaN;
   701             }
   702             if (n.floatValue() == 0.0f && !isZero(proper))
   703                 error(token.pos, "fp.number.too.small");
   704             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   705                 error(token.pos, "fp.number.too.large");
   706             else
   707                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
   708             break;
   709         }
   710         case DOUBLELITERAL: {
   711             String proper = token.radix() == 16 ?
   712                     ("0x"+ token.stringVal()) :
   713                     token.stringVal();
   714             Double n;
   715             try {
   716                 n = Double.valueOf(proper);
   717             } catch (NumberFormatException ex) {
   718                 // error already reported in scanner
   719                 n = Double.NaN;
   720             }
   721             if (n.doubleValue() == 0.0d && !isZero(proper))
   722                 error(token.pos, "fp.number.too.small");
   723             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   724                 error(token.pos, "fp.number.too.large");
   725             else
   726                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
   727             break;
   728         }
   729         case CHARLITERAL:
   730             t = F.at(pos).Literal(
   731                 TypeTag.CHAR,
   732                 token.stringVal().charAt(0) + 0);
   733             break;
   734         case STRINGLITERAL:
   735             t = F.at(pos).Literal(
   736                 TypeTag.CLASS,
   737                 token.stringVal());
   738             break;
   739         case TRUE: case FALSE:
   740             t = F.at(pos).Literal(
   741                 TypeTag.BOOLEAN,
   742                 (token.kind == TRUE ? 1 : 0));
   743             break;
   744         case NULL:
   745             t = F.at(pos).Literal(
   746                 TypeTag.BOT,
   747                 null);
   748             break;
   749         default:
   750             Assert.error();
   751         }
   752         if (t == errorTree)
   753             t = F.at(pos).Erroneous();
   754         storeEnd(t, token.endPos);
   755         nextToken();
   756         return t;
   757     }
   758     //where
   759         boolean isZero(String s) {
   760             char[] cs = s.toCharArray();
   761             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   762             int i = ((base==16) ? 2 : 0);
   763             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   764             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   765         }
   767         String strval(Name prefix) {
   768             String s = token.stringVal();
   769             return prefix.isEmpty() ? s : prefix + s;
   770         }
   772     /** terms can be either expressions or types.
   773      */
   774     public JCExpression parseExpression() {
   775         return term(EXPR);
   776     }
   778     /**
   779      * parses (optional) type annotations followed by a type. If the
   780      * annotations are present before the type and are not consumed during array
   781      * parsing, this method returns a {@link JCAnnotatedType} consisting of
   782      * these annotations and the underlying type. Otherwise, it returns the
   783      * underlying type.
   784      *
   785      * <p>
   786      *
   787      * Note that this method sets {@code mode} to {@code TYPE} first, before
   788      * parsing annotations.
   789      */
   790     public JCExpression parseType() {
   791         List<JCAnnotation> annotations = typeAnnotationsOpt();
   792         return parseType(annotations);
   793     }
   795     public JCExpression parseType(List<JCAnnotation> annotations) {
   796         JCExpression result = unannotatedType();
   798         if (annotations.nonEmpty()) {
   799             result = insertAnnotationsToMostInner(result, annotations, false);
   800         }
   802         return result;
   803     }
   805     public JCExpression unannotatedType() {
   806         return term(TYPE);
   807     }
   809     JCExpression term(int newmode) {
   810         int prevmode = mode;
   811         mode = newmode;
   812         JCExpression t = term();
   813         lastmode = mode;
   814         mode = prevmode;
   815         return t;
   816     }
   818     /**
   819      *  {@literal
   820      *  Expression = Expression1 [ExpressionRest]
   821      *  ExpressionRest = [AssignmentOperator Expression1]
   822      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   823      *                       "&=" | "|=" | "^=" |
   824      *                       "%=" | "<<=" | ">>=" | ">>>="
   825      *  Type = Type1
   826      *  TypeNoParams = TypeNoParams1
   827      *  StatementExpression = Expression
   828      *  ConstantExpression = Expression
   829      *  }
   830      */
   831     JCExpression term() {
   832         JCExpression t = term1();
   833         if ((mode & EXPR) != 0 &&
   834             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   835             return termRest(t);
   836         else
   837             return t;
   838     }
   840     JCExpression termRest(JCExpression t) {
   841         switch (token.kind) {
   842         case EQ: {
   843             int pos = token.pos;
   844             nextToken();
   845             mode = EXPR;
   846             JCExpression t1 = term();
   847             return toP(F.at(pos).Assign(t, t1));
   848         }
   849         case PLUSEQ:
   850         case SUBEQ:
   851         case STAREQ:
   852         case SLASHEQ:
   853         case PERCENTEQ:
   854         case AMPEQ:
   855         case BAREQ:
   856         case CARETEQ:
   857         case LTLTEQ:
   858         case GTGTEQ:
   859         case GTGTGTEQ:
   860             int pos = token.pos;
   861             TokenKind tk = token.kind;
   862             nextToken();
   863             mode = EXPR;
   864             JCExpression t1 = term();
   865             return F.at(pos).Assignop(optag(tk), t, t1);
   866         default:
   867             return t;
   868         }
   869     }
   871     /** Expression1   = Expression2 [Expression1Rest]
   872      *  Type1         = Type2
   873      *  TypeNoParams1 = TypeNoParams2
   874      */
   875     JCExpression term1() {
   876         JCExpression t = term2();
   877         if ((mode & EXPR) != 0 && token.kind == QUES) {
   878             mode = EXPR;
   879             return term1Rest(t);
   880         } else {
   881             return t;
   882         }
   883     }
   885     /** Expression1Rest = ["?" Expression ":" Expression1]
   886      */
   887     JCExpression term1Rest(JCExpression t) {
   888         if (token.kind == QUES) {
   889             int pos = token.pos;
   890             nextToken();
   891             JCExpression t1 = term();
   892             accept(COLON);
   893             JCExpression t2 = term1();
   894             return F.at(pos).Conditional(t, t1, t2);
   895         } else {
   896             return t;
   897         }
   898     }
   900     /** Expression2   = Expression3 [Expression2Rest]
   901      *  Type2         = Type3
   902      *  TypeNoParams2 = TypeNoParams3
   903      */
   904     JCExpression term2() {
   905         JCExpression t = term3();
   906         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   907             mode = EXPR;
   908             return term2Rest(t, TreeInfo.orPrec);
   909         } else {
   910             return t;
   911         }
   912     }
   914     /*  Expression2Rest = {infixop Expression3}
   915      *                  | Expression3 instanceof Type
   916      *  infixop         = "||"
   917      *                  | "&&"
   918      *                  | "|"
   919      *                  | "^"
   920      *                  | "&"
   921      *                  | "==" | "!="
   922      *                  | "<" | ">" | "<=" | ">="
   923      *                  | "<<" | ">>" | ">>>"
   924      *                  | "+" | "-"
   925      *                  | "*" | "/" | "%"
   926      */
   927     JCExpression term2Rest(JCExpression t, int minprec) {
   928         JCExpression[] odStack = newOdStack();
   929         Token[] opStack = newOpStack();
   931         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   932         int top = 0;
   933         odStack[0] = t;
   934         int startPos = token.pos;
   935         Token topOp = Tokens.DUMMY;
   936         while (prec(token.kind) >= minprec) {
   937             opStack[top] = topOp;
   938             top++;
   939             topOp = token;
   940             nextToken();
   941             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   942             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   943                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   944                                         odStack[top]);
   945                 top--;
   946                 topOp = opStack[top];
   947             }
   948         }
   949         Assert.check(top == 0);
   950         t = odStack[0];
   952         if (t.hasTag(JCTree.Tag.PLUS)) {
   953             StringBuilder buf = foldStrings(t);
   954             if (buf != null) {
   955                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
   956             }
   957         }
   959         odStackSupply.add(odStack);
   960         opStackSupply.add(opStack);
   961         return t;
   962     }
   963     //where
   964         /** Construct a binary or type test node.
   965          */
   966         private JCExpression makeOp(int pos,
   967                                     TokenKind topOp,
   968                                     JCExpression od1,
   969                                     JCExpression od2)
   970         {
   971             if (topOp == INSTANCEOF) {
   972                 return F.at(pos).TypeTest(od1, od2);
   973             } else {
   974                 return F.at(pos).Binary(optag(topOp), od1, od2);
   975             }
   976         }
   977         /** If tree is a concatenation of string literals, replace it
   978          *  by a single literal representing the concatenated string.
   979          */
   980         protected StringBuilder foldStrings(JCTree tree) {
   981             if (!allowStringFolding)
   982                 return null;
   983             List<String> buf = List.nil();
   984             while (true) {
   985                 if (tree.hasTag(LITERAL)) {
   986                     JCLiteral lit = (JCLiteral) tree;
   987                     if (lit.typetag == TypeTag.CLASS) {
   988                         StringBuilder sbuf =
   989                             new StringBuilder((String)lit.value);
   990                         while (buf.nonEmpty()) {
   991                             sbuf.append(buf.head);
   992                             buf = buf.tail;
   993                         }
   994                         return sbuf;
   995                     }
   996                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   997                     JCBinary op = (JCBinary)tree;
   998                     if (op.rhs.hasTag(LITERAL)) {
   999                         JCLiteral lit = (JCLiteral) op.rhs;
  1000                         if (lit.typetag == TypeTag.CLASS) {
  1001                             buf = buf.prepend((String) lit.value);
  1002                             tree = op.lhs;
  1003                             continue;
  1007                 return null;
  1011         /** optimization: To save allocating a new operand/operator stack
  1012          *  for every binary operation, we use supplys.
  1013          */
  1014         ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>();
  1015         ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>();
  1017         private JCExpression[] newOdStack() {
  1018             if (odStackSupply.isEmpty())
  1019                 return new JCExpression[infixPrecedenceLevels + 1];
  1020             return odStackSupply.remove(odStackSupply.size() - 1);
  1023         private Token[] newOpStack() {
  1024             if (opStackSupply.isEmpty())
  1025                 return new Token[infixPrecedenceLevels + 1];
  1026             return opStackSupply.remove(opStackSupply.size() - 1);
  1029     /**
  1030      *  Expression3    = PrefixOp Expression3
  1031      *                 | "(" Expr | TypeNoParams ")" Expression3
  1032      *                 | Primary {Selector} {PostfixOp}
  1034      *  {@literal
  1035      *  Primary        = "(" Expression ")"
  1036      *                 | Literal
  1037      *                 | [TypeArguments] THIS [Arguments]
  1038      *                 | [TypeArguments] SUPER SuperSuffix
  1039      *                 | NEW [TypeArguments] Creator
  1040      *                 | "(" Arguments ")" "->" ( Expression | Block )
  1041      *                 | Ident "->" ( Expression | Block )
  1042      *                 | [Annotations] Ident { "." [Annotations] Ident }
  1043      *                 | Expression3 MemberReferenceSuffix
  1044      *                   [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
  1045      *                   | Arguments
  1046      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
  1047      *                   ]
  1048      *                 | BasicType BracketsOpt "." CLASS
  1049      *  }
  1051      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
  1052      *  PostfixOp      = "++" | "--"
  1053      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
  1054      *                 | BasicType
  1055      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
  1056      *  Selector       = "." [TypeArguments] Ident [Arguments]
  1057      *                 | "." THIS
  1058      *                 | "." [TypeArguments] SUPER SuperSuffix
  1059      *                 | "." NEW [TypeArguments] InnerCreator
  1060      *                 | "[" Expression "]"
  1061      *  TypeSelector   = "." Ident [TypeArguments]
  1062      *  SuperSuffix    = Arguments | "." Ident [Arguments]
  1063      */
  1064     protected JCExpression term3() {
  1065         int pos = token.pos;
  1066         JCExpression t;
  1067         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
  1068         switch (token.kind) {
  1069         case QUES:
  1070             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
  1071                 mode = TYPE;
  1072                 return typeArgument();
  1073             } else
  1074                 return illegal();
  1075         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
  1076             if (typeArgs == null && (mode & EXPR) != 0) {
  1077                 TokenKind tk = token.kind;
  1078                 nextToken();
  1079                 mode = EXPR;
  1080                 if (tk == SUB &&
  1081                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
  1082                     token.radix() == 10) {
  1083                     mode = EXPR;
  1084                     t = literal(names.hyphen, pos);
  1085                 } else {
  1086                     t = term3();
  1087                     return F.at(pos).Unary(unoptag(tk), t);
  1089             } else return illegal();
  1090             break;
  1091         case LPAREN:
  1092             if (typeArgs == null && (mode & EXPR) != 0) {
  1093                 ParensResult pres = analyzeParens();
  1094                 switch (pres) {
  1095                     case CAST:
  1096                        accept(LPAREN);
  1097                        mode = TYPE;
  1098                        int pos1 = pos;
  1099                        List<JCExpression> targets = List.of(t = term3());
  1100                        while (token.kind == AMP) {
  1101                            checkIntersectionTypesInCast();
  1102                            accept(AMP);
  1103                            targets = targets.prepend(term3());
  1105                        if (targets.length() > 1) {
  1106                            t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
  1108                        accept(RPAREN);
  1109                        mode = EXPR;
  1110                        JCExpression t1 = term3();
  1111                        return F.at(pos).TypeCast(t, t1);
  1112                     case IMPLICIT_LAMBDA:
  1113                     case EXPLICIT_LAMBDA:
  1114                         t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
  1115                         break;
  1116                     default: //PARENS
  1117                         accept(LPAREN);
  1118                         mode = EXPR;
  1119                         t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
  1120                         accept(RPAREN);
  1121                         t = toP(F.at(pos).Parens(t));
  1122                         break;
  1124             } else {
  1125                 return illegal();
  1127             break;
  1128         case THIS:
  1129             if ((mode & EXPR) != 0) {
  1130                 mode = EXPR;
  1131                 t = to(F.at(pos).Ident(names._this));
  1132                 nextToken();
  1133                 if (typeArgs == null)
  1134                     t = argumentsOpt(null, t);
  1135                 else
  1136                     t = arguments(typeArgs, t);
  1137                 typeArgs = null;
  1138             } else return illegal();
  1139             break;
  1140         case SUPER:
  1141             if ((mode & EXPR) != 0) {
  1142                 mode = EXPR;
  1143                 t = to(F.at(pos).Ident(names._super));
  1144                 t = superSuffix(typeArgs, t);
  1145                 typeArgs = null;
  1146             } else return illegal();
  1147             break;
  1148         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1149         case CHARLITERAL: case STRINGLITERAL:
  1150         case TRUE: case FALSE: case NULL:
  1151             if (typeArgs == null && (mode & EXPR) != 0) {
  1152                 mode = EXPR;
  1153                 t = literal(names.empty);
  1154             } else return illegal();
  1155             break;
  1156         case NEW:
  1157             if (typeArgs != null) return illegal();
  1158             if ((mode & EXPR) != 0) {
  1159                 mode = EXPR;
  1160                 nextToken();
  1161                 if (token.kind == LT) typeArgs = typeArguments(false);
  1162                 t = creator(pos, typeArgs);
  1163                 typeArgs = null;
  1164             } else return illegal();
  1165             break;
  1166         case MONKEYS_AT:
  1167             // Only annotated cast types and method references are valid
  1168             List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
  1169             if (typeAnnos.isEmpty()) {
  1170                 // else there would be no '@'
  1171                 throw new AssertionError("Expected type annotations, but found none!");
  1174             JCExpression expr = term3();
  1176             if ((mode & TYPE) == 0) {
  1177                 // Type annotations on class literals no longer legal
  1178                 switch (expr.getTag()) {
  1179                 case REFERENCE: {
  1180                     JCMemberReference mref = (JCMemberReference) expr;
  1181                     mref.expr = toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
  1182                     t = mref;
  1183                     break;
  1185                 case SELECT: {
  1186                     JCFieldAccess sel = (JCFieldAccess) expr;
  1188                     if (sel.name != names._class) {
  1189                         return illegal();
  1190                     } else {
  1191                         log.error(token.pos, "no.annotations.on.dot.class");
  1192                         return expr;
  1195                 default:
  1196                     return illegal(typeAnnos.head.pos);
  1199             } else {
  1200                 // Type annotations targeting a cast
  1201                 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
  1203             break;
  1204         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
  1205             if (typeArgs != null) return illegal();
  1206             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1207                 t = lambdaExpressionOrStatement(false, false, pos);
  1208             } else {
  1209                 t = toP(F.at(token.pos).Ident(ident()));
  1210                 loop: while (true) {
  1211                     pos = token.pos;
  1212                     final List<JCAnnotation> annos = typeAnnotationsOpt();
  1214                     // need to report an error later if LBRACKET is for array
  1215                     // index access rather than array creation level
  1216                     if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
  1217                         return illegal(annos.head.pos);
  1219                     switch (token.kind) {
  1220                     case LBRACKET:
  1221                         nextToken();
  1222                         if (token.kind == RBRACKET) {
  1223                             nextToken();
  1224                             t = bracketsOpt(t);
  1225                             t = toP(F.at(pos).TypeArray(t));
  1226                             if (annos.nonEmpty()) {
  1227                                 t = toP(F.at(pos).AnnotatedType(annos, t));
  1229                             // .class is only allowed if there were no annotations
  1230                             JCExpression nt = bracketsSuffix(t);
  1231                             if (nt != t && (annos.nonEmpty() || TreeInfo.containsTypeAnnotation(t))) {
  1232                                 // t and nt are different if bracketsSuffix parsed a .class.
  1233                                 // The check for nonEmpty covers the case when the whole array is annotated.
  1234                                 // Helper method isAnnotated looks for annos deeply within t.
  1235                                 syntaxError("no.annotations.on.dot.class");
  1237                             t = nt;
  1238                         } else {
  1239                             if ((mode & EXPR) != 0) {
  1240                                 mode = EXPR;
  1241                                 JCExpression t1 = term();
  1242                                 if (!annos.isEmpty()) t = illegal(annos.head.pos);
  1243                                 t = to(F.at(pos).Indexed(t, t1));
  1245                             accept(RBRACKET);
  1247                         break loop;
  1248                     case LPAREN:
  1249                         if ((mode & EXPR) != 0) {
  1250                             mode = EXPR;
  1251                             t = arguments(typeArgs, t);
  1252                             if (!annos.isEmpty()) t = illegal(annos.head.pos);
  1253                             typeArgs = null;
  1255                         break loop;
  1256                     case DOT:
  1257                         nextToken();
  1258                         int oldmode = mode;
  1259                         mode &= ~NOPARAMS;
  1260                         typeArgs = typeArgumentsOpt(EXPR);
  1261                         mode = oldmode;
  1262                         if ((mode & EXPR) != 0) {
  1263                             switch (token.kind) {
  1264                             case CLASS:
  1265                                 if (typeArgs != null) return illegal();
  1266                                 mode = EXPR;
  1267                                 t = to(F.at(pos).Select(t, names._class));
  1268                                 nextToken();
  1269                                 break loop;
  1270                             case THIS:
  1271                                 if (typeArgs != null) return illegal();
  1272                                 mode = EXPR;
  1273                                 t = to(F.at(pos).Select(t, names._this));
  1274                                 nextToken();
  1275                                 break loop;
  1276                             case SUPER:
  1277                                 mode = EXPR;
  1278                                 t = to(F.at(pos).Select(t, names._super));
  1279                                 t = superSuffix(typeArgs, t);
  1280                                 typeArgs = null;
  1281                                 break loop;
  1282                             case NEW:
  1283                                 if (typeArgs != null) return illegal();
  1284                                 mode = EXPR;
  1285                                 int pos1 = token.pos;
  1286                                 nextToken();
  1287                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1288                                 t = innerCreator(pos1, typeArgs, t);
  1289                                 typeArgs = null;
  1290                                 break loop;
  1294                         List<JCAnnotation> tyannos = null;
  1295                         if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
  1296                             tyannos = typeAnnotationsOpt();
  1298                         // typeArgs saved for next loop iteration.
  1299                         t = toP(F.at(pos).Select(t, ident()));
  1300                         if (tyannos != null && tyannos.nonEmpty()) {
  1301                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
  1303                         break;
  1304                     case ELLIPSIS:
  1305                         if (this.permitTypeAnnotationsPushBack) {
  1306                             this.typeAnnotationsPushedBack = annos;
  1307                         } else if (annos.nonEmpty()) {
  1308                             // Don't return here -- error recovery attempt
  1309                             illegal(annos.head.pos);
  1311                         break loop;
  1312                     case LT:
  1313                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1314                             //this is an unbound method reference whose qualifier
  1315                             //is a generic type i.e. A<S>::m
  1316                             int pos1 = token.pos;
  1317                             accept(LT);
  1318                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1319                             args.append(typeArgument());
  1320                             while (token.kind == COMMA) {
  1321                                 nextToken();
  1322                                 args.append(typeArgument());
  1324                             accept(GT);
  1325                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1326                             checkGenerics();
  1327                             while (token.kind == DOT) {
  1328                                 nextToken();
  1329                                 mode = TYPE;
  1330                                 t = toP(F.at(token.pos).Select(t, ident()));
  1331                                 t = typeArgumentsOpt(t);
  1333                             t = bracketsOpt(t);
  1334                             if (token.kind != COLCOL) {
  1335                                 //method reference expected here
  1336                                 t = illegal();
  1338                             mode = EXPR;
  1339                             return term3Rest(t, typeArgs);
  1341                         break loop;
  1342                     default:
  1343                         break loop;
  1347             if (typeArgs != null) illegal();
  1348             t = typeArgumentsOpt(t);
  1349             break;
  1350         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1351         case DOUBLE: case BOOLEAN:
  1352             if (typeArgs != null) illegal();
  1353             t = bracketsSuffix(bracketsOpt(basicType()));
  1354             break;
  1355         case VOID:
  1356             if (typeArgs != null) illegal();
  1357             if ((mode & EXPR) != 0) {
  1358                 nextToken();
  1359                 if (token.kind == DOT) {
  1360                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
  1361                     t = bracketsSuffix(ti);
  1362                 } else {
  1363                     return illegal(pos);
  1365             } else {
  1366                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1367                 // a void type (like other primitive types) to the next phase.
  1368                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1369                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
  1370                 nextToken();
  1371                 return ti;
  1372                 //return illegal();
  1374             break;
  1375         default:
  1376             return illegal();
  1378         return term3Rest(t, typeArgs);
  1381     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1382         if (typeArgs != null) illegal();
  1383         while (true) {
  1384             int pos1 = token.pos;
  1385             final List<JCAnnotation> annos = typeAnnotationsOpt();
  1387             if (token.kind == LBRACKET) {
  1388                 nextToken();
  1389                 if ((mode & TYPE) != 0) {
  1390                     int oldmode = mode;
  1391                     mode = TYPE;
  1392                     if (token.kind == RBRACKET) {
  1393                         nextToken();
  1394                         t = bracketsOpt(t);
  1395                         t = toP(F.at(pos1).TypeArray(t));
  1396                         if (token.kind == COLCOL) {
  1397                             mode = EXPR;
  1398                             continue;
  1400                         if (annos.nonEmpty()) {
  1401                             t = toP(F.at(pos1).AnnotatedType(annos, t));
  1403                         return t;
  1405                     mode = oldmode;
  1407                 if ((mode & EXPR) != 0) {
  1408                     mode = EXPR;
  1409                     JCExpression t1 = term();
  1410                     t = to(F.at(pos1).Indexed(t, t1));
  1412                 accept(RBRACKET);
  1413             } else if (token.kind == DOT) {
  1414                 nextToken();
  1415                 typeArgs = typeArgumentsOpt(EXPR);
  1416                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1417                     mode = EXPR;
  1418                     t = to(F.at(pos1).Select(t, names._super));
  1419                     nextToken();
  1420                     t = arguments(typeArgs, t);
  1421                     typeArgs = null;
  1422                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1423                     if (typeArgs != null) return illegal();
  1424                     mode = EXPR;
  1425                     int pos2 = token.pos;
  1426                     nextToken();
  1427                     if (token.kind == LT) typeArgs = typeArguments(false);
  1428                     t = innerCreator(pos2, typeArgs, t);
  1429                     typeArgs = null;
  1430                 } else {
  1431                     List<JCAnnotation> tyannos = null;
  1432                     if ((mode & TYPE) != 0 && token.kind == MONKEYS_AT) {
  1433                         // is the mode check needed?
  1434                         tyannos = typeAnnotationsOpt();
  1436                     t = toP(F.at(pos1).Select(t, ident()));
  1437                     if (tyannos != null && tyannos.nonEmpty()) {
  1438                         t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
  1440                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1441                     typeArgs = null;
  1443             } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
  1444                 mode = EXPR;
  1445                 if (typeArgs != null) return illegal();
  1446                 accept(COLCOL);
  1447                 t = memberReferenceSuffix(pos1, t);
  1448             } else {
  1449                 if (!annos.isEmpty()) {
  1450                     if (permitTypeAnnotationsPushBack)
  1451                         typeAnnotationsPushedBack = annos;
  1452                     else
  1453                         return illegal(annos.head.pos);
  1455                 break;
  1458         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1459             mode = EXPR;
  1460             t = to(F.at(token.pos).Unary(
  1461                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1462             nextToken();
  1464         return toP(t);
  1467     /**
  1468      * If we see an identifier followed by a '&lt;' it could be an unbound
  1469      * method reference or a binary expression. To disambiguate, look for a
  1470      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
  1471      */
  1472     @SuppressWarnings("fallthrough")
  1473     boolean isUnboundMemberRef() {
  1474         int pos = 0, depth = 0;
  1475         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1476             switch (t.kind) {
  1477                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
  1478                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1479                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1480                 case DOUBLE: case BOOLEAN: case CHAR:
  1481                 case MONKEYS_AT:
  1482                     break;
  1484                 case LPAREN:
  1485                     // skip annotation values
  1486                     int nesting = 0;
  1487                     for (; ; pos++) {
  1488                         TokenKind tk2 = S.token(pos).kind;
  1489                         switch (tk2) {
  1490                             case EOF:
  1491                                 return false;
  1492                             case LPAREN:
  1493                                 nesting++;
  1494                                 break;
  1495                             case RPAREN:
  1496                                 nesting--;
  1497                                 if (nesting == 0) {
  1498                                     continue outer;
  1500                                 break;
  1504                 case LT:
  1505                     depth++; break;
  1506                 case GTGTGT:
  1507                     depth--;
  1508                 case GTGT:
  1509                     depth--;
  1510                 case GT:
  1511                     depth--;
  1512                     if (depth == 0) {
  1513                         TokenKind nextKind = S.token(pos + 1).kind;
  1514                         return
  1515                             nextKind == TokenKind.DOT ||
  1516                             nextKind == TokenKind.LBRACKET ||
  1517                             nextKind == TokenKind.COLCOL;
  1519                     break;
  1520                 default:
  1521                     return false;
  1526     /**
  1527      * If we see an identifier followed by a '&lt;' it could be an unbound
  1528      * method reference or a binary expression. To disambiguate, look for a
  1529      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
  1530      */
  1531     @SuppressWarnings("fallthrough")
  1532     ParensResult analyzeParens() {
  1533         int depth = 0;
  1534         boolean type = false;
  1535         outer: for (int lookahead = 0 ; ; lookahead++) {
  1536             TokenKind tk = S.token(lookahead).kind;
  1537             switch (tk) {
  1538                 case EXTENDS: case SUPER: case COMMA:
  1539                     type = true;
  1540                 case QUES: case DOT: case AMP:
  1541                     //skip
  1542                     break;
  1543                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1544                 case DOUBLE: case BOOLEAN: case CHAR:
  1545                     if (peekToken(lookahead, RPAREN)) {
  1546                         //Type, ')' -> cast
  1547                         return ParensResult.CAST;
  1548                     } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1549                         //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1550                         return ParensResult.EXPLICIT_LAMBDA;
  1552                     break;
  1553                 case LPAREN:
  1554                     if (lookahead != 0) {
  1555                         // '(' in a non-starting position -> parens
  1556                         return ParensResult.PARENS;
  1557                     } else if (peekToken(lookahead, RPAREN)) {
  1558                         // '(', ')' -> explicit lambda
  1559                         return ParensResult.EXPLICIT_LAMBDA;
  1561                     break;
  1562                 case RPAREN:
  1563                     // if we have seen something that looks like a type,
  1564                     // then it's a cast expression
  1565                     if (type) return ParensResult.CAST;
  1566                     // otherwise, disambiguate cast vs. parenthesized expression
  1567                     // based on subsequent token.
  1568                     switch (S.token(lookahead + 1).kind) {
  1569                         /*case PLUSPLUS: case SUBSUB: */
  1570                         case BANG: case TILDE:
  1571                         case LPAREN: case THIS: case SUPER:
  1572                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1573                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1574                         case TRUE: case FALSE: case NULL:
  1575                         case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
  1576                         case BYTE: case SHORT: case CHAR: case INT:
  1577                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1578                             return ParensResult.CAST;
  1579                         default:
  1580                             return ParensResult.PARENS;
  1582                 case UNDERSCORE:
  1583                 case ASSERT:
  1584                 case ENUM:
  1585                 case IDENTIFIER:
  1586                     if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1587                         // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1588                         return ParensResult.EXPLICIT_LAMBDA;
  1589                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
  1590                         // Identifier, ')' '->' -> implicit lambda
  1591                         return ParensResult.IMPLICIT_LAMBDA;
  1593                     break;
  1594                 case FINAL:
  1595                 case ELLIPSIS:
  1596                     //those can only appear in explicit lambdas
  1597                     return ParensResult.EXPLICIT_LAMBDA;
  1598                 case MONKEYS_AT:
  1599                     type = true;
  1600                     lookahead += 1; //skip '@'
  1601                     while (peekToken(lookahead, DOT)) {
  1602                         lookahead += 2;
  1604                     if (peekToken(lookahead, LPAREN)) {
  1605                         lookahead++;
  1606                         //skip annotation values
  1607                         int nesting = 0;
  1608                         for (; ; lookahead++) {
  1609                             TokenKind tk2 = S.token(lookahead).kind;
  1610                             switch (tk2) {
  1611                                 case EOF:
  1612                                     return ParensResult.PARENS;
  1613                                 case LPAREN:
  1614                                     nesting++;
  1615                                     break;
  1616                                 case RPAREN:
  1617                                     nesting--;
  1618                                     if (nesting == 0) {
  1619                                         continue outer;
  1621                                 break;
  1625                     break;
  1626                 case LBRACKET:
  1627                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
  1628                         // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
  1629                         return ParensResult.EXPLICIT_LAMBDA;
  1630                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
  1631                             peekToken(lookahead, RBRACKET, AMP)) {
  1632                         // '[', ']', ')' -> cast
  1633                         // '[', ']', '&' -> cast (intersection type)
  1634                         return ParensResult.CAST;
  1635                     } else if (peekToken(lookahead, RBRACKET)) {
  1636                         //consume the ']' and skip
  1637                         type = true;
  1638                         lookahead++;
  1639                         break;
  1640                     } else {
  1641                         return ParensResult.PARENS;
  1643                 case LT:
  1644                     depth++; break;
  1645                 case GTGTGT:
  1646                     depth--;
  1647                 case GTGT:
  1648                     depth--;
  1649                 case GT:
  1650                     depth--;
  1651                     if (depth == 0) {
  1652                         if (peekToken(lookahead, RPAREN) ||
  1653                                 peekToken(lookahead, AMP)) {
  1654                             // '>', ')' -> cast
  1655                             // '>', '&' -> cast
  1656                             return ParensResult.CAST;
  1657                         } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
  1658                                 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
  1659                                 peekToken(lookahead, ELLIPSIS)) {
  1660                             // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
  1661                             // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
  1662                             // '>', '...' -> explicit lambda
  1663                             return ParensResult.EXPLICIT_LAMBDA;
  1665                         //it looks a type, but could still be (i) a cast to generic type,
  1666                         //(ii) an unbound method reference or (iii) an explicit lambda
  1667                         type = true;
  1668                         break;
  1669                     } else if (depth < 0) {
  1670                         //unbalanced '<', '>' - not a generic type
  1671                         return ParensResult.PARENS;
  1673                     break;
  1674                 default:
  1675                     //this includes EOF
  1676                     return ParensResult.PARENS;
  1681     /** Accepts all identifier-like tokens */
  1682     Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
  1683         public boolean accepts(TokenKind t) {
  1684             return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
  1686     };
  1688     enum ParensResult {
  1689         CAST,
  1690         EXPLICIT_LAMBDA,
  1691         IMPLICIT_LAMBDA,
  1692         PARENS;
  1695     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1696         List<JCVariableDecl> params = explicitParams ?
  1697                 formalParameters(true) :
  1698                 implicitParameters(hasParens);
  1700         return lambdaExpressionOrStatementRest(params, pos);
  1703     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1704         checkLambda();
  1705         accept(ARROW);
  1707         return token.kind == LBRACE ?
  1708             lambdaStatement(args, pos, pos) :
  1709             lambdaExpression(args, pos);
  1712     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1713         JCBlock block = block(pos2, 0);
  1714         return toP(F.at(pos).Lambda(args, block));
  1717     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1718         JCTree expr = parseExpression();
  1719         return toP(F.at(pos).Lambda(args, expr));
  1722     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1723      */
  1724     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1725         nextToken();
  1726         if (token.kind == LPAREN || typeArgs != null) {
  1727             t = arguments(typeArgs, t);
  1728         } else if (token.kind == COLCOL) {
  1729             if (typeArgs != null) return illegal();
  1730             t = memberReferenceSuffix(t);
  1731         } else {
  1732             int pos = token.pos;
  1733             accept(DOT);
  1734             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1735             t = toP(F.at(pos).Select(t, ident()));
  1736             t = argumentsOpt(typeArgs, t);
  1738         return t;
  1741     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1742      */
  1743     JCPrimitiveTypeTree basicType() {
  1744         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1745         nextToken();
  1746         return t;
  1749     /** ArgumentsOpt = [ Arguments ]
  1750      */
  1751     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1752         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1753             mode = EXPR;
  1754             return arguments(typeArgs, t);
  1755         } else {
  1756             return t;
  1760     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1761      */
  1762     List<JCExpression> arguments() {
  1763         ListBuffer<JCExpression> args = lb();
  1764         if (token.kind == LPAREN) {
  1765             nextToken();
  1766             if (token.kind != RPAREN) {
  1767                 args.append(parseExpression());
  1768                 while (token.kind == COMMA) {
  1769                     nextToken();
  1770                     args.append(parseExpression());
  1773             accept(RPAREN);
  1774         } else {
  1775             syntaxError(token.pos, "expected", LPAREN);
  1777         return args.toList();
  1780     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1781         int pos = token.pos;
  1782         List<JCExpression> args = arguments();
  1783         return toP(F.at(pos).Apply(typeArgs, t, args));
  1786     /**  TypeArgumentsOpt = [ TypeArguments ]
  1787      */
  1788     JCExpression typeArgumentsOpt(JCExpression t) {
  1789         if (token.kind == LT &&
  1790             (mode & TYPE) != 0 &&
  1791             (mode & NOPARAMS) == 0) {
  1792             mode = TYPE;
  1793             checkGenerics();
  1794             return typeArguments(t, false);
  1795         } else {
  1796             return t;
  1799     List<JCExpression> typeArgumentsOpt() {
  1800         return typeArgumentsOpt(TYPE);
  1803     List<JCExpression> typeArgumentsOpt(int useMode) {
  1804         if (token.kind == LT) {
  1805             checkGenerics();
  1806             if ((mode & useMode) == 0 ||
  1807                 (mode & NOPARAMS) != 0) {
  1808                 illegal();
  1810             mode = useMode;
  1811             return typeArguments(false);
  1813         return null;
  1816     /**
  1817      *  {@literal
  1818      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1819      *  }
  1820      */
  1821     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1822         if (token.kind == LT) {
  1823             nextToken();
  1824             if (token.kind == GT && diamondAllowed) {
  1825                 checkDiamond();
  1826                 mode |= DIAMOND;
  1827                 nextToken();
  1828                 return List.nil();
  1829             } else {
  1830                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1831                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1832                 while (token.kind == COMMA) {
  1833                     nextToken();
  1834                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1836                 switch (token.kind) {
  1838                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1839                 case GTGTGT: case GTGT:
  1840                     token = S.split();
  1841                     break;
  1842                 case GT:
  1843                     nextToken();
  1844                     break;
  1845                 default:
  1846                     args.append(syntaxError(token.pos, "expected", GT));
  1847                     break;
  1849                 return args.toList();
  1851         } else {
  1852             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1856     /**
  1857      *  {@literal
  1858      *  TypeArgument = Type
  1859      *               | [Annotations] "?"
  1860      *               | [Annotations] "?" EXTENDS Type {"&" Type}
  1861      *               | [Annotations] "?" SUPER Type
  1862      *  }
  1863      */
  1864     JCExpression typeArgument() {
  1865         List<JCAnnotation> annotations = typeAnnotationsOpt();
  1866         if (token.kind != QUES) return parseType(annotations);
  1867         int pos = token.pos;
  1868         nextToken();
  1869         JCExpression result;
  1870         if (token.kind == EXTENDS) {
  1871             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1872             nextToken();
  1873             JCExpression bound = parseType();
  1874             result = F.at(pos).Wildcard(t, bound);
  1875         } else if (token.kind == SUPER) {
  1876             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1877             nextToken();
  1878             JCExpression bound = parseType();
  1879             result = F.at(pos).Wildcard(t, bound);
  1880         } else if (LAX_IDENTIFIER.accepts(token.kind)) {
  1881             //error recovery
  1882             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1883             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1884             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1885             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1886             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1887             result = err;
  1888         } else {
  1889             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1890             result = toP(F.at(pos).Wildcard(t, null));
  1892         if (!annotations.isEmpty()) {
  1893             result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
  1895         return result;
  1898     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1899         int pos = token.pos;
  1900         List<JCExpression> args = typeArguments(diamondAllowed);
  1901         return toP(F.at(pos).TypeApply(t, args));
  1904     /**
  1905      * BracketsOpt = { [Annotations] "[" "]" }*
  1907      * <p>
  1909      * <code>annotations</code> is the list of annotations targeting
  1910      * the expression <code>t</code>.
  1911      */
  1912     private JCExpression bracketsOpt(JCExpression t,
  1913             List<JCAnnotation> annotations) {
  1914         List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
  1916         if (token.kind == LBRACKET) {
  1917             int pos = token.pos;
  1918             nextToken();
  1919             t = bracketsOptCont(t, pos, nextLevelAnnotations);
  1920         } else if (!nextLevelAnnotations.isEmpty()) {
  1921             if (permitTypeAnnotationsPushBack) {
  1922                 this.typeAnnotationsPushedBack = nextLevelAnnotations;
  1923             } else {
  1924                 return illegal(nextLevelAnnotations.head.pos);
  1928         if (!annotations.isEmpty()) {
  1929             t = toP(F.at(token.pos).AnnotatedType(annotations, t));
  1931         return t;
  1934     /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ]
  1935      */
  1936     private JCExpression bracketsOpt(JCExpression t) {
  1937         return bracketsOpt(t, List.<JCAnnotation>nil());
  1940     private JCExpression bracketsOptCont(JCExpression t, int pos,
  1941             List<JCAnnotation> annotations) {
  1942         accept(RBRACKET);
  1943         t = bracketsOpt(t);
  1944         t = toP(F.at(pos).TypeArray(t));
  1945         if (annotations.nonEmpty()) {
  1946             t = toP(F.at(pos).AnnotatedType(annotations, t));
  1948         return t;
  1951     /** BracketsSuffixExpr = "." CLASS
  1952      *  BracketsSuffixType =
  1953      */
  1954     JCExpression bracketsSuffix(JCExpression t) {
  1955         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1956             mode = EXPR;
  1957             int pos = token.pos;
  1958             nextToken();
  1959             accept(CLASS);
  1960             if (token.pos == endPosTable.errorEndPos) {
  1961                 // error recovery
  1962                 Name name;
  1963                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  1964                     name = token.name();
  1965                     nextToken();
  1966                 } else {
  1967                     name = names.error;
  1969                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1970             } else {
  1971                 t = toP(F.at(pos).Select(t, names._class));
  1973         } else if ((mode & TYPE) != 0) {
  1974             if (token.kind != COLCOL) {
  1975                 mode = TYPE;
  1977         } else if (token.kind != COLCOL) {
  1978             syntaxError(token.pos, "dot.class.expected");
  1980         return t;
  1983     /**
  1984      * MemberReferenceSuffix = "::" [TypeArguments] Ident
  1985      *                       | "::" [TypeArguments] "new"
  1986      */
  1987     JCExpression memberReferenceSuffix(JCExpression t) {
  1988         int pos1 = token.pos;
  1989         accept(COLCOL);
  1990         return memberReferenceSuffix(pos1, t);
  1993     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1994         checkMethodReferences();
  1995         mode = EXPR;
  1996         List<JCExpression> typeArgs = null;
  1997         if (token.kind == LT) {
  1998             typeArgs = typeArguments(false);
  2000         Name refName;
  2001         ReferenceMode refMode;
  2002         if (token.kind == NEW) {
  2003             refMode = ReferenceMode.NEW;
  2004             refName = names.init;
  2005             nextToken();
  2006         } else {
  2007             refMode = ReferenceMode.INVOKE;
  2008             refName = ident();
  2010         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  2013     /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  2014      */
  2015     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  2016         List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
  2018         switch (token.kind) {
  2019         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  2020         case DOUBLE: case BOOLEAN:
  2021             if (typeArgs == null) {
  2022                 if (newAnnotations.isEmpty()) {
  2023                     return arrayCreatorRest(newpos, basicType());
  2024                 } else {
  2025                     return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
  2028             break;
  2029         default:
  2031         JCExpression t = qualident(true);
  2033         // handle type annotations for non primitive arrays
  2034         if (newAnnotations.nonEmpty()) {
  2035             t = insertAnnotationsToMostInner(t, newAnnotations, false);
  2038         int oldmode = mode;
  2039         mode = TYPE;
  2040         boolean diamondFound = false;
  2041         int lastTypeargsPos = -1;
  2042         if (token.kind == LT) {
  2043             checkGenerics();
  2044             lastTypeargsPos = token.pos;
  2045             t = typeArguments(t, true);
  2046             diamondFound = (mode & DIAMOND) != 0;
  2048         while (token.kind == DOT) {
  2049             if (diamondFound) {
  2050                 //cannot select after a diamond
  2051                 illegal();
  2053             int pos = token.pos;
  2054             nextToken();
  2055             List<JCAnnotation> tyannos = typeAnnotationsOpt();
  2056             t = toP(F.at(pos).Select(t, ident()));
  2058             if (tyannos != null && tyannos.nonEmpty()) {
  2059                 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
  2062             if (token.kind == LT) {
  2063                 lastTypeargsPos = token.pos;
  2064                 checkGenerics();
  2065                 t = typeArguments(t, true);
  2066                 diamondFound = (mode & DIAMOND) != 0;
  2069         mode = oldmode;
  2070         if (token.kind == LBRACKET || token.kind == MONKEYS_AT) {
  2071             JCExpression e = arrayCreatorRest(newpos, t);
  2072             if (diamondFound) {
  2073                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  2074                 return toP(F.at(newpos).Erroneous(List.of(e)));
  2076             else if (typeArgs != null) {
  2077                 int pos = newpos;
  2078                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  2079                     // note: this should always happen but we should
  2080                     // not rely on this as the parser is continuously
  2081                     // modified to improve error recovery.
  2082                     pos = typeArgs.head.pos;
  2084                 setErrorEndPos(S.prevToken().endPos);
  2085                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  2086                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  2087                 return toP(err);
  2089             return e;
  2090         } else if (token.kind == LPAREN) {
  2091             JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t);
  2092             if (newClass.def != null) {
  2093                 assert newClass.def.mods.annotations.isEmpty();
  2094                 if (newAnnotations.nonEmpty()) {
  2095                     newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos);
  2096                     newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations);
  2099             return newClass;
  2100         } else {
  2101             setErrorEndPos(token.pos);
  2102             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  2103             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  2104             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  2108     /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
  2109      */
  2110     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  2111         List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
  2113         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  2115         if (newAnnotations.nonEmpty()) {
  2116             t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
  2119         if (token.kind == LT) {
  2120             int oldmode = mode;
  2121             checkGenerics();
  2122             t = typeArguments(t, true);
  2123             mode = oldmode;
  2125         return classCreatorRest(newpos, encl, typeArgs, t);
  2128     /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
  2129      *                         | Expression "]" {[Annotations]  "[" Expression "]"} BracketsOpt )
  2130      */
  2131     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  2132         List<JCAnnotation> annos = typeAnnotationsOpt();
  2134         accept(LBRACKET);
  2135         if (token.kind == RBRACKET) {
  2136             accept(RBRACKET);
  2137             elemtype = bracketsOpt(elemtype, annos);
  2138             if (token.kind == LBRACE) {
  2139                 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
  2140                 if (annos.nonEmpty()) {
  2141                     // when an array initializer is present then
  2142                     // the parsed annotations should target the
  2143                     // new array tree
  2144                     // bracketsOpt inserts the annotation in
  2145                     // elemtype, and it needs to be corrected
  2146                     //
  2147                     JCAnnotatedType annotated = (JCAnnotatedType)elemtype;
  2148                     assert annotated.annotations == annos;
  2149                     na.annotations = annotated.annotations;
  2150                     na.elemtype = annotated.underlyingType;
  2152                 return na;
  2153             } else {
  2154                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  2155                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  2157         } else {
  2158             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  2160             // maintain array dimension type annotations
  2161             ListBuffer<List<JCAnnotation>> dimAnnotations = ListBuffer.lb();
  2162             dimAnnotations.append(annos);
  2164             dims.append(parseExpression());
  2165             accept(RBRACKET);
  2166             while (token.kind == LBRACKET
  2167                     || token.kind == MONKEYS_AT) {
  2168                 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt();
  2169                 int pos = token.pos;
  2170                 nextToken();
  2171                 if (token.kind == RBRACKET) {
  2172                     elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  2173                 } else {
  2174                     if (token.kind == RBRACKET) { // no dimension
  2175                         elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
  2176                     } else {
  2177                         dimAnnotations.append(maybeDimAnnos);
  2178                         dims.append(parseExpression());
  2179                         accept(RBRACKET);
  2184             JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  2185             na.dimAnnotations = dimAnnotations.toList();
  2186             return na;
  2190     /** ClassCreatorRest = Arguments [ClassBody]
  2191      */
  2192     JCNewClass classCreatorRest(int newpos,
  2193                                   JCExpression encl,
  2194                                   List<JCExpression> typeArgs,
  2195                                   JCExpression t)
  2197         List<JCExpression> args = arguments();
  2198         JCClassDecl body = null;
  2199         if (token.kind == LBRACE) {
  2200             int pos = token.pos;
  2201             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2202             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2203             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  2205         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  2208     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  2209      */
  2210     JCExpression arrayInitializer(int newpos, JCExpression t) {
  2211         accept(LBRACE);
  2212         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  2213         if (token.kind == COMMA) {
  2214             nextToken();
  2215         } else if (token.kind != RBRACE) {
  2216             elems.append(variableInitializer());
  2217             while (token.kind == COMMA) {
  2218                 nextToken();
  2219                 if (token.kind == RBRACE) break;
  2220                 elems.append(variableInitializer());
  2223         accept(RBRACE);
  2224         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  2227     /** VariableInitializer = ArrayInitializer | Expression
  2228      */
  2229     public JCExpression variableInitializer() {
  2230         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  2233     /** ParExpression = "(" Expression ")"
  2234      */
  2235     JCExpression parExpression() {
  2236         int pos = token.pos;
  2237         accept(LPAREN);
  2238         JCExpression t = parseExpression();
  2239         accept(RPAREN);
  2240         return toP(F.at(pos).Parens(t));
  2243     /** Block = "{" BlockStatements "}"
  2244      */
  2245     JCBlock block(int pos, long flags) {
  2246         accept(LBRACE);
  2247         List<JCStatement> stats = blockStatements();
  2248         JCBlock t = F.at(pos).Block(flags, stats);
  2249         while (token.kind == CASE || token.kind == DEFAULT) {
  2250             syntaxError("orphaned", token.kind);
  2251             switchBlockStatementGroups();
  2253         // the Block node has a field "endpos" for first char of last token, which is
  2254         // usually but not necessarily the last char of the last token.
  2255         t.endpos = token.pos;
  2256         accept(RBRACE);
  2257         return toP(t);
  2260     public JCBlock block() {
  2261         return block(token.pos, 0);
  2264     /** BlockStatements = { BlockStatement }
  2265      *  BlockStatement  = LocalVariableDeclarationStatement
  2266      *                  | ClassOrInterfaceOrEnumDeclaration
  2267      *                  | [Ident ":"] Statement
  2268      *  LocalVariableDeclarationStatement
  2269      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  2270      */
  2271     @SuppressWarnings("fallthrough")
  2272     List<JCStatement> blockStatements() {
  2273         //todo: skip to anchor on error(?)
  2274         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  2275         while (true) {
  2276             List<JCStatement> stat = blockStatement();
  2277             if (stat.isEmpty()) {
  2278                 return stats.toList();
  2279             } else {
  2280                 if (token.pos <= endPosTable.errorEndPos) {
  2281                     skip(false, true, true, true);
  2283                 stats.addAll(stat);
  2288     /*
  2289      * This method parses a statement treating it as a block, relaxing the
  2290      * JLS restrictions, allows us to parse more faulty code, doing so
  2291      * enables us to provide better and accurate diagnostics to the user.
  2292      */
  2293     JCStatement parseStatementAsBlock() {
  2294         int pos = token.pos;
  2295         List<JCStatement> stats = blockStatement();
  2296         if (stats.isEmpty()) {
  2297             JCErroneous e = F.at(pos).Erroneous();
  2298             error(e, "illegal.start.of.stmt");
  2299             return F.at(pos).Exec(e);
  2300         } else {
  2301             JCStatement first = stats.head;
  2302             String error = null;
  2303             switch (first.getTag()) {
  2304             case CLASSDEF:
  2305                 error = "class.not.allowed";
  2306                 break;
  2307             case VARDEF:
  2308                 error = "variable.not.allowed";
  2309                 break;
  2311             if (error != null) {
  2312                 error(first, error);
  2313                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  2314                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  2316             return first;
  2320     @SuppressWarnings("fallthrough")
  2321     List<JCStatement> blockStatement() {
  2322         //todo: skip to anchor on error(?)
  2323         int pos = token.pos;
  2324         switch (token.kind) {
  2325         case RBRACE: case CASE: case DEFAULT: case EOF:
  2326             return List.nil();
  2327         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  2328         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  2329         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  2330             return List.of(parseStatement());
  2331         case MONKEYS_AT:
  2332         case FINAL: {
  2333             Comment dc = token.comment(CommentStyle.JAVADOC);
  2334             JCModifiers mods = modifiersOpt();
  2335             if (token.kind == INTERFACE ||
  2336                 token.kind == CLASS ||
  2337                 allowEnums && token.kind == ENUM) {
  2338                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2339             } else {
  2340                 JCExpression t = parseType();
  2341                 ListBuffer<JCStatement> stats =
  2342                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2343                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2344                 storeEnd(stats.last(), token.endPos);
  2345                 accept(SEMI);
  2346                 return stats.toList();
  2349         case ABSTRACT: case STRICTFP: {
  2350             Comment dc = token.comment(CommentStyle.JAVADOC);
  2351             JCModifiers mods = modifiersOpt();
  2352             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2354         case INTERFACE:
  2355         case CLASS:
  2356             Comment dc = token.comment(CommentStyle.JAVADOC);
  2357             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2358         case ENUM:
  2359         case ASSERT:
  2360             if (allowEnums && token.kind == ENUM) {
  2361                 error(token.pos, "local.enum");
  2362                 dc = token.comment(CommentStyle.JAVADOC);
  2363                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2364             } else if (allowAsserts && token.kind == ASSERT) {
  2365                 return List.of(parseStatement());
  2367             /* fall through to default */
  2368         default:
  2369             Token prevToken = token;
  2370             JCExpression t = term(EXPR | TYPE);
  2371             if (token.kind == COLON && t.hasTag(IDENT)) {
  2372                 nextToken();
  2373                 JCStatement stat = parseStatement();
  2374                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  2375             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2376                 pos = token.pos;
  2377                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2378                 F.at(pos);
  2379                 ListBuffer<JCStatement> stats =
  2380                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2381                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2382                 storeEnd(stats.last(), token.endPos);
  2383                 accept(SEMI);
  2384                 return stats.toList();
  2385             } else {
  2386                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2387                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  2388                 accept(SEMI);
  2389                 return List.<JCStatement>of(expr);
  2394     /** Statement =
  2395      *       Block
  2396      *     | IF ParExpression Statement [ELSE Statement]
  2397      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  2398      *     | FOR "(" FormalParameter : Expression ")" Statement
  2399      *     | WHILE ParExpression Statement
  2400      *     | DO Statement WHILE ParExpression ";"
  2401      *     | TRY Block ( Catches | [Catches] FinallyPart )
  2402      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  2403      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  2404      *     | SYNCHRONIZED ParExpression Block
  2405      *     | RETURN [Expression] ";"
  2406      *     | THROW Expression ";"
  2407      *     | BREAK [Ident] ";"
  2408      *     | CONTINUE [Ident] ";"
  2409      *     | ASSERT Expression [ ":" Expression ] ";"
  2410      *     | ";"
  2411      *     | ExpressionStatement
  2412      *     | Ident ":" Statement
  2413      */
  2414     @SuppressWarnings("fallthrough")
  2415     public JCStatement parseStatement() {
  2416         int pos = token.pos;
  2417         switch (token.kind) {
  2418         case LBRACE:
  2419             return block();
  2420         case IF: {
  2421             nextToken();
  2422             JCExpression cond = parExpression();
  2423             JCStatement thenpart = parseStatementAsBlock();
  2424             JCStatement elsepart = null;
  2425             if (token.kind == ELSE) {
  2426                 nextToken();
  2427                 elsepart = parseStatementAsBlock();
  2429             return F.at(pos).If(cond, thenpart, elsepart);
  2431         case FOR: {
  2432             nextToken();
  2433             accept(LPAREN);
  2434             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  2435             if (inits.length() == 1 &&
  2436                 inits.head.hasTag(VARDEF) &&
  2437                 ((JCVariableDecl) inits.head).init == null &&
  2438                 token.kind == COLON) {
  2439                 checkForeach();
  2440                 JCVariableDecl var = (JCVariableDecl)inits.head;
  2441                 accept(COLON);
  2442                 JCExpression expr = parseExpression();
  2443                 accept(RPAREN);
  2444                 JCStatement body = parseStatementAsBlock();
  2445                 return F.at(pos).ForeachLoop(var, expr, body);
  2446             } else {
  2447                 accept(SEMI);
  2448                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  2449                 accept(SEMI);
  2450                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2451                 accept(RPAREN);
  2452                 JCStatement body = parseStatementAsBlock();
  2453                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2456         case WHILE: {
  2457             nextToken();
  2458             JCExpression cond = parExpression();
  2459             JCStatement body = parseStatementAsBlock();
  2460             return F.at(pos).WhileLoop(cond, body);
  2462         case DO: {
  2463             nextToken();
  2464             JCStatement body = parseStatementAsBlock();
  2465             accept(WHILE);
  2466             JCExpression cond = parExpression();
  2467             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2468             accept(SEMI);
  2469             return t;
  2471         case TRY: {
  2472             nextToken();
  2473             List<JCTree> resources = List.<JCTree>nil();
  2474             if (token.kind == LPAREN) {
  2475                 checkTryWithResources();
  2476                 nextToken();
  2477                 resources = resources();
  2478                 accept(RPAREN);
  2480             JCBlock body = block();
  2481             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2482             JCBlock finalizer = null;
  2483             if (token.kind == CATCH || token.kind == FINALLY) {
  2484                 while (token.kind == CATCH) catchers.append(catchClause());
  2485                 if (token.kind == FINALLY) {
  2486                     nextToken();
  2487                     finalizer = block();
  2489             } else {
  2490                 if (allowTWR) {
  2491                     if (resources.isEmpty())
  2492                         error(pos, "try.without.catch.finally.or.resource.decls");
  2493                 } else
  2494                     error(pos, "try.without.catch.or.finally");
  2496             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2498         case SWITCH: {
  2499             nextToken();
  2500             JCExpression selector = parExpression();
  2501             accept(LBRACE);
  2502             List<JCCase> cases = switchBlockStatementGroups();
  2503             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2504             accept(RBRACE);
  2505             return t;
  2507         case SYNCHRONIZED: {
  2508             nextToken();
  2509             JCExpression lock = parExpression();
  2510             JCBlock body = block();
  2511             return F.at(pos).Synchronized(lock, body);
  2513         case RETURN: {
  2514             nextToken();
  2515             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2516             JCReturn t = to(F.at(pos).Return(result));
  2517             accept(SEMI);
  2518             return t;
  2520         case THROW: {
  2521             nextToken();
  2522             JCExpression exc = parseExpression();
  2523             JCThrow t = to(F.at(pos).Throw(exc));
  2524             accept(SEMI);
  2525             return t;
  2527         case BREAK: {
  2528             nextToken();
  2529             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2530             JCBreak t = to(F.at(pos).Break(label));
  2531             accept(SEMI);
  2532             return t;
  2534         case CONTINUE: {
  2535             nextToken();
  2536             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2537             JCContinue t =  to(F.at(pos).Continue(label));
  2538             accept(SEMI);
  2539             return t;
  2541         case SEMI:
  2542             nextToken();
  2543             return toP(F.at(pos).Skip());
  2544         case ELSE:
  2545             int elsePos = token.pos;
  2546             nextToken();
  2547             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
  2548         case FINALLY:
  2549             int finallyPos = token.pos;
  2550             nextToken();
  2551             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
  2552         case CATCH:
  2553             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
  2554         case ASSERT: {
  2555             if (allowAsserts && token.kind == ASSERT) {
  2556                 nextToken();
  2557                 JCExpression assertion = parseExpression();
  2558                 JCExpression message = null;
  2559                 if (token.kind == COLON) {
  2560                     nextToken();
  2561                     message = parseExpression();
  2563                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2564                 accept(SEMI);
  2565                 return t;
  2567             /* else fall through to default case */
  2569         case ENUM:
  2570         default:
  2571             Token prevToken = token;
  2572             JCExpression expr = parseExpression();
  2573             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2574                 nextToken();
  2575                 JCStatement stat = parseStatement();
  2576                 return F.at(pos).Labelled(prevToken.name(), stat);
  2577             } else {
  2578                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2579                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2580                 accept(SEMI);
  2581                 return stat;
  2586     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
  2587         int errPos = S.errPos();
  2588         JCTree stm = action.doRecover(this);
  2589         S.errPos(errPos);
  2590         return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
  2593     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2594      * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below.
  2595      */
  2596     protected JCCatch catchClause() {
  2597         int pos = token.pos;
  2598         accept(CATCH);
  2599         accept(LPAREN);
  2600         JCModifiers mods = optFinal(Flags.PARAMETER);
  2601         List<JCExpression> catchTypes = catchTypes();
  2602         JCExpression paramType = catchTypes.size() > 1 ?
  2603                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2604                 catchTypes.head;
  2605         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2606         accept(RPAREN);
  2607         JCBlock body = block();
  2608         return F.at(pos).Catch(formal, body);
  2611     List<JCExpression> catchTypes() {
  2612         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2613         catchTypes.add(parseType());
  2614         while (token.kind == BAR) {
  2615             checkMulticatch();
  2616             nextToken();
  2617             // Instead of qualident this is now parseType.
  2618             // But would that allow too much, e.g. arrays or generics?
  2619             catchTypes.add(parseType());
  2621         return catchTypes.toList();
  2624     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2625      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2626      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2627      */
  2628     List<JCCase> switchBlockStatementGroups() {
  2629         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2630         while (true) {
  2631             int pos = token.pos;
  2632             switch (token.kind) {
  2633             case CASE:
  2634             case DEFAULT:
  2635                 cases.append(switchBlockStatementGroup());
  2636                 break;
  2637             case RBRACE: case EOF:
  2638                 return cases.toList();
  2639             default:
  2640                 nextToken(); // to ensure progress
  2641                 syntaxError(pos, "expected3",
  2642                     CASE, DEFAULT, RBRACE);
  2647     protected JCCase switchBlockStatementGroup() {
  2648         int pos = token.pos;
  2649         List<JCStatement> stats;
  2650         JCCase c;
  2651         switch (token.kind) {
  2652         case CASE:
  2653             nextToken();
  2654             JCExpression pat = parseExpression();
  2655             accept(COLON);
  2656             stats = blockStatements();
  2657             c = F.at(pos).Case(pat, stats);
  2658             if (stats.isEmpty())
  2659                 storeEnd(c, S.prevToken().endPos);
  2660             return c;
  2661         case DEFAULT:
  2662             nextToken();
  2663             accept(COLON);
  2664             stats = blockStatements();
  2665             c = F.at(pos).Case(null, stats);
  2666             if (stats.isEmpty())
  2667                 storeEnd(c, S.prevToken().endPos);
  2668             return c;
  2670         throw new AssertionError("should not reach here");
  2673     /** MoreStatementExpressions = { COMMA StatementExpression }
  2674      */
  2675     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2676                                                                     JCExpression first,
  2677                                                                     T stats) {
  2678         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2679         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2680         while (token.kind == COMMA) {
  2681             nextToken();
  2682             pos = token.pos;
  2683             JCExpression t = parseExpression();
  2684             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2685             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2687         return stats;
  2690     /** ForInit = StatementExpression MoreStatementExpressions
  2691      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2692      */
  2693     List<JCStatement> forInit() {
  2694         ListBuffer<JCStatement> stats = lb();
  2695         int pos = token.pos;
  2696         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2697             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2698         } else {
  2699             JCExpression t = term(EXPR | TYPE);
  2700             if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2701                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2702             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2703                 error(pos, "bad.initializer", "for-loop");
  2704                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2705             } else {
  2706                 return moreStatementExpressions(pos, t, stats).toList();
  2711     /** ForUpdate = StatementExpression MoreStatementExpressions
  2712      */
  2713     List<JCExpressionStatement> forUpdate() {
  2714         return moreStatementExpressions(token.pos,
  2715                                         parseExpression(),
  2716                                         new ListBuffer<JCExpressionStatement>()).toList();
  2719     /** AnnotationsOpt = { '@' Annotation }
  2721      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
  2722      */
  2723     List<JCAnnotation> annotationsOpt(Tag kind) {
  2724         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2725         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2726         int prevmode = mode;
  2727         while (token.kind == MONKEYS_AT) {
  2728             int pos = token.pos;
  2729             nextToken();
  2730             buf.append(annotation(pos, kind));
  2732         lastmode = mode;
  2733         mode = prevmode;
  2734         List<JCAnnotation> annotations = buf.toList();
  2736         return annotations;
  2739     List<JCAnnotation> typeAnnotationsOpt() {
  2740         List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
  2741         return annotations;
  2744     /** ModifiersOpt = { Modifier }
  2745      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2746      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2747      *           | "@" Annotation
  2748      */
  2749     JCModifiers modifiersOpt() {
  2750         return modifiersOpt(null);
  2752     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2753         long flags;
  2754         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2755         int pos;
  2756         if (partial == null) {
  2757             flags = 0;
  2758             pos = token.pos;
  2759         } else {
  2760             flags = partial.flags;
  2761             annotations.appendList(partial.annotations);
  2762             pos = partial.pos;
  2764         if (token.deprecatedFlag()) {
  2765             flags |= Flags.DEPRECATED;
  2767         int lastPos;
  2768     loop:
  2769         while (true) {
  2770             long flag;
  2771             switch (token.kind) {
  2772             case PRIVATE     : flag = Flags.PRIVATE; break;
  2773             case PROTECTED   : flag = Flags.PROTECTED; break;
  2774             case PUBLIC      : flag = Flags.PUBLIC; break;
  2775             case STATIC      : flag = Flags.STATIC; break;
  2776             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2777             case FINAL       : flag = Flags.FINAL; break;
  2778             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2779             case NATIVE      : flag = Flags.NATIVE; break;
  2780             case VOLATILE    : flag = Flags.VOLATILE; break;
  2781             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2782             case STRICTFP    : flag = Flags.STRICTFP; break;
  2783             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2784             case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
  2785             case ERROR       : flag = 0; nextToken(); break;
  2786             default: break loop;
  2788             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2789             lastPos = token.pos;
  2790             nextToken();
  2791             if (flag == Flags.ANNOTATION) {
  2792                 checkAnnotations();
  2793                 if (token.kind != INTERFACE) {
  2794                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
  2795                     // if first modifier is an annotation, set pos to annotation's.
  2796                     if (flags == 0 && annotations.isEmpty())
  2797                         pos = ann.pos;
  2798                     annotations.append(ann);
  2799                     flag = 0;
  2802             flags |= flag;
  2804         switch (token.kind) {
  2805         case ENUM: flags |= Flags.ENUM; break;
  2806         case INTERFACE: flags |= Flags.INTERFACE; break;
  2807         default: break;
  2810         /* A modifiers tree with no modifier tokens or annotations
  2811          * has no text position. */
  2812         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2813             pos = Position.NOPOS;
  2815         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2816         if (pos != Position.NOPOS)
  2817             storeEnd(mods, S.prevToken().endPos);
  2818         return mods;
  2821     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2823      * @param pos position of "@" token
  2824      * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
  2825      */
  2826     JCAnnotation annotation(int pos, Tag kind) {
  2827         // accept(AT); // AT consumed by caller
  2828         checkAnnotations();
  2829         if (kind == Tag.TYPE_ANNOTATION) {
  2830             checkTypeAnnotations();
  2832         JCTree ident = qualident(false);
  2833         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2834         JCAnnotation ann;
  2835         if (kind == Tag.ANNOTATION) {
  2836             ann = F.at(pos).Annotation(ident, fieldValues);
  2837         } else if (kind == Tag.TYPE_ANNOTATION) {
  2838             ann = F.at(pos).TypeAnnotation(ident, fieldValues);
  2839         } else {
  2840             throw new AssertionError("Unhandled annotation kind: " + kind);
  2843         storeEnd(ann, S.prevToken().endPos);
  2844         return ann;
  2847     List<JCExpression> annotationFieldValuesOpt() {
  2848         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2851     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2852     List<JCExpression> annotationFieldValues() {
  2853         accept(LPAREN);
  2854         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2855         if (token.kind != RPAREN) {
  2856             buf.append(annotationFieldValue());
  2857             while (token.kind == COMMA) {
  2858                 nextToken();
  2859                 buf.append(annotationFieldValue());
  2862         accept(RPAREN);
  2863         return buf.toList();
  2866     /** AnnotationFieldValue    = AnnotationValue
  2867      *                          | Identifier "=" AnnotationValue
  2868      */
  2869     JCExpression annotationFieldValue() {
  2870         if (token.kind == IDENTIFIER) {
  2871             mode = EXPR;
  2872             JCExpression t1 = term1();
  2873             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2874                 int pos = token.pos;
  2875                 accept(EQ);
  2876                 JCExpression v = annotationValue();
  2877                 return toP(F.at(pos).Assign(t1, v));
  2878             } else {
  2879                 return t1;
  2882         return annotationValue();
  2885     /* AnnotationValue          = ConditionalExpression
  2886      *                          | Annotation
  2887      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2888      */
  2889     JCExpression annotationValue() {
  2890         int pos;
  2891         switch (token.kind) {
  2892         case MONKEYS_AT:
  2893             pos = token.pos;
  2894             nextToken();
  2895             return annotation(pos, Tag.ANNOTATION);
  2896         case LBRACE:
  2897             pos = token.pos;
  2898             accept(LBRACE);
  2899             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2900             if (token.kind != RBRACE) {
  2901                 buf.append(annotationValue());
  2902                 while (token.kind == COMMA) {
  2903                     nextToken();
  2904                     if (token.kind == RBRACE) break;
  2905                     buf.append(annotationValue());
  2908             accept(RBRACE);
  2909             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2910         default:
  2911             mode = EXPR;
  2912             return term1();
  2916     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2917      */
  2918     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2919                                                                          JCExpression type,
  2920                                                                          T vdefs)
  2922         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2925     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2926      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2928      *  @param reqInit  Is an initializer always required?
  2929      *  @param dc       The documentation comment for the variable declarations, or null.
  2930      */
  2931     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2932                                                                      JCModifiers mods,
  2933                                                                      JCExpression type,
  2934                                                                      Name name,
  2935                                                                      boolean reqInit,
  2936                                                                      Comment dc,
  2937                                                                      T vdefs)
  2939         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2940         while (token.kind == COMMA) {
  2941             // All but last of multiple declarators subsume a comma
  2942             storeEnd((JCTree)vdefs.last(), token.endPos);
  2943             nextToken();
  2944             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2946         return vdefs;
  2949     /** VariableDeclarator = Ident VariableDeclaratorRest
  2950      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2951      */
  2952     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2953         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2956     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2957      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2959      *  @param reqInit  Is an initializer always required?
  2960      *  @param dc       The documentation comment for the variable declarations, or null.
  2961      */
  2962     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2963                                   boolean reqInit, Comment dc) {
  2964         type = bracketsOpt(type);
  2965         JCExpression init = null;
  2966         if (token.kind == EQ) {
  2967             nextToken();
  2968             init = variableInitializer();
  2970         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2971         JCVariableDecl result =
  2972             toP(F.at(pos).VarDef(mods, name, type, init));
  2973         attach(result, dc);
  2974         return result;
  2977     /** VariableDeclaratorId = Ident BracketsOpt
  2978      */
  2979     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2980         return variableDeclaratorId(mods, type, false);
  2982     //where
  2983     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
  2984         int pos = token.pos;
  2985         Name name;
  2986         if (lambdaParameter && token.kind == UNDERSCORE) {
  2987             syntaxError(pos, "expected", IDENTIFIER);
  2988             name = token.name();
  2989         } else {
  2990             name = ident();
  2992         if ((mods.flags & Flags.VARARGS) != 0 &&
  2993                 token.kind == LBRACKET) {
  2994             log.error(token.pos, "varargs.and.old.array.syntax");
  2996         type = bracketsOpt(type);
  2997         return toP(F.at(pos).VarDef(mods, name, type, null));
  3000     /** Resources = Resource { ";" Resources }
  3001      */
  3002     List<JCTree> resources() {
  3003         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3004         defs.append(resource());
  3005         while (token.kind == SEMI) {
  3006             // All but last of multiple declarators must subsume a semicolon
  3007             storeEnd(defs.last(), token.endPos);
  3008             int semiColonPos = token.pos;
  3009             nextToken();
  3010             if (token.kind == RPAREN) { // Optional trailing semicolon
  3011                                        // after last resource
  3012                 break;
  3014             defs.append(resource());
  3016         return defs.toList();
  3019     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  3020      */
  3021     protected JCTree resource() {
  3022         JCModifiers optFinal = optFinal(Flags.FINAL);
  3023         JCExpression type = parseType();
  3024         int pos = token.pos;
  3025         Name ident = ident();
  3026         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  3029     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  3030      */
  3031     public JCTree.JCCompilationUnit parseCompilationUnit() {
  3032         Token firstToken = token;
  3033         JCExpression pid = null;
  3034         JCModifiers mods = null;
  3035         boolean consumedToplevelDoc = false;
  3036         boolean seenImport = false;
  3037         boolean seenPackage = false;
  3038         List<JCAnnotation> packageAnnotations = List.nil();
  3039         if (token.kind == MONKEYS_AT)
  3040             mods = modifiersOpt();
  3042         if (token.kind == PACKAGE) {
  3043             seenPackage = true;
  3044             if (mods != null) {
  3045                 checkNoMods(mods.flags);
  3046                 packageAnnotations = mods.annotations;
  3047                 mods = null;
  3049             nextToken();
  3050             pid = qualident(false);
  3051             accept(SEMI);
  3053         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3054         boolean checkForImports = true;
  3055         boolean firstTypeDecl = true;
  3056         while (token.kind != EOF) {
  3057             if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
  3058                 // error recovery
  3059                 skip(checkForImports, false, false, false);
  3060                 if (token.kind == EOF)
  3061                     break;
  3063             if (checkForImports && mods == null && token.kind == IMPORT) {
  3064                 seenImport = true;
  3065                 defs.append(importDeclaration());
  3066             } else {
  3067                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  3068                 if (firstTypeDecl && !seenImport && !seenPackage) {
  3069                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  3070                     consumedToplevelDoc = true;
  3072                 JCTree def = typeDeclaration(mods, docComment);
  3073                 if (def instanceof JCExpressionStatement)
  3074                     def = ((JCExpressionStatement)def).expr;
  3075                 defs.append(def);
  3076                 if (def instanceof JCClassDecl)
  3077                     checkForImports = false;
  3078                 mods = null;
  3079                 firstTypeDecl = false;
  3082         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  3083         if (!consumedToplevelDoc)
  3084             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  3085         if (defs.isEmpty())
  3086             storeEnd(toplevel, S.prevToken().endPos);
  3087         if (keepDocComments)
  3088             toplevel.docComments = docComments;
  3089         if (keepLineMap)
  3090             toplevel.lineMap = S.getLineMap();
  3091         toplevel.endPositions = this.endPosTable;
  3092         return toplevel;
  3095     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  3096      */
  3097     JCTree importDeclaration() {
  3098         int pos = token.pos;
  3099         nextToken();
  3100         boolean importStatic = false;
  3101         if (token.kind == STATIC) {
  3102             checkStaticImports();
  3103             importStatic = true;
  3104             nextToken();
  3106         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  3107         do {
  3108             int pos1 = token.pos;
  3109             accept(DOT);
  3110             if (token.kind == STAR) {
  3111                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  3112                 nextToken();
  3113                 break;
  3114             } else {
  3115                 pid = toP(F.at(pos1).Select(pid, ident()));
  3117         } while (token.kind == DOT);
  3118         accept(SEMI);
  3119         return toP(F.at(pos).Import(pid, importStatic));
  3122     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  3123      *                  | ";"
  3124      */
  3125     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  3126         int pos = token.pos;
  3127         if (mods == null && token.kind == SEMI) {
  3128             nextToken();
  3129             return toP(F.at(pos).Skip());
  3130         } else {
  3131             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  3135     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  3136      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  3137      *  @param mods     Any modifiers starting the class or interface declaration
  3138      *  @param dc       The documentation comment for the class, or null.
  3139      */
  3140     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  3141         if (token.kind == CLASS) {
  3142             return classDeclaration(mods, dc);
  3143         } else if (token.kind == INTERFACE) {
  3144             return interfaceDeclaration(mods, dc);
  3145         } else if (allowEnums) {
  3146             if (token.kind == ENUM) {
  3147                 return enumDeclaration(mods, dc);
  3148             } else {
  3149                 int pos = token.pos;
  3150                 List<JCTree> errs;
  3151                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  3152                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  3153                     setErrorEndPos(token.pos);
  3154                 } else {
  3155                     errs = List.<JCTree>of(mods);
  3157                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  3158                                               CLASS, INTERFACE, ENUM)));
  3160         } else {
  3161             if (token.kind == ENUM) {
  3162                 error(token.pos, "enums.not.supported.in.source", source.name);
  3163                 allowEnums = true;
  3164                 return enumDeclaration(mods, dc);
  3166             int pos = token.pos;
  3167             List<JCTree> errs;
  3168             if (LAX_IDENTIFIER.accepts(token.kind)) {
  3169                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  3170                 setErrorEndPos(token.pos);
  3171             } else {
  3172                 errs = List.<JCTree>of(mods);
  3174             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  3175                                           CLASS, INTERFACE)));
  3179     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  3180      *                     [IMPLEMENTS TypeList] ClassBody
  3181      *  @param mods    The modifiers starting the class declaration
  3182      *  @param dc       The documentation comment for the class, or null.
  3183      */
  3184     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  3185         int pos = token.pos;
  3186         accept(CLASS);
  3187         Name name = ident();
  3189         List<JCTypeParameter> typarams = typeParametersOpt();
  3191         JCExpression extending = null;
  3192         if (token.kind == EXTENDS) {
  3193             nextToken();
  3194             extending = parseType();
  3196         List<JCExpression> implementing = List.nil();
  3197         if (token.kind == IMPLEMENTS) {
  3198             nextToken();
  3199             implementing = typeList();
  3201         List<JCTree> defs = classOrInterfaceBody(name, false);
  3202         JCClassDecl result = toP(F.at(pos).ClassDef(
  3203             mods, name, typarams, extending, implementing, defs));
  3204         attach(result, dc);
  3205         return result;
  3208     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  3209      *                         [EXTENDS TypeList] InterfaceBody
  3210      *  @param mods    The modifiers starting the interface declaration
  3211      *  @param dc       The documentation comment for the interface, or null.
  3212      */
  3213     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  3214         int pos = token.pos;
  3215         accept(INTERFACE);
  3216         Name name = ident();
  3218         List<JCTypeParameter> typarams = typeParametersOpt();
  3220         List<JCExpression> extending = List.nil();
  3221         if (token.kind == EXTENDS) {
  3222             nextToken();
  3223             extending = typeList();
  3225         List<JCTree> defs = classOrInterfaceBody(name, true);
  3226         JCClassDecl result = toP(F.at(pos).ClassDef(
  3227             mods, name, typarams, null, extending, defs));
  3228         attach(result, dc);
  3229         return result;
  3232     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  3233      *  @param mods    The modifiers starting the enum declaration
  3234      *  @param dc       The documentation comment for the enum, or null.
  3235      */
  3236     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  3237         int pos = token.pos;
  3238         accept(ENUM);
  3239         Name name = ident();
  3241         List<JCExpression> implementing = List.nil();
  3242         if (token.kind == IMPLEMENTS) {
  3243             nextToken();
  3244             implementing = typeList();
  3247         List<JCTree> defs = enumBody(name);
  3248         mods.flags |= Flags.ENUM;
  3249         JCClassDecl result = toP(F.at(pos).
  3250             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  3251                 null, implementing, defs));
  3252         attach(result, dc);
  3253         return result;
  3256     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  3257      *                  [ ";" {ClassBodyDeclaration} ] "}"
  3258      */
  3259     List<JCTree> enumBody(Name enumName) {
  3260         accept(LBRACE);
  3261         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3262         if (token.kind == COMMA) {
  3263             nextToken();
  3264         } else if (token.kind != RBRACE && token.kind != SEMI) {
  3265             defs.append(enumeratorDeclaration(enumName));
  3266             while (token.kind == COMMA) {
  3267                 nextToken();
  3268                 if (token.kind == RBRACE || token.kind == SEMI) break;
  3269                 defs.append(enumeratorDeclaration(enumName));
  3271             if (token.kind != SEMI && token.kind != RBRACE) {
  3272                 defs.append(syntaxError(token.pos, "expected3",
  3273                                 COMMA, RBRACE, SEMI));
  3274                 nextToken();
  3277         if (token.kind == SEMI) {
  3278             nextToken();
  3279             while (token.kind != RBRACE && token.kind != EOF) {
  3280                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  3281                                                                 false));
  3282                 if (token.pos <= endPosTable.errorEndPos) {
  3283                     // error recovery
  3284                    skip(false, true, true, false);
  3288         accept(RBRACE);
  3289         return defs.toList();
  3292     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  3293      */
  3294     JCTree enumeratorDeclaration(Name enumName) {
  3295         Comment dc = token.comment(CommentStyle.JAVADOC);
  3296         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  3297         if (token.deprecatedFlag()) {
  3298             flags |= Flags.DEPRECATED;
  3300         int pos = token.pos;
  3301         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
  3302         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  3303         List<JCExpression> typeArgs = typeArgumentsOpt();
  3304         int identPos = token.pos;
  3305         Name name = ident();
  3306         int createPos = token.pos;
  3307         List<JCExpression> args = (token.kind == LPAREN)
  3308             ? arguments() : List.<JCExpression>nil();
  3309         JCClassDecl body = null;
  3310         if (token.kind == LBRACE) {
  3311             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  3312             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  3313             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  3315         if (args.isEmpty() && body == null)
  3316             createPos = identPos;
  3317         JCIdent ident = F.at(identPos).Ident(enumName);
  3318         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  3319         if (createPos != identPos)
  3320             storeEnd(create, S.prevToken().endPos);
  3321         ident = F.at(identPos).Ident(enumName);
  3322         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  3323         attach(result, dc);
  3324         return result;
  3327     /** TypeList = Type {"," Type}
  3328      */
  3329     List<JCExpression> typeList() {
  3330         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3331         ts.append(parseType());
  3332         while (token.kind == COMMA) {
  3333             nextToken();
  3334             ts.append(parseType());
  3336         return ts.toList();
  3339     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  3340      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  3341      */
  3342     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  3343         accept(LBRACE);
  3344         if (token.pos <= endPosTable.errorEndPos) {
  3345             // error recovery
  3346             skip(false, true, false, false);
  3347             if (token.kind == LBRACE)
  3348                 nextToken();
  3350         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  3351         while (token.kind != RBRACE && token.kind != EOF) {
  3352             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  3353             if (token.pos <= endPosTable.errorEndPos) {
  3354                // error recovery
  3355                skip(false, true, true, false);
  3358         accept(RBRACE);
  3359         return defs.toList();
  3362     /** ClassBodyDeclaration =
  3363      *      ";"
  3364      *    | [STATIC] Block
  3365      *    | ModifiersOpt
  3366      *      ( Type Ident
  3367      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  3368      *      | VOID Ident MethodDeclaratorRest
  3369      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  3370      *      | Ident ConstructorDeclaratorRest
  3371      *      | TypeParameters Ident ConstructorDeclaratorRest
  3372      *      | ClassOrInterfaceOrEnumDeclaration
  3373      *      )
  3374      *  InterfaceBodyDeclaration =
  3375      *      ";"
  3376      *    | ModifiersOpt Type Ident
  3377      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  3378      */
  3379     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  3380         if (token.kind == SEMI) {
  3381             nextToken();
  3382             return List.<JCTree>nil();
  3383         } else {
  3384             Comment dc = token.comment(CommentStyle.JAVADOC);
  3385             int pos = token.pos;
  3386             JCModifiers mods = modifiersOpt();
  3387             if (token.kind == CLASS ||
  3388                 token.kind == INTERFACE ||
  3389                 allowEnums && token.kind == ENUM) {
  3390                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  3391             } else if (token.kind == LBRACE && !isInterface &&
  3392                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  3393                        mods.annotations.isEmpty()) {
  3394                 return List.<JCTree>of(block(pos, mods.flags));
  3395             } else {
  3396                 pos = token.pos;
  3397                 List<JCTypeParameter> typarams = typeParametersOpt();
  3398                 // if there are type parameters but no modifiers, save the start
  3399                 // position of the method in the modifiers.
  3400                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  3401                     mods.pos = pos;
  3402                     storeEnd(mods, pos);
  3404                 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
  3406                 Token tk = token;
  3407                 pos = token.pos;
  3408                 JCExpression type;
  3409                 boolean isVoid = token.kind == VOID;
  3410                 if (isVoid) {
  3411                     if (annosAfterParams.nonEmpty())
  3412                         illegal(annosAfterParams.head.pos);
  3413                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
  3414                     nextToken();
  3415                 } else {
  3416                     if (annosAfterParams.nonEmpty()) {
  3417                         mods.annotations = mods.annotations.appendList(annosAfterParams);
  3418                         if (mods.pos == Position.NOPOS)
  3419                             mods.pos = mods.annotations.head.pos;
  3421                     // method returns types are un-annotated types
  3422                     type = unannotatedType();
  3424                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  3425                     if (isInterface || tk.name() != className)
  3426                         error(pos, "invalid.meth.decl.ret.type.req");
  3427                     return List.of(methodDeclaratorRest(
  3428                         pos, mods, null, names.init, typarams,
  3429                         isInterface, true, dc));
  3430                 } else {
  3431                     pos = token.pos;
  3432                     Name name = ident();
  3433                     if (token.kind == LPAREN) {
  3434                         return List.of(methodDeclaratorRest(
  3435                             pos, mods, type, name, typarams,
  3436                             isInterface, isVoid, dc));
  3437                     } else if (!isVoid && typarams.isEmpty()) {
  3438                         List<JCTree> defs =
  3439                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  3440                                                     new ListBuffer<JCTree>()).toList();
  3441                         storeEnd(defs.last(), token.endPos);
  3442                         accept(SEMI);
  3443                         return defs;
  3444                     } else {
  3445                         pos = token.pos;
  3446                         List<JCTree> err = isVoid
  3447                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3448                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  3449                             : null;
  3450                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  3457     /** MethodDeclaratorRest =
  3458      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  3459      *  VoidMethodDeclaratorRest =
  3460      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  3461      *  InterfaceMethodDeclaratorRest =
  3462      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  3463      *  VoidInterfaceMethodDeclaratorRest =
  3464      *      FormalParameters [THROWS TypeList] ";"
  3465      *  ConstructorDeclaratorRest =
  3466      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  3467      */
  3468     protected JCTree methodDeclaratorRest(int pos,
  3469                               JCModifiers mods,
  3470                               JCExpression type,
  3471                               Name name,
  3472                               List<JCTypeParameter> typarams,
  3473                               boolean isInterface, boolean isVoid,
  3474                               Comment dc) {
  3475         if (isInterface && (mods.flags & Flags.STATIC) != 0) {
  3476             checkStaticInterfaceMethods();
  3478         JCVariableDecl prevReceiverParam = this.receiverParam;
  3479         try {
  3480             this.receiverParam = null;
  3481             // Parsing formalParameters sets the receiverParam, if present
  3482             List<JCVariableDecl> params = formalParameters();
  3483             if (!isVoid) type = bracketsOpt(type);
  3484             List<JCExpression> thrown = List.nil();
  3485             if (token.kind == THROWS) {
  3486                 nextToken();
  3487                 thrown = qualidentList();
  3489             JCBlock body = null;
  3490             JCExpression defaultValue;
  3491             if (token.kind == LBRACE) {
  3492                 body = block();
  3493                 defaultValue = null;
  3494             } else {
  3495                 if (token.kind == DEFAULT) {
  3496                     accept(DEFAULT);
  3497                     defaultValue = annotationValue();
  3498                 } else {
  3499                     defaultValue = null;
  3501                 accept(SEMI);
  3502                 if (token.pos <= endPosTable.errorEndPos) {
  3503                     // error recovery
  3504                     skip(false, true, false, false);
  3505                     if (token.kind == LBRACE) {
  3506                         body = block();
  3511             JCMethodDecl result =
  3512                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3513                                             receiverParam, params, thrown,
  3514                                             body, defaultValue));
  3515             attach(result, dc);
  3516             return result;
  3517         } finally {
  3518             this.receiverParam = prevReceiverParam;
  3522     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
  3523      */
  3524     List<JCExpression> qualidentList() {
  3525         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3527         List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
  3528         if (!typeAnnos.isEmpty())
  3529             ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true))));
  3530         else
  3531             ts.append(qualident(true));
  3532         while (token.kind == COMMA) {
  3533             nextToken();
  3535             typeAnnos = typeAnnotationsOpt();
  3536             if (!typeAnnos.isEmpty())
  3537                 ts.append(toP(F.at(typeAnnos.head.pos).AnnotatedType(typeAnnos, qualident(true))));
  3538             else
  3539                 ts.append(qualident(true));
  3541         return ts.toList();
  3544     /**
  3545      *  {@literal
  3546      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3547      *  }
  3548      */
  3549     List<JCTypeParameter> typeParametersOpt() {
  3550         if (token.kind == LT) {
  3551             checkGenerics();
  3552             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3553             nextToken();
  3554             typarams.append(typeParameter());
  3555             while (token.kind == COMMA) {
  3556                 nextToken();
  3557                 typarams.append(typeParameter());
  3559             accept(GT);
  3560             return typarams.toList();
  3561         } else {
  3562             return List.nil();
  3566     /**
  3567      *  {@literal
  3568      *  TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
  3569      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3570      *  TypeVariable = Ident
  3571      *  }
  3572      */
  3573     JCTypeParameter typeParameter() {
  3574         int pos = token.pos;
  3575         List<JCAnnotation> annos = typeAnnotationsOpt();
  3576         Name name = ident();
  3577         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3578         if (token.kind == EXTENDS) {
  3579             nextToken();
  3580             bounds.append(parseType());
  3581             while (token.kind == AMP) {
  3582                 nextToken();
  3583                 bounds.append(parseType());
  3586         return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
  3589     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3590      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3591      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3592      */
  3593     List<JCVariableDecl> formalParameters() {
  3594         return formalParameters(false);
  3596     List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
  3597         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3598         JCVariableDecl lastParam;
  3599         accept(LPAREN);
  3600         if (token.kind != RPAREN) {
  3601             this.allowThisIdent = true;
  3602             lastParam = formalParameter(lambdaParameters);
  3603             if (lastParam.name.contentEquals(TokenKind.THIS.name)) {
  3604                 this.receiverParam = lastParam;
  3605             } else {
  3606                 params.append(lastParam);
  3608             this.allowThisIdent = false;
  3609             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3610                 nextToken();
  3611                 params.append(lastParam = formalParameter(lambdaParameters));
  3614         accept(RPAREN);
  3615         return params.toList();
  3618     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3619         if (hasParens) {
  3620             accept(LPAREN);
  3622         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3623         if (token.kind != RPAREN && token.kind != ARROW) {
  3624             params.append(implicitParameter());
  3625             while (token.kind == COMMA) {
  3626                 nextToken();
  3627                 params.append(implicitParameter());
  3630         if (hasParens) {
  3631             accept(RPAREN);
  3633         return params.toList();
  3636     JCModifiers optFinal(long flags) {
  3637         JCModifiers mods = modifiersOpt();
  3638         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3639         mods.flags |= flags;
  3640         return mods;
  3643     /**
  3644      * Inserts the annotations (and possibly a new array level)
  3645      * to the left-most type in an array or nested type.
  3647      * When parsing a type like {@code @B Outer.Inner @A []}, the
  3648      * {@code @A} annotation should target the array itself, while
  3649      * {@code @B} targets the nested type {@code Outer}.
  3651      * Currently the parser parses the annotation first, then
  3652      * the array, and then inserts the annotation to the left-most
  3653      * nested type.
  3655      * When {@code createNewLevel} is true, then a new array
  3656      * level is inserted as the most inner type, and have the
  3657      * annotations target it.  This is useful in the case of
  3658      * varargs, e.g. {@code String @A [] @B ...}, as the parser
  3659      * first parses the type {@code String @A []} then inserts
  3660      * a new array level with {@code @B} annotation.
  3661      */
  3662     private JCExpression insertAnnotationsToMostInner(
  3663             JCExpression type, List<JCAnnotation> annos,
  3664             boolean createNewLevel) {
  3665         int origEndPos = getEndPos(type);
  3666         JCExpression mostInnerType = type;
  3667         JCArrayTypeTree mostInnerArrayType = null;
  3668         while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
  3669             mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
  3670             mostInnerType = mostInnerArrayType.elemtype;
  3673         if (createNewLevel) {
  3674             mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
  3677         JCExpression mostInnerTypeToReturn = mostInnerType;
  3678         if (annos.nonEmpty()) {
  3679             JCExpression lastToModify = mostInnerType;
  3681             while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
  3682                     TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
  3683                 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
  3684                     lastToModify = mostInnerType;
  3685                     mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
  3687                 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
  3688                     lastToModify = mostInnerType;
  3689                     mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
  3693             mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
  3695             if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
  3696                 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
  3697             } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
  3698                 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
  3699             } else {
  3700                 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
  3701                 mostInnerTypeToReturn = mostInnerType;
  3705         if (mostInnerArrayType == null) {
  3706             return mostInnerTypeToReturn;
  3707         } else {
  3708             mostInnerArrayType.elemtype = mostInnerTypeToReturn;
  3709             storeEnd(type, origEndPos);
  3710             return type;
  3714     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3715      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3716      */
  3717     protected JCVariableDecl formalParameter() {
  3718         return formalParameter(false);
  3720     protected JCVariableDecl formalParameter(boolean lambdaParameter) {
  3721         JCModifiers mods = optFinal(Flags.PARAMETER);
  3722         // need to distinguish between vararg annos and array annos
  3723         // look at typeAnnotationsPushedBack comment
  3724         this.permitTypeAnnotationsPushBack = true;
  3725         JCExpression type = parseType();
  3726         this.permitTypeAnnotationsPushBack = false;
  3728         if (token.kind == ELLIPSIS) {
  3729             List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
  3730             typeAnnotationsPushedBack = List.nil();
  3731             checkVarargs();
  3732             mods.flags |= Flags.VARARGS;
  3733             // insert var arg type annotations
  3734             type = insertAnnotationsToMostInner(type, varargsAnnos, true);
  3735             nextToken();
  3736         } else {
  3737             // if not a var arg, then typeAnnotationsPushedBack should be null
  3738             if (typeAnnotationsPushedBack.nonEmpty()) {
  3739                 reportSyntaxError(typeAnnotationsPushedBack.head.pos,
  3740                         "illegal.start.of.type");
  3742             typeAnnotationsPushedBack = List.nil();
  3744         return variableDeclaratorId(mods, type, lambdaParameter);
  3747     protected JCVariableDecl implicitParameter() {
  3748         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3749         return variableDeclaratorId(mods, null, true);
  3752 /* ---------- auxiliary methods -------------- */
  3754     void error(int pos, String key, Object ... args) {
  3755         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3758     void error(DiagnosticPosition pos, String key, Object ... args) {
  3759         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3762     void warning(int pos, String key, Object ... args) {
  3763         log.warning(pos, key, args);
  3766     /** Check that given tree is a legal expression statement.
  3767      */
  3768     protected JCExpression checkExprStat(JCExpression t) {
  3769         if (!TreeInfo.isExpressionStatement(t)) {
  3770             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3771             error(ret, "not.stmt");
  3772             return ret;
  3773         } else {
  3774             return t;
  3778     /** Return precedence of operator represented by token,
  3779      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3780      */
  3781     static int prec(TokenKind token) {
  3782         JCTree.Tag oc = optag(token);
  3783         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3786     /**
  3787      * Return the lesser of two positions, making allowance for either one
  3788      * being unset.
  3789      */
  3790     static int earlier(int pos1, int pos2) {
  3791         if (pos1 == Position.NOPOS)
  3792             return pos2;
  3793         if (pos2 == Position.NOPOS)
  3794             return pos1;
  3795         return (pos1 < pos2 ? pos1 : pos2);
  3798     /** Return operation tag of binary operator represented by token,
  3799      *  No_TAG if token is not a binary operator.
  3800      */
  3801     static JCTree.Tag optag(TokenKind token) {
  3802         switch (token) {
  3803         case BARBAR:
  3804             return OR;
  3805         case AMPAMP:
  3806             return AND;
  3807         case BAR:
  3808             return BITOR;
  3809         case BAREQ:
  3810             return BITOR_ASG;
  3811         case CARET:
  3812             return BITXOR;
  3813         case CARETEQ:
  3814             return BITXOR_ASG;
  3815         case AMP:
  3816             return BITAND;
  3817         case AMPEQ:
  3818             return BITAND_ASG;
  3819         case EQEQ:
  3820             return JCTree.Tag.EQ;
  3821         case BANGEQ:
  3822             return NE;
  3823         case LT:
  3824             return JCTree.Tag.LT;
  3825         case GT:
  3826             return JCTree.Tag.GT;
  3827         case LTEQ:
  3828             return LE;
  3829         case GTEQ:
  3830             return GE;
  3831         case LTLT:
  3832             return SL;
  3833         case LTLTEQ:
  3834             return SL_ASG;
  3835         case GTGT:
  3836             return SR;
  3837         case GTGTEQ:
  3838             return SR_ASG;
  3839         case GTGTGT:
  3840             return USR;
  3841         case GTGTGTEQ:
  3842             return USR_ASG;
  3843         case PLUS:
  3844             return JCTree.Tag.PLUS;
  3845         case PLUSEQ:
  3846             return PLUS_ASG;
  3847         case SUB:
  3848             return MINUS;
  3849         case SUBEQ:
  3850             return MINUS_ASG;
  3851         case STAR:
  3852             return MUL;
  3853         case STAREQ:
  3854             return MUL_ASG;
  3855         case SLASH:
  3856             return DIV;
  3857         case SLASHEQ:
  3858             return DIV_ASG;
  3859         case PERCENT:
  3860             return MOD;
  3861         case PERCENTEQ:
  3862             return MOD_ASG;
  3863         case INSTANCEOF:
  3864             return TYPETEST;
  3865         default:
  3866             return NO_TAG;
  3870     /** Return operation tag of unary operator represented by token,
  3871      *  No_TAG if token is not a binary operator.
  3872      */
  3873     static JCTree.Tag unoptag(TokenKind token) {
  3874         switch (token) {
  3875         case PLUS:
  3876             return POS;
  3877         case SUB:
  3878             return NEG;
  3879         case BANG:
  3880             return NOT;
  3881         case TILDE:
  3882             return COMPL;
  3883         case PLUSPLUS:
  3884             return PREINC;
  3885         case SUBSUB:
  3886             return PREDEC;
  3887         default:
  3888             return NO_TAG;
  3892     /** Return type tag of basic type represented by token,
  3893      *  NONE if token is not a basic type identifier.
  3894      */
  3895     static TypeTag typetag(TokenKind token) {
  3896         switch (token) {
  3897         case BYTE:
  3898             return TypeTag.BYTE;
  3899         case CHAR:
  3900             return TypeTag.CHAR;
  3901         case SHORT:
  3902             return TypeTag.SHORT;
  3903         case INT:
  3904             return TypeTag.INT;
  3905         case LONG:
  3906             return TypeTag.LONG;
  3907         case FLOAT:
  3908             return TypeTag.FLOAT;
  3909         case DOUBLE:
  3910             return TypeTag.DOUBLE;
  3911         case BOOLEAN:
  3912             return TypeTag.BOOLEAN;
  3913         default:
  3914             return TypeTag.NONE;
  3918     void checkGenerics() {
  3919         if (!allowGenerics) {
  3920             error(token.pos, "generics.not.supported.in.source", source.name);
  3921             allowGenerics = true;
  3924     void checkVarargs() {
  3925         if (!allowVarargs) {
  3926             error(token.pos, "varargs.not.supported.in.source", source.name);
  3927             allowVarargs = true;
  3930     void checkForeach() {
  3931         if (!allowForeach) {
  3932             error(token.pos, "foreach.not.supported.in.source", source.name);
  3933             allowForeach = true;
  3936     void checkStaticImports() {
  3937         if (!allowStaticImport) {
  3938             error(token.pos, "static.import.not.supported.in.source", source.name);
  3939             allowStaticImport = true;
  3942     void checkAnnotations() {
  3943         if (!allowAnnotations) {
  3944             error(token.pos, "annotations.not.supported.in.source", source.name);
  3945             allowAnnotations = true;
  3948     void checkDiamond() {
  3949         if (!allowDiamond) {
  3950             error(token.pos, "diamond.not.supported.in.source", source.name);
  3951             allowDiamond = true;
  3954     void checkMulticatch() {
  3955         if (!allowMulticatch) {
  3956             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3957             allowMulticatch = true;
  3960     void checkTryWithResources() {
  3961         if (!allowTWR) {
  3962             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3963             allowTWR = true;
  3966     void checkLambda() {
  3967         if (!allowLambda) {
  3968             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3969             allowLambda = true;
  3972     void checkMethodReferences() {
  3973         if (!allowMethodReferences) {
  3974             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3975             allowMethodReferences = true;
  3978     void checkDefaultMethods() {
  3979         if (!allowDefaultMethods) {
  3980             log.error(token.pos, "default.methods.not.supported.in.source", source.name);
  3981             allowDefaultMethods = true;
  3984     void checkIntersectionTypesInCast() {
  3985         if (!allowIntersectionTypesInCast) {
  3986             log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
  3987             allowIntersectionTypesInCast = true;
  3990     void checkStaticInterfaceMethods() {
  3991         if (!allowStaticInterfaceMethods) {
  3992             log.error(token.pos, "static.intf.methods.not.supported.in.source", source.name);
  3993             allowStaticInterfaceMethods = true;
  3996     void checkTypeAnnotations() {
  3997         if (!allowTypeAnnotations) {
  3998             log.error(token.pos, "type.annotations.not.supported.in.source", source.name);
  3999             allowTypeAnnotations = true;
  4003     /*
  4004      * a functional source tree and end position mappings
  4005      */
  4006     protected class SimpleEndPosTable extends AbstractEndPosTable {
  4008         private final Map<JCTree, Integer> endPosMap;
  4010         SimpleEndPosTable() {
  4011             endPosMap = new HashMap<JCTree, Integer>();
  4014         protected void storeEnd(JCTree tree, int endpos) {
  4015             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  4018         protected <T extends JCTree> T to(T t) {
  4019             storeEnd(t, token.endPos);
  4020             return t;
  4023         protected <T extends JCTree> T toP(T t) {
  4024             storeEnd(t, S.prevToken().endPos);
  4025             return t;
  4028         public int getEndPos(JCTree tree) {
  4029             Integer value = endPosMap.get(tree);
  4030             return (value == null) ? Position.NOPOS : value;
  4033         public int replaceTree(JCTree oldTree, JCTree newTree) {
  4034             Integer pos = endPosMap.remove(oldTree);
  4035             if (pos != null) {
  4036                 endPosMap.put(newTree, pos);
  4037                 return pos;
  4039             return Position.NOPOS;
  4043     /*
  4044      * a default skeletal implementation without any mapping overhead.
  4045      */
  4046     protected class EmptyEndPosTable extends AbstractEndPosTable {
  4048         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  4050         protected <T extends JCTree> T to(T t) {
  4051             return t;
  4054         protected <T extends JCTree> T toP(T t) {
  4055             return t;
  4058         public int getEndPos(JCTree tree) {
  4059             return Position.NOPOS;
  4062         public int replaceTree(JCTree oldTree, JCTree newTree) {
  4063             return Position.NOPOS;
  4068     protected abstract class AbstractEndPosTable implements EndPosTable {
  4070         /**
  4071          * Store the last error position.
  4072          */
  4073         protected int errorEndPos;
  4075         /**
  4076          * Store ending position for a tree, the value of which is the greater
  4077          * of last error position and the given ending position.
  4078          * @param tree   The tree.
  4079          * @param endpos The ending position to associate with the tree.
  4080          */
  4081         protected abstract void storeEnd(JCTree tree, int endpos);
  4083         /**
  4084          * Store current token's ending position for a tree, the value of which
  4085          * will be the greater of last error position and the ending position of
  4086          * the current token.
  4087          * @param t The tree.
  4088          */
  4089         protected abstract <T extends JCTree> T to(T t);
  4091         /**
  4092          * Store current token's ending position for a tree, the value of which
  4093          * will be the greater of last error position and the ending position of
  4094          * the previous token.
  4095          * @param t The tree.
  4096          */
  4097         protected abstract <T extends JCTree> T toP(T t);
  4099         /**
  4100          * Set the error position during the parsing phases, the value of which
  4101          * will be set only if it is greater than the last stored error position.
  4102          * @param errPos The error position
  4103          */
  4104         protected void setErrorEndPos(int errPos) {
  4105             if (errPos > errorEndPos) {
  4106                 errorEndPos = errPos;

mercurial