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

Mon, 21 Jan 2013 20:14:39 +0000

author
mcimadamore
date
Mon, 21 Jan 2013 20:14:39 +0000
changeset 1511
c7c41a044e7c
parent 1503
2d2b2be57c78
child 1513
cf84b07a82db
permissions
-rw-r--r--

8006566: Remove transient lambda-related guards from JavacParser
Summary: Remove transitional internal flag for allowing intersection types in cast
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javac.parser;
    28 import java.util.*;
    30 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
    32 import com.sun.tools.javac.code.*;
    33 import com.sun.tools.javac.parser.Tokens.*;
    34 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
    35 import com.sun.tools.javac.tree.*;
    36 import com.sun.tools.javac.tree.JCTree.*;
    37 import com.sun.tools.javac.util.*;
    38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
    39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    40 import com.sun.tools.javac.util.List;
    42 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
    43 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
    44 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
    45 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
    46 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
    47 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
    48 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
    49 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
    50 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    51 import static com.sun.tools.javac.util.ListBuffer.lb;
    53 /** The parser maps a token sequence into an abstract syntax
    54  *  tree. It operates by recursive descent, with code derived
    55  *  systematically from an LL(1) grammar. For efficiency reasons, an
    56  *  operator precedence scheme is used for parsing binary operation
    57  *  expressions.
    58  *
    59  *  <p><b>This is NOT part of any supported API.
    60  *  If you write code that depends on this, you do so at your own risk.
    61  *  This code and its internal interfaces are subject to change or
    62  *  deletion without notice.</b>
    63  */
    64 public class JavacParser implements Parser {
    66     /** The number of precedence levels of infix operators.
    67      */
    68     private static final int infixPrecedenceLevels = 10;
    70     /** The scanner used for lexical analysis.
    71      */
    72     protected Lexer S;
    74     /** The factory to be used for abstract syntax tree construction.
    75      */
    76     protected TreeMaker F;
    78     /** The log to be used for error diagnostics.
    79      */
    80     private Log log;
    82     /** The Source language setting. */
    83     private Source source;
    85     /** The name table. */
    86     private Names names;
    88     /** End position mappings container */
    89     private final AbstractEndPosTable endPosTable;
    91     interface ErrorRecoveryAction {
    92         JCTree doRecover(JavacParser parser);
    93     }
    95     enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
    96         BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
    97         CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
    98     }
   100     /** Construct a parser from a given scanner, tree factory and log.
   101      */
   102     protected JavacParser(ParserFactory fac,
   103                      Lexer S,
   104                      boolean keepDocComments,
   105                      boolean keepLineMap,
   106                      boolean keepEndPositions) {
   107         this.S = S;
   108         nextToken(); // prime the pump
   109         this.F = fac.F;
   110         this.log = fac.log;
   111         this.names = fac.names;
   112         this.source = fac.source;
   113         this.allowGenerics = source.allowGenerics();
   114         this.allowVarargs = source.allowVarargs();
   115         this.allowAsserts = source.allowAsserts();
   116         this.allowEnums = source.allowEnums();
   117         this.allowForeach = source.allowForeach();
   118         this.allowStaticImport = source.allowStaticImport();
   119         this.allowAnnotations = source.allowAnnotations();
   120         this.allowTWR = source.allowTryWithResources();
   121         this.allowDiamond = source.allowDiamond();
   122         this.allowMulticatch = source.allowMulticatch();
   123         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   124         this.allowLambda = source.allowLambda();
   125         this.allowMethodReferences = source.allowMethodReferences();
   126         this.allowDefaultMethods = source.allowDefaultMethods();
   127         this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
   128         this.keepDocComments = keepDocComments;
   129         docComments = newDocCommentTable(keepDocComments, fac);
   130         this.keepLineMap = keepLineMap;
   131         this.errorTree = F.Erroneous();
   132         endPosTable = newEndPosTable(keepEndPositions);
   133     }
   135     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
   136         return  keepEndPositions
   137                 ? new SimpleEndPosTable()
   138                 : new EmptyEndPosTable();
   139     }
   141     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
   142         return keepDocComments ? new LazyDocCommentTable(fac) : null;
   143     }
   145     /** Switch: Should generics be recognized?
   146      */
   147     boolean allowGenerics;
   149     /** Switch: Should diamond operator be recognized?
   150      */
   151     boolean allowDiamond;
   153     /** Switch: Should multicatch clause be accepted?
   154      */
   155     boolean allowMulticatch;
   157     /** Switch: Should varargs be recognized?
   158      */
   159     boolean allowVarargs;
   161     /** Switch: should we recognize assert statements, or just give a warning?
   162      */
   163     boolean allowAsserts;
   165     /** Switch: should we recognize enums, or just give a warning?
   166      */
   167     boolean allowEnums;
   169     /** Switch: should we recognize foreach?
   170      */
   171     boolean allowForeach;
   173     /** Switch: should we recognize foreach?
   174      */
   175     boolean allowStaticImport;
   177     /** Switch: should we recognize annotations?
   178      */
   179     boolean allowAnnotations;
   181     /** Switch: should we recognize try-with-resources?
   182      */
   183     boolean allowTWR;
   185     /** Switch: should we fold strings?
   186      */
   187     boolean allowStringFolding;
   189     /** Switch: should we recognize lambda expressions?
   190      */
   191     boolean allowLambda;
   193     /** Switch: should we allow method/constructor references?
   194      */
   195     boolean allowMethodReferences;
   197     /** Switch: should we allow default methods in interfaces?
   198      */
   199     boolean allowDefaultMethods;
   201     /** Switch: should we allow intersection types in cast?
   202      */
   203     boolean allowIntersectionTypesInCast;
   205     /** Switch: should we keep docComments?
   206      */
   207     boolean keepDocComments;
   209     /** Switch: should we keep line table?
   210      */
   211     boolean keepLineMap;
   213     /** When terms are parsed, the mode determines which is expected:
   214      *     mode = EXPR        : an expression
   215      *     mode = TYPE        : a type
   216      *     mode = NOPARAMS    : no parameters allowed for type
   217      *     mode = TYPEARG     : type argument
   218      */
   219     static final int EXPR = 0x1;
   220     static final int TYPE = 0x2;
   221     static final int NOPARAMS = 0x4;
   222     static final int TYPEARG = 0x8;
   223     static final int DIAMOND = 0x10;
   225     /** The current mode.
   226      */
   227     private int mode = 0;
   229     /** The mode of the term that was parsed last.
   230      */
   231     private int lastmode = 0;
   233     /* ---------- token management -------------- */
   235     protected Token token;
   237     public Token token() {
   238         return token;
   239     }
   241     public void nextToken() {
   242         S.nextToken();
   243         token = S.token();
   244     }
   246     protected boolean peekToken(Filter<TokenKind> tk) {
   247         return peekToken(0, tk);
   248     }
   250     protected boolean peekToken(int lookahead, Filter<TokenKind> tk) {
   251         return tk.accepts(S.token(lookahead + 1).kind);
   252     }
   254     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   255         return peekToken(0, tk1, tk2);
   256     }
   258     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2) {
   259         return tk1.accepts(S.token(lookahead + 1).kind) &&
   260                 tk2.accepts(S.token(lookahead + 2).kind);
   261     }
   263     protected boolean peekToken(Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   264         return peekToken(0, tk1, tk2, tk3);
   265     }
   267     protected boolean peekToken(int lookahead, Filter<TokenKind> tk1, Filter<TokenKind> tk2, Filter<TokenKind> tk3) {
   268         return tk1.accepts(S.token(lookahead + 1).kind) &&
   269                 tk2.accepts(S.token(lookahead + 2).kind) &&
   270                 tk3.accepts(S.token(lookahead + 3).kind);
   271     }
   273     @SuppressWarnings("unchecked")
   274     protected boolean peekToken(Filter<TokenKind>... kinds) {
   275         return peekToken(0, kinds);
   276     }
   278     @SuppressWarnings("unchecked")
   279     protected boolean peekToken(int lookahead, Filter<TokenKind>... kinds) {
   280         for (; lookahead < kinds.length ; lookahead++) {
   281             if (!kinds[lookahead].accepts(S.token(lookahead + 1).kind)) {
   282                 return false;
   283             }
   284         }
   285         return true;
   286     }
   288     /* ---------- error recovery -------------- */
   290     private JCErroneous errorTree;
   292     /** Skip forward until a suitable stop token is found.
   293      */
   294     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   295          while (true) {
   296              switch (token.kind) {
   297                 case SEMI:
   298                     nextToken();
   299                     return;
   300                 case PUBLIC:
   301                 case FINAL:
   302                 case ABSTRACT:
   303                 case MONKEYS_AT:
   304                 case EOF:
   305                 case CLASS:
   306                 case INTERFACE:
   307                 case ENUM:
   308                     return;
   309                 case IMPORT:
   310                     if (stopAtImport)
   311                         return;
   312                     break;
   313                 case LBRACE:
   314                 case RBRACE:
   315                 case PRIVATE:
   316                 case PROTECTED:
   317                 case STATIC:
   318                 case TRANSIENT:
   319                 case NATIVE:
   320                 case VOLATILE:
   321                 case SYNCHRONIZED:
   322                 case STRICTFP:
   323                 case LT:
   324                 case BYTE:
   325                 case SHORT:
   326                 case CHAR:
   327                 case INT:
   328                 case LONG:
   329                 case FLOAT:
   330                 case DOUBLE:
   331                 case BOOLEAN:
   332                 case VOID:
   333                     if (stopAtMemberDecl)
   334                         return;
   335                     break;
   336                 case UNDERSCORE:
   337                 case IDENTIFIER:
   338                    if (stopAtIdentifier)
   339                         return;
   340                     break;
   341                 case CASE:
   342                 case DEFAULT:
   343                 case IF:
   344                 case FOR:
   345                 case WHILE:
   346                 case DO:
   347                 case TRY:
   348                 case SWITCH:
   349                 case RETURN:
   350                 case THROW:
   351                 case BREAK:
   352                 case CONTINUE:
   353                 case ELSE:
   354                 case FINALLY:
   355                 case CATCH:
   356                     if (stopAtStatement)
   357                         return;
   358                     break;
   359             }
   360             nextToken();
   361         }
   362     }
   364     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   365         return syntaxError(pos, List.<JCTree>nil(), key, args);
   366     }
   368     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   369         setErrorEndPos(pos);
   370         JCErroneous err = F.at(pos).Erroneous(errs);
   371         reportSyntaxError(err, key, (Object[])args);
   372         if (errs != null) {
   373             JCTree last = errs.last();
   374             if (last != null)
   375                 storeEnd(last, pos);
   376         }
   377         return toP(err);
   378     }
   380     private int errorPos = Position.NOPOS;
   382     /**
   383      * Report a syntax using the given the position parameter and arguments,
   384      * unless one was already reported at the same position.
   385      */
   386     private void reportSyntaxError(int pos, String key, Object... args) {
   387         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   388         reportSyntaxError(diag, key, args);
   389     }
   391     /**
   392      * Report a syntax error using the given DiagnosticPosition object and
   393      * arguments, unless one was already reported at the same position.
   394      */
   395     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   396         int pos = diagPos.getPreferredPosition();
   397         if (pos > S.errPos() || pos == Position.NOPOS) {
   398             if (token.kind == EOF) {
   399                 error(diagPos, "premature.eof");
   400             } else {
   401                 error(diagPos, key, args);
   402             }
   403         }
   404         S.errPos(pos);
   405         if (token.pos == errorPos)
   406             nextToken(); // guarantee progress
   407         errorPos = token.pos;
   408     }
   411     /** Generate a syntax error at current position unless one was already
   412      *  reported at the same position.
   413      */
   414     private JCErroneous syntaxError(String key) {
   415         return syntaxError(token.pos, key);
   416     }
   418     /** Generate a syntax error at current position unless one was
   419      *  already reported at the same position.
   420      */
   421     private JCErroneous syntaxError(String key, TokenKind arg) {
   422         return syntaxError(token.pos, key, arg);
   423     }
   425     /** If next input token matches given token, skip it, otherwise report
   426      *  an error.
   427      */
   428     public void accept(TokenKind tk) {
   429         if (token.kind == tk) {
   430             nextToken();
   431         } else {
   432             setErrorEndPos(token.pos);
   433             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   434         }
   435     }
   437     /** Report an illegal start of expression/type error at given position.
   438      */
   439     JCExpression illegal(int pos) {
   440         setErrorEndPos(pos);
   441         if ((mode & EXPR) != 0)
   442             return syntaxError(pos, "illegal.start.of.expr");
   443         else
   444             return syntaxError(pos, "illegal.start.of.type");
   446     }
   448     /** Report an illegal start of expression/type error at current position.
   449      */
   450     JCExpression illegal() {
   451         return illegal(token.pos);
   452     }
   454     /** Diagnose a modifier flag from the set, if any. */
   455     void checkNoMods(long mods) {
   456         if (mods != 0) {
   457             long lowestMod = mods & -mods;
   458             error(token.pos, "mod.not.allowed.here",
   459                       Flags.asFlagSet(lowestMod));
   460         }
   461     }
   463 /* ---------- doc comments --------- */
   465     /** A table to store all documentation comments
   466      *  indexed by the tree nodes they refer to.
   467      *  defined only if option flag keepDocComment is set.
   468      */
   469     private final DocCommentTable docComments;
   471     /** Make an entry into docComments hashtable,
   472      *  provided flag keepDocComments is set and given doc comment is non-null.
   473      *  @param tree   The tree to be used as index in the hashtable
   474      *  @param dc     The doc comment to associate with the tree, or null.
   475      */
   476     void attach(JCTree tree, Comment dc) {
   477         if (keepDocComments && dc != null) {
   478 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   479             docComments.putComment(tree, dc);
   480         }
   481     }
   483 /* -------- source positions ------- */
   485     private void setErrorEndPos(int errPos) {
   486         endPosTable.setErrorEndPos(errPos);
   487     }
   489     private void storeEnd(JCTree tree, int endpos) {
   490         endPosTable.storeEnd(tree, endpos);
   491     }
   493     private <T extends JCTree> T to(T t) {
   494         return endPosTable.to(t);
   495     }
   497     private <T extends JCTree> T toP(T t) {
   498         return endPosTable.toP(t);
   499     }
   501     /** Get the start position for a tree node.  The start position is
   502      * defined to be the position of the first character of the first
   503      * token of the node's source text.
   504      * @param tree  The tree node
   505      */
   506     public int getStartPos(JCTree tree) {
   507         return TreeInfo.getStartPos(tree);
   508     }
   510     /**
   511      * Get the end position for a tree node.  The end position is
   512      * defined to be the position of the last character of the last
   513      * token of the node's source text.  Returns Position.NOPOS if end
   514      * positions are not generated or the position is otherwise not
   515      * found.
   516      * @param tree  The tree node
   517      */
   518     public int getEndPos(JCTree tree) {
   519         return endPosTable.getEndPos(tree);
   520     }
   524 /* ---------- parsing -------------- */
   526     /**
   527      * Ident = IDENTIFIER
   528      */
   529     Name ident() {
   530         if (token.kind == IDENTIFIER) {
   531             Name name = token.name();
   532             nextToken();
   533             return name;
   534         } else if (token.kind == ASSERT) {
   535             if (allowAsserts) {
   536                 error(token.pos, "assert.as.identifier");
   537                 nextToken();
   538                 return names.error;
   539             } else {
   540                 warning(token.pos, "assert.as.identifier");
   541                 Name name = token.name();
   542                 nextToken();
   543                 return name;
   544             }
   545         } else if (token.kind == ENUM) {
   546             if (allowEnums) {
   547                 error(token.pos, "enum.as.identifier");
   548                 nextToken();
   549                 return names.error;
   550             } else {
   551                 warning(token.pos, "enum.as.identifier");
   552                 Name name = token.name();
   553                 nextToken();
   554                 return name;
   555             }
   556         } else if (token.kind == UNDERSCORE) {
   557             warning(token.pos, "underscore.as.identifier");
   558             Name name = token.name();
   559             nextToken();
   560             return name;
   561         } else {
   562             accept(IDENTIFIER);
   563             return names.error;
   564         }
   565     }
   567     /**
   568      * Qualident = Ident { DOT Ident }
   569      */
   570     public JCExpression qualident() {
   571         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   572         while (token.kind == DOT) {
   573             int pos = token.pos;
   574             nextToken();
   575             t = toP(F.at(pos).Select(t, ident()));
   576         }
   577         return t;
   578     }
   580     JCExpression literal(Name prefix) {
   581         return literal(prefix, token.pos);
   582     }
   584     /**
   585      * Literal =
   586      *     INTLITERAL
   587      *   | LONGLITERAL
   588      *   | FLOATLITERAL
   589      *   | DOUBLELITERAL
   590      *   | CHARLITERAL
   591      *   | STRINGLITERAL
   592      *   | TRUE
   593      *   | FALSE
   594      *   | NULL
   595      */
   596     JCExpression literal(Name prefix, int pos) {
   597         JCExpression t = errorTree;
   598         switch (token.kind) {
   599         case INTLITERAL:
   600             try {
   601                 t = F.at(pos).Literal(
   602                     TypeTag.INT,
   603                     Convert.string2int(strval(prefix), token.radix()));
   604             } catch (NumberFormatException ex) {
   605                 error(token.pos, "int.number.too.large", strval(prefix));
   606             }
   607             break;
   608         case LONGLITERAL:
   609             try {
   610                 t = F.at(pos).Literal(
   611                     TypeTag.LONG,
   612                     new Long(Convert.string2long(strval(prefix), token.radix())));
   613             } catch (NumberFormatException ex) {
   614                 error(token.pos, "int.number.too.large", strval(prefix));
   615             }
   616             break;
   617         case FLOATLITERAL: {
   618             String proper = token.radix() == 16 ?
   619                     ("0x"+ token.stringVal()) :
   620                     token.stringVal();
   621             Float n;
   622             try {
   623                 n = Float.valueOf(proper);
   624             } catch (NumberFormatException ex) {
   625                 // error already reported in scanner
   626                 n = Float.NaN;
   627             }
   628             if (n.floatValue() == 0.0f && !isZero(proper))
   629                 error(token.pos, "fp.number.too.small");
   630             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   631                 error(token.pos, "fp.number.too.large");
   632             else
   633                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
   634             break;
   635         }
   636         case DOUBLELITERAL: {
   637             String proper = token.radix() == 16 ?
   638                     ("0x"+ token.stringVal()) :
   639                     token.stringVal();
   640             Double n;
   641             try {
   642                 n = Double.valueOf(proper);
   643             } catch (NumberFormatException ex) {
   644                 // error already reported in scanner
   645                 n = Double.NaN;
   646             }
   647             if (n.doubleValue() == 0.0d && !isZero(proper))
   648                 error(token.pos, "fp.number.too.small");
   649             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   650                 error(token.pos, "fp.number.too.large");
   651             else
   652                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
   653             break;
   654         }
   655         case CHARLITERAL:
   656             t = F.at(pos).Literal(
   657                 TypeTag.CHAR,
   658                 token.stringVal().charAt(0) + 0);
   659             break;
   660         case STRINGLITERAL:
   661             t = F.at(pos).Literal(
   662                 TypeTag.CLASS,
   663                 token.stringVal());
   664             break;
   665         case TRUE: case FALSE:
   666             t = F.at(pos).Literal(
   667                 TypeTag.BOOLEAN,
   668                 (token.kind == TRUE ? 1 : 0));
   669             break;
   670         case NULL:
   671             t = F.at(pos).Literal(
   672                 TypeTag.BOT,
   673                 null);
   674             break;
   675         default:
   676             Assert.error();
   677         }
   678         if (t == errorTree)
   679             t = F.at(pos).Erroneous();
   680         storeEnd(t, token.endPos);
   681         nextToken();
   682         return t;
   683     }
   684 //where
   685         boolean isZero(String s) {
   686             char[] cs = s.toCharArray();
   687             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   688             int i = ((base==16) ? 2 : 0);
   689             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   690             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   691         }
   693         String strval(Name prefix) {
   694             String s = token.stringVal();
   695             return prefix.isEmpty() ? s : prefix + s;
   696         }
   698     /** terms can be either expressions or types.
   699      */
   700     public JCExpression parseExpression() {
   701         return term(EXPR);
   702     }
   704     public JCExpression parseType() {
   705         return term(TYPE);
   706     }
   708     JCExpression term(int newmode) {
   709         int prevmode = mode;
   710         mode = newmode;
   711         JCExpression t = term();
   712         lastmode = mode;
   713         mode = prevmode;
   714         return t;
   715     }
   717     /**
   718      *  {@literal
   719      *  Expression = Expression1 [ExpressionRest]
   720      *  ExpressionRest = [AssignmentOperator Expression1]
   721      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   722      *                       "&=" | "|=" | "^=" |
   723      *                       "%=" | "<<=" | ">>=" | ">>>="
   724      *  Type = Type1
   725      *  TypeNoParams = TypeNoParams1
   726      *  StatementExpression = Expression
   727      *  ConstantExpression = Expression
   728      *  }
   729      */
   730     JCExpression term() {
   731         JCExpression t = term1();
   732         if ((mode & EXPR) != 0 &&
   733             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   734             return termRest(t);
   735         else
   736             return t;
   737     }
   739     JCExpression termRest(JCExpression t) {
   740         switch (token.kind) {
   741         case EQ: {
   742             int pos = token.pos;
   743             nextToken();
   744             mode = EXPR;
   745             JCExpression t1 = term();
   746             return toP(F.at(pos).Assign(t, t1));
   747         }
   748         case PLUSEQ:
   749         case SUBEQ:
   750         case STAREQ:
   751         case SLASHEQ:
   752         case PERCENTEQ:
   753         case AMPEQ:
   754         case BAREQ:
   755         case CARETEQ:
   756         case LTLTEQ:
   757         case GTGTEQ:
   758         case GTGTGTEQ:
   759             int pos = token.pos;
   760             TokenKind tk = token.kind;
   761             nextToken();
   762             mode = EXPR;
   763             JCExpression t1 = term();
   764             return F.at(pos).Assignop(optag(tk), t, t1);
   765         default:
   766             return t;
   767         }
   768     }
   770     /** Expression1   = Expression2 [Expression1Rest]
   771      *  Type1         = Type2
   772      *  TypeNoParams1 = TypeNoParams2
   773      */
   774     JCExpression term1() {
   775         JCExpression t = term2();
   776         if ((mode & EXPR) != 0 && token.kind == QUES) {
   777             mode = EXPR;
   778             return term1Rest(t);
   779         } else {
   780             return t;
   781         }
   782     }
   784     /** Expression1Rest = ["?" Expression ":" Expression1]
   785      */
   786     JCExpression term1Rest(JCExpression t) {
   787         if (token.kind == QUES) {
   788             int pos = token.pos;
   789             nextToken();
   790             JCExpression t1 = term();
   791             accept(COLON);
   792             JCExpression t2 = term1();
   793             return F.at(pos).Conditional(t, t1, t2);
   794         } else {
   795             return t;
   796         }
   797     }
   799     /** Expression2   = Expression3 [Expression2Rest]
   800      *  Type2         = Type3
   801      *  TypeNoParams2 = TypeNoParams3
   802      */
   803     JCExpression term2() {
   804         JCExpression t = term3();
   805         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   806             mode = EXPR;
   807             return term2Rest(t, TreeInfo.orPrec);
   808         } else {
   809             return t;
   810         }
   811     }
   813     /*  Expression2Rest = {infixop Expression3}
   814      *                  | Expression3 instanceof Type
   815      *  infixop         = "||"
   816      *                  | "&&"
   817      *                  | "|"
   818      *                  | "^"
   819      *                  | "&"
   820      *                  | "==" | "!="
   821      *                  | "<" | ">" | "<=" | ">="
   822      *                  | "<<" | ">>" | ">>>"
   823      *                  | "+" | "-"
   824      *                  | "*" | "/" | "%"
   825      */
   826     JCExpression term2Rest(JCExpression t, int minprec) {
   827         JCExpression[] odStack = newOdStack();
   828         Token[] opStack = newOpStack();
   830         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   831         int top = 0;
   832         odStack[0] = t;
   833         int startPos = token.pos;
   834         Token topOp = Tokens.DUMMY;
   835         while (prec(token.kind) >= minprec) {
   836             opStack[top] = topOp;
   837             top++;
   838             topOp = token;
   839             nextToken();
   840             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   841             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   842                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   843                                         odStack[top]);
   844                 top--;
   845                 topOp = opStack[top];
   846             }
   847         }
   848         Assert.check(top == 0);
   849         t = odStack[0];
   851         if (t.hasTag(JCTree.Tag.PLUS)) {
   852             StringBuilder buf = foldStrings(t);
   853             if (buf != null) {
   854                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
   855             }
   856         }
   858         odStackSupply.add(odStack);
   859         opStackSupply.add(opStack);
   860         return t;
   861     }
   862 //where
   863         /** Construct a binary or type test node.
   864          */
   865         private JCExpression makeOp(int pos,
   866                                     TokenKind topOp,
   867                                     JCExpression od1,
   868                                     JCExpression od2)
   869         {
   870             if (topOp == INSTANCEOF) {
   871                 return F.at(pos).TypeTest(od1, od2);
   872             } else {
   873                 return F.at(pos).Binary(optag(topOp), od1, od2);
   874             }
   875         }
   876         /** If tree is a concatenation of string literals, replace it
   877          *  by a single literal representing the concatenated string.
   878          */
   879         protected StringBuilder foldStrings(JCTree tree) {
   880             if (!allowStringFolding)
   881                 return null;
   882             List<String> buf = List.nil();
   883             while (true) {
   884                 if (tree.hasTag(LITERAL)) {
   885                     JCLiteral lit = (JCLiteral) tree;
   886                     if (lit.typetag == TypeTag.CLASS) {
   887                         StringBuilder sbuf =
   888                             new StringBuilder((String)lit.value);
   889                         while (buf.nonEmpty()) {
   890                             sbuf.append(buf.head);
   891                             buf = buf.tail;
   892                         }
   893                         return sbuf;
   894                     }
   895                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   896                     JCBinary op = (JCBinary)tree;
   897                     if (op.rhs.hasTag(LITERAL)) {
   898                         JCLiteral lit = (JCLiteral) op.rhs;
   899                         if (lit.typetag == TypeTag.CLASS) {
   900                             buf = buf.prepend((String) lit.value);
   901                             tree = op.lhs;
   902                             continue;
   903                         }
   904                     }
   905                 }
   906                 return null;
   907             }
   908         }
   910         /** optimization: To save allocating a new operand/operator stack
   911          *  for every binary operation, we use supplys.
   912          */
   913         ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>();
   914         ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>();
   916         private JCExpression[] newOdStack() {
   917             if (odStackSupply.isEmpty())
   918                 return new JCExpression[infixPrecedenceLevels + 1];
   919             return odStackSupply.remove(odStackSupply.size() - 1);
   920         }
   922         private Token[] newOpStack() {
   923             if (opStackSupply.isEmpty())
   924                 return new Token[infixPrecedenceLevels + 1];
   925             return opStackSupply.remove(opStackSupply.size() - 1);
   926         }
   928     /**
   929      *  Expression3    = PrefixOp Expression3
   930      *                 | "(" Expr | TypeNoParams ")" Expression3
   931      *                 | Primary {Selector} {PostfixOp}
   932      *
   933      *  {@literal
   934      *  Primary        = "(" Expression ")"
   935      *                 | Literal
   936      *                 | [TypeArguments] THIS [Arguments]
   937      *                 | [TypeArguments] SUPER SuperSuffix
   938      *                 | NEW [TypeArguments] Creator
   939      *                 | "(" Arguments ")" "->" ( Expression | Block )
   940      *                 | Ident "->" ( Expression | Block )
   941      *                 | Ident { "." Ident }
   942      *                 | Expression3 MemberReferenceSuffix
   943      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   944      *                   | Arguments
   945      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   946      *                   ]
   947      *                 | BasicType BracketsOpt "." CLASS
   948      *  }
   949      *
   950      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   951      *  PostfixOp      = "++" | "--"
   952      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   953      *                 | BasicType
   954      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   955      *  Selector       = "." [TypeArguments] Ident [Arguments]
   956      *                 | "." THIS
   957      *                 | "." [TypeArguments] SUPER SuperSuffix
   958      *                 | "." NEW [TypeArguments] InnerCreator
   959      *                 | "[" Expression "]"
   960      *  TypeSelector   = "." Ident [TypeArguments]
   961      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   962      */
   963     protected JCExpression term3() {
   964         int pos = token.pos;
   965         JCExpression t;
   966         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   967         switch (token.kind) {
   968         case QUES:
   969             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   970                 mode = TYPE;
   971                 return typeArgument();
   972             } else
   973                 return illegal();
   974         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   975             if (typeArgs == null && (mode & EXPR) != 0) {
   976                 TokenKind tk = token.kind;
   977                 nextToken();
   978                 mode = EXPR;
   979                 if (tk == SUB &&
   980                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
   981                     token.radix() == 10) {
   982                     mode = EXPR;
   983                     t = literal(names.hyphen, pos);
   984                 } else {
   985                     t = term3();
   986                     return F.at(pos).Unary(unoptag(tk), t);
   987                 }
   988             } else return illegal();
   989             break;
   990         case LPAREN:
   991             if (typeArgs == null && (mode & EXPR) != 0) {
   992                 ParensResult pres = analyzeParens();
   993                 switch (pres) {
   994                     case CAST:
   995                        accept(LPAREN);
   996                        mode = TYPE;
   997                        int pos1 = pos;
   998                        List<JCExpression> targets = List.of(t = term3());
   999                        while (token.kind == AMP) {
  1000                            checkIntersectionTypesInCast();
  1001                            accept(AMP);
  1002                            targets = targets.prepend(term3());
  1004                        if (targets.length() > 1) {
  1005                            t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
  1007                        accept(RPAREN);
  1008                        mode = EXPR;
  1009                        JCExpression t1 = term3();
  1010                        return F.at(pos).TypeCast(t, t1);
  1011                     case IMPLICIT_LAMBDA:
  1012                     case EXPLICIT_LAMBDA:
  1013                         t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
  1014                         break;
  1015                     default: //PARENS
  1016                         accept(LPAREN);
  1017                         mode = EXPR;
  1018                         t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
  1019                         accept(RPAREN);
  1020                         t = toP(F.at(pos).Parens(t));
  1021                         break;
  1023             } else {
  1024                 return illegal();
  1026             break;
  1027         case THIS:
  1028             if ((mode & EXPR) != 0) {
  1029                 mode = EXPR;
  1030                 t = to(F.at(pos).Ident(names._this));
  1031                 nextToken();
  1032                 if (typeArgs == null)
  1033                     t = argumentsOpt(null, t);
  1034                 else
  1035                     t = arguments(typeArgs, t);
  1036                 typeArgs = null;
  1037             } else return illegal();
  1038             break;
  1039         case SUPER:
  1040             if ((mode & EXPR) != 0) {
  1041                 mode = EXPR;
  1042                 t = to(F.at(pos).Ident(names._super));
  1043                 t = superSuffix(typeArgs, t);
  1044                 typeArgs = null;
  1045             } else return illegal();
  1046             break;
  1047         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1048         case CHARLITERAL: case STRINGLITERAL:
  1049         case TRUE: case FALSE: case NULL:
  1050             if (typeArgs == null && (mode & EXPR) != 0) {
  1051                 mode = EXPR;
  1052                 t = literal(names.empty);
  1053             } else return illegal();
  1054             break;
  1055         case NEW:
  1056             if (typeArgs != null) return illegal();
  1057             if ((mode & EXPR) != 0) {
  1058                 mode = EXPR;
  1059                 nextToken();
  1060                 if (token.kind == LT) typeArgs = typeArguments(false);
  1061                 t = creator(pos, typeArgs);
  1062                 typeArgs = null;
  1063             } else return illegal();
  1064             break;
  1065         case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
  1066             if (typeArgs != null) return illegal();
  1067             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1068                 t = lambdaExpressionOrStatement(false, false, pos);
  1069             } else {
  1070                 t = toP(F.at(token.pos).Ident(ident()));
  1071                 loop: while (true) {
  1072                     pos = token.pos;
  1073                     switch (token.kind) {
  1074                     case LBRACKET:
  1075                         nextToken();
  1076                         if (token.kind == RBRACKET) {
  1077                             nextToken();
  1078                             t = bracketsOpt(t);
  1079                             t = toP(F.at(pos).TypeArray(t));
  1080                             t = bracketsSuffix(t);
  1081                         } else {
  1082                             if ((mode & EXPR) != 0) {
  1083                                 mode = EXPR;
  1084                                 JCExpression t1 = term();
  1085                                 t = to(F.at(pos).Indexed(t, t1));
  1087                             accept(RBRACKET);
  1089                         break loop;
  1090                     case LPAREN:
  1091                         if ((mode & EXPR) != 0) {
  1092                             mode = EXPR;
  1093                             t = arguments(typeArgs, t);
  1094                             typeArgs = null;
  1096                         break loop;
  1097                     case DOT:
  1098                         nextToken();
  1099                         int oldmode = mode;
  1100                         mode &= ~NOPARAMS;
  1101                         typeArgs = typeArgumentsOpt(EXPR);
  1102                         mode = oldmode;
  1103                         if ((mode & EXPR) != 0) {
  1104                             switch (token.kind) {
  1105                             case CLASS:
  1106                                 if (typeArgs != null) return illegal();
  1107                                 mode = EXPR;
  1108                                 t = to(F.at(pos).Select(t, names._class));
  1109                                 nextToken();
  1110                                 break loop;
  1111                             case THIS:
  1112                                 if (typeArgs != null) return illegal();
  1113                                 mode = EXPR;
  1114                                 t = to(F.at(pos).Select(t, names._this));
  1115                                 nextToken();
  1116                                 break loop;
  1117                             case SUPER:
  1118                                 mode = EXPR;
  1119                                 t = to(F.at(pos).Select(t, names._super));
  1120                                 t = superSuffix(typeArgs, t);
  1121                                 typeArgs = null;
  1122                                 break loop;
  1123                             case NEW:
  1124                                 if (typeArgs != null) return illegal();
  1125                                 mode = EXPR;
  1126                                 int pos1 = token.pos;
  1127                                 nextToken();
  1128                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1129                                 t = innerCreator(pos1, typeArgs, t);
  1130                                 typeArgs = null;
  1131                                 break loop;
  1134                         // typeArgs saved for next loop iteration.
  1135                         t = toP(F.at(pos).Select(t, ident()));
  1136                         break;
  1137                     case LT:
  1138                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1139                             //this is an unbound method reference whose qualifier
  1140                             //is a generic type i.e. A<S>::m
  1141                             int pos1 = token.pos;
  1142                             accept(LT);
  1143                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1144                             args.append(typeArgument());
  1145                             while (token.kind == COMMA) {
  1146                                 nextToken();
  1147                                 args.append(typeArgument());
  1149                             accept(GT);
  1150                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1151                             checkGenerics();
  1152                             while (token.kind == DOT) {
  1153                                 nextToken();
  1154                                 mode = TYPE;
  1155                                 t = toP(F.at(token.pos).Select(t, ident()));
  1156                                 t = typeArgumentsOpt(t);
  1158                             t = bracketsOpt(t);
  1159                             if (token.kind != COLCOL) {
  1160                                 //method reference expected here
  1161                                 t = illegal();
  1163                             mode = EXPR;
  1164                             return term3Rest(t, typeArgs);
  1166                         break loop;
  1167                     default:
  1168                         break loop;
  1172             if (typeArgs != null) illegal();
  1173             t = typeArgumentsOpt(t);
  1174             break;
  1175         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1176         case DOUBLE: case BOOLEAN:
  1177             if (typeArgs != null) illegal();
  1178             t = bracketsSuffix(bracketsOpt(basicType()));
  1179             break;
  1180         case VOID:
  1181             if (typeArgs != null) illegal();
  1182             if ((mode & EXPR) != 0) {
  1183                 nextToken();
  1184                 if (token.kind == DOT) {
  1185                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
  1186                     t = bracketsSuffix(ti);
  1187                 } else {
  1188                     return illegal(pos);
  1190             } else {
  1191                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1192                 // a void type (like other primitive types) to the next phase.
  1193                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1194                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
  1195                 nextToken();
  1196                 return ti;
  1197                 //return illegal();
  1199             break;
  1200         default:
  1201             return illegal();
  1203         return term3Rest(t, typeArgs);
  1206     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1207         if (typeArgs != null) illegal();
  1208         while (true) {
  1209             int pos1 = token.pos;
  1210             if (token.kind == LBRACKET) {
  1211                 nextToken();
  1212                 if ((mode & TYPE) != 0) {
  1213                     int oldmode = mode;
  1214                     mode = TYPE;
  1215                     if (token.kind == RBRACKET) {
  1216                         nextToken();
  1217                         t = bracketsOpt(t);
  1218                         t = toP(F.at(pos1).TypeArray(t));
  1219                         if (token.kind == COLCOL) {
  1220                             mode = EXPR;
  1221                             continue;
  1223                         return t;
  1225                     mode = oldmode;
  1227                 if ((mode & EXPR) != 0) {
  1228                     mode = EXPR;
  1229                     JCExpression t1 = term();
  1230                     t = to(F.at(pos1).Indexed(t, t1));
  1232                 accept(RBRACKET);
  1233             } else if (token.kind == DOT) {
  1234                 nextToken();
  1235                 typeArgs = typeArgumentsOpt(EXPR);
  1236                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1237                     mode = EXPR;
  1238                     t = to(F.at(pos1).Select(t, names._super));
  1239                     nextToken();
  1240                     t = arguments(typeArgs, t);
  1241                     typeArgs = null;
  1242                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1243                     if (typeArgs != null) return illegal();
  1244                     mode = EXPR;
  1245                     int pos2 = token.pos;
  1246                     nextToken();
  1247                     if (token.kind == LT) typeArgs = typeArguments(false);
  1248                     t = innerCreator(pos2, typeArgs, t);
  1249                     typeArgs = null;
  1250                 } else {
  1251                     t = toP(F.at(pos1).Select(t, ident()));
  1252                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1253                     typeArgs = null;
  1255             } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
  1256                 mode = EXPR;
  1257                 if (typeArgs != null) return illegal();
  1258                 accept(COLCOL);
  1259                 t = memberReferenceSuffix(pos1, t);
  1260             } else {
  1261                 break;
  1264         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1265             mode = EXPR;
  1266             t = to(F.at(token.pos).Unary(
  1267                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1268             nextToken();
  1270         return toP(t);
  1273     /**
  1274      * If we see an identifier followed by a '&lt;' it could be an unbound
  1275      * method reference or a binary expression. To disambiguate, look for a
  1276      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1277      */
  1278     @SuppressWarnings("fallthrough")
  1279     boolean isUnboundMemberRef() {
  1280         int pos = 0, depth = 0;
  1281         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1282             switch (t.kind) {
  1283                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
  1284                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1285                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1286                 case DOUBLE: case BOOLEAN: case CHAR:
  1287                     break;
  1288                 case LT:
  1289                     depth++; break;
  1290                 case GTGTGT:
  1291                     depth--;
  1292                 case GTGT:
  1293                     depth--;
  1294                 case GT:
  1295                     depth--;
  1296                     if (depth == 0) {
  1297                         TokenKind nextKind = S.token(pos + 1).kind;
  1298                         return
  1299                             nextKind == TokenKind.DOT ||
  1300                             nextKind == TokenKind.LBRACKET ||
  1301                             nextKind == TokenKind.COLCOL;
  1303                     break;
  1304                 default:
  1305                     return false;
  1310     /**
  1311      * If we see an identifier followed by a '&lt;' it could be an unbound
  1312      * method reference or a binary expression. To disambiguate, look for a
  1313      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1314      */
  1315     @SuppressWarnings("fallthrough")
  1316     ParensResult analyzeParens() {
  1317         int depth = 0;
  1318         boolean type = false;
  1319         for (int lookahead = 0 ; ; lookahead++) {
  1320             TokenKind tk = S.token(lookahead).kind;
  1321             switch (tk) {
  1322                 case EXTENDS: case SUPER: case COMMA:
  1323                     type = true;
  1324                 case QUES: case DOT: case AMP:
  1325                     //skip
  1326                     break;
  1327                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1328                 case DOUBLE: case BOOLEAN: case CHAR:
  1329                     if (peekToken(lookahead, RPAREN)) {
  1330                         //Type, ')' -> cast
  1331                         return ParensResult.CAST;
  1332                     } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1333                         //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1334                         return ParensResult.EXPLICIT_LAMBDA;
  1336                     break;
  1337                 case LPAREN:
  1338                     if (lookahead != 0) {
  1339                         // '(' in a non-starting position -> parens
  1340                         return ParensResult.PARENS;
  1341                     } else if (peekToken(lookahead, RPAREN)) {
  1342                         // '(', ')' -> explicit lambda
  1343                         return ParensResult.EXPLICIT_LAMBDA;
  1345                     break;
  1346                 case RPAREN:
  1347                     // if we have seen something that looks like a type,
  1348                     // then it's a cast expression
  1349                     if (type) return ParensResult.CAST;
  1350                     // otherwise, disambiguate cast vs. parenthesized expression
  1351                     // based on subsequent token.
  1352                     switch (S.token(lookahead + 1).kind) {
  1353                         /*case PLUSPLUS: case SUBSUB: */
  1354                         case BANG: case TILDE:
  1355                         case LPAREN: case THIS: case SUPER:
  1356                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1357                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1358                         case TRUE: case FALSE: case NULL:
  1359                         case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
  1360                         case BYTE: case SHORT: case CHAR: case INT:
  1361                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1362                             return ParensResult.CAST;
  1363                         default:
  1364                             return ParensResult.PARENS;
  1366                 case UNDERSCORE:
  1367                 case ASSERT:
  1368                 case ENUM:
  1369                 case IDENTIFIER:
  1370                     if (peekToken(lookahead, LAX_IDENTIFIER)) {
  1371                         // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
  1372                         return ParensResult.EXPLICIT_LAMBDA;
  1373                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
  1374                         // Identifier, ')' '->' -> implicit lambda
  1375                         return ParensResult.IMPLICIT_LAMBDA;
  1377                     break;
  1378                 case FINAL:
  1379                 case ELLIPSIS:
  1380                 case MONKEYS_AT:
  1381                     //those can only appear in explicit lambdas
  1382                     return ParensResult.EXPLICIT_LAMBDA;
  1383                 case LBRACKET:
  1384                     if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
  1385                         // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
  1386                         return ParensResult.EXPLICIT_LAMBDA;
  1387                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
  1388                             peekToken(lookahead, RBRACKET, AMP)) {
  1389                         // '[', ']', ')' -> cast
  1390                         // '[', ']', '&' -> cast (intersection type)
  1391                         return ParensResult.CAST;
  1392                     } else if (peekToken(lookahead, RBRACKET)) {
  1393                         //consume the ']' and skip
  1394                         type = true;
  1395                         lookahead++;
  1396                         break;
  1397                     } else {
  1398                         return ParensResult.PARENS;
  1400                 case LT:
  1401                     depth++; break;
  1402                 case GTGTGT:
  1403                     depth--;
  1404                 case GTGT:
  1405                     depth--;
  1406                 case GT:
  1407                     depth--;
  1408                     if (depth == 0) {
  1409                         if (peekToken(lookahead, RPAREN) ||
  1410                                 peekToken(lookahead, AMP)) {
  1411                             // '>', ')' -> cast
  1412                             // '>', '&' -> cast
  1413                             return ParensResult.CAST;
  1414                         } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
  1415                                 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
  1416                                 peekToken(lookahead, ELLIPSIS)) {
  1417                             // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
  1418                             // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
  1419                             // '>', '...' -> explicit lambda
  1420                             return ParensResult.EXPLICIT_LAMBDA;
  1422                         //it looks a type, but could still be (i) a cast to generic type,
  1423                         //(ii) an unbound method reference or (iii) an explicit lambda
  1424                         type = true;
  1425                         break;
  1426                     } else if (depth < 0) {
  1427                         //unbalanced '<', '>' - not a generic type
  1428                         return ParensResult.PARENS;
  1430                     break;
  1431                 default:
  1432                     //this includes EOF
  1433                     return ParensResult.PARENS;
  1438     /** Accepts all identifier-like tokens */
  1439     Filter<TokenKind> LAX_IDENTIFIER = new Filter<TokenKind>() {
  1440         public boolean accepts(TokenKind t) {
  1441             return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
  1443     };
  1445     enum ParensResult {
  1446         CAST,
  1447         EXPLICIT_LAMBDA,
  1448         IMPLICIT_LAMBDA,
  1449         PARENS;
  1452     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1453         List<JCVariableDecl> params = explicitParams ?
  1454                 formalParameters(true) :
  1455                 implicitParameters(hasParens);
  1457         return lambdaExpressionOrStatementRest(params, pos);
  1460     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1461         checkLambda();
  1462         accept(ARROW);
  1464         return token.kind == LBRACE ?
  1465             lambdaStatement(args, pos, pos) :
  1466             lambdaExpression(args, pos);
  1469     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1470         JCBlock block = block(pos2, 0);
  1471         return toP(F.at(pos).Lambda(args, block));
  1474     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1475         JCTree expr = parseExpression();
  1476         return toP(F.at(pos).Lambda(args, expr));
  1479     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1480      */
  1481     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1482         nextToken();
  1483         if (token.kind == LPAREN || typeArgs != null) {
  1484             t = arguments(typeArgs, t);
  1485         } else if (token.kind == COLCOL) {
  1486             if (typeArgs != null) return illegal();
  1487             t = memberReferenceSuffix(t);
  1488         } else {
  1489             int pos = token.pos;
  1490             accept(DOT);
  1491             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1492             t = toP(F.at(pos).Select(t, ident()));
  1493             t = argumentsOpt(typeArgs, t);
  1495         return t;
  1498     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1499      */
  1500     JCPrimitiveTypeTree basicType() {
  1501         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1502         nextToken();
  1503         return t;
  1506     /** ArgumentsOpt = [ Arguments ]
  1507      */
  1508     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1509         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1510             mode = EXPR;
  1511             return arguments(typeArgs, t);
  1512         } else {
  1513             return t;
  1517     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1518      */
  1519     List<JCExpression> arguments() {
  1520         ListBuffer<JCExpression> args = lb();
  1521         if (token.kind == LPAREN) {
  1522             nextToken();
  1523             if (token.kind != RPAREN) {
  1524                 args.append(parseExpression());
  1525                 while (token.kind == COMMA) {
  1526                     nextToken();
  1527                     args.append(parseExpression());
  1530             accept(RPAREN);
  1531         } else {
  1532             syntaxError(token.pos, "expected", LPAREN);
  1534         return args.toList();
  1537     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1538         int pos = token.pos;
  1539         List<JCExpression> args = arguments();
  1540         return toP(F.at(pos).Apply(typeArgs, t, args));
  1543     /**  TypeArgumentsOpt = [ TypeArguments ]
  1544      */
  1545     JCExpression typeArgumentsOpt(JCExpression t) {
  1546         if (token.kind == LT &&
  1547             (mode & TYPE) != 0 &&
  1548             (mode & NOPARAMS) == 0) {
  1549             mode = TYPE;
  1550             checkGenerics();
  1551             return typeArguments(t, false);
  1552         } else {
  1553             return t;
  1556     List<JCExpression> typeArgumentsOpt() {
  1557         return typeArgumentsOpt(TYPE);
  1560     List<JCExpression> typeArgumentsOpt(int useMode) {
  1561         if (token.kind == LT) {
  1562             checkGenerics();
  1563             if ((mode & useMode) == 0 ||
  1564                 (mode & NOPARAMS) != 0) {
  1565                 illegal();
  1567             mode = useMode;
  1568             return typeArguments(false);
  1570         return null;
  1573     /**
  1574      *  {@literal
  1575      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1576      *  }
  1577      */
  1578     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1579         if (token.kind == LT) {
  1580             nextToken();
  1581             if (token.kind == GT && diamondAllowed) {
  1582                 checkDiamond();
  1583                 mode |= DIAMOND;
  1584                 nextToken();
  1585                 return List.nil();
  1586             } else {
  1587                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1588                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1589                 while (token.kind == COMMA) {
  1590                     nextToken();
  1591                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1593                 switch (token.kind) {
  1595                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1596                 case GTGTGT: case GTGT:
  1597                     token = S.split();
  1598                     break;
  1599                 case GT:
  1600                     nextToken();
  1601                     break;
  1602                 default:
  1603                     args.append(syntaxError(token.pos, "expected", GT));
  1604                     break;
  1606                 return args.toList();
  1608         } else {
  1609             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1613     /**
  1614      *  {@literal
  1615      *  TypeArgument = Type
  1616      *               | "?"
  1617      *               | "?" EXTENDS Type {"&" Type}
  1618      *               | "?" SUPER Type
  1619      *  }
  1620      */
  1621     JCExpression typeArgument() {
  1622         if (token.kind != QUES) return parseType();
  1623         int pos = token.pos;
  1624         nextToken();
  1625         if (token.kind == EXTENDS) {
  1626             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1627             nextToken();
  1628             JCExpression bound = parseType();
  1629             return F.at(pos).Wildcard(t, bound);
  1630         } else if (token.kind == SUPER) {
  1631             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1632             nextToken();
  1633             JCExpression bound = parseType();
  1634             return F.at(pos).Wildcard(t, bound);
  1635         } else if (LAX_IDENTIFIER.accepts(token.kind)) {
  1636             //error recovery
  1637             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1638             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1639             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1640             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1641             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1642             return err;
  1643         } else {
  1644             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1645             return toP(F.at(pos).Wildcard(t, null));
  1649     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1650         int pos = token.pos;
  1651         List<JCExpression> args = typeArguments(diamondAllowed);
  1652         return toP(F.at(pos).TypeApply(t, args));
  1655     /** BracketsOpt = {"[" "]"}
  1656      */
  1657     private JCExpression bracketsOpt(JCExpression t) {
  1658         if (token.kind == LBRACKET) {
  1659             int pos = token.pos;
  1660             nextToken();
  1661             t = bracketsOptCont(t, pos);
  1662             F.at(pos);
  1664         return t;
  1667     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1668         accept(RBRACKET);
  1669         t = bracketsOpt(t);
  1670         return toP(F.at(pos).TypeArray(t));
  1673     /** BracketsSuffixExpr = "." CLASS
  1674      *  BracketsSuffixType =
  1675      */
  1676     JCExpression bracketsSuffix(JCExpression t) {
  1677         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1678             mode = EXPR;
  1679             int pos = token.pos;
  1680             nextToken();
  1681             accept(CLASS);
  1682             if (token.pos == endPosTable.errorEndPos) {
  1683                 // error recovery
  1684                 Name name = null;
  1685                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  1686                     name = token.name();
  1687                     nextToken();
  1688                 } else {
  1689                     name = names.error;
  1691                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1692             } else {
  1693                 t = toP(F.at(pos).Select(t, names._class));
  1695         } else if ((mode & TYPE) != 0) {
  1696             if (token.kind != COLCOL) {
  1697                 mode = TYPE;
  1699         } else if (token.kind != COLCOL) {
  1700             syntaxError(token.pos, "dot.class.expected");
  1702         return t;
  1705     /**
  1706      * MemberReferenceSuffix = "::" [TypeArguments] Ident
  1707      *                       | "::" [TypeArguments] "new"
  1708      */
  1709     JCExpression memberReferenceSuffix(JCExpression t) {
  1710         int pos1 = token.pos;
  1711         accept(COLCOL);
  1712         return memberReferenceSuffix(pos1, t);
  1715     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1716         checkMethodReferences();
  1717         mode = EXPR;
  1718         List<JCExpression> typeArgs = null;
  1719         if (token.kind == LT) {
  1720             typeArgs = typeArguments(false);
  1722         Name refName = null;
  1723         ReferenceMode refMode = null;
  1724         if (token.kind == NEW) {
  1725             refMode = ReferenceMode.NEW;
  1726             refName = names.init;
  1727             nextToken();
  1728         } else {
  1729             refMode = ReferenceMode.INVOKE;
  1730             refName = ident();
  1732         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  1735     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1736      */
  1737     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1738         switch (token.kind) {
  1739         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1740         case DOUBLE: case BOOLEAN:
  1741             if (typeArgs == null)
  1742                 return arrayCreatorRest(newpos, basicType());
  1743             break;
  1744         default:
  1746         JCExpression t = qualident();
  1747         int oldmode = mode;
  1748         mode = TYPE;
  1749         boolean diamondFound = false;
  1750         int lastTypeargsPos = -1;
  1751         if (token.kind == LT) {
  1752             checkGenerics();
  1753             lastTypeargsPos = token.pos;
  1754             t = typeArguments(t, true);
  1755             diamondFound = (mode & DIAMOND) != 0;
  1757         while (token.kind == DOT) {
  1758             if (diamondFound) {
  1759                 //cannot select after a diamond
  1760                 illegal();
  1762             int pos = token.pos;
  1763             nextToken();
  1764             t = toP(F.at(pos).Select(t, ident()));
  1765             if (token.kind == LT) {
  1766                 lastTypeargsPos = token.pos;
  1767                 checkGenerics();
  1768                 t = typeArguments(t, true);
  1769                 diamondFound = (mode & DIAMOND) != 0;
  1772         mode = oldmode;
  1773         if (token.kind == LBRACKET) {
  1774             JCExpression e = arrayCreatorRest(newpos, t);
  1775             if (diamondFound) {
  1776                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1777                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1779             else if (typeArgs != null) {
  1780                 int pos = newpos;
  1781                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1782                     // note: this should always happen but we should
  1783                     // not rely on this as the parser is continuously
  1784                     // modified to improve error recovery.
  1785                     pos = typeArgs.head.pos;
  1787                 setErrorEndPos(S.prevToken().endPos);
  1788                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1789                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1790                 return toP(err);
  1792             return e;
  1793         } else if (token.kind == LPAREN) {
  1794             return classCreatorRest(newpos, null, typeArgs, t);
  1795         } else {
  1796             setErrorEndPos(token.pos);
  1797             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1798             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1799             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1803     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1804      */
  1805     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1806         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1807         if (token.kind == LT) {
  1808             int oldmode = mode;
  1809             checkGenerics();
  1810             t = typeArguments(t, true);
  1811             mode = oldmode;
  1813         return classCreatorRest(newpos, encl, typeArgs, t);
  1816     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1817      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1818      */
  1819     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1820         accept(LBRACKET);
  1821         if (token.kind == RBRACKET) {
  1822             accept(RBRACKET);
  1823             elemtype = bracketsOpt(elemtype);
  1824             if (token.kind == LBRACE) {
  1825                 return arrayInitializer(newpos, elemtype);
  1826             } else {
  1827                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1828                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1830         } else {
  1831             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1832             dims.append(parseExpression());
  1833             accept(RBRACKET);
  1834             while (token.kind == LBRACKET) {
  1835                 int pos = token.pos;
  1836                 nextToken();
  1837                 if (token.kind == RBRACKET) {
  1838                     elemtype = bracketsOptCont(elemtype, pos);
  1839                 } else {
  1840                     dims.append(parseExpression());
  1841                     accept(RBRACKET);
  1844             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1848     /** ClassCreatorRest = Arguments [ClassBody]
  1849      */
  1850     JCNewClass classCreatorRest(int newpos,
  1851                                   JCExpression encl,
  1852                                   List<JCExpression> typeArgs,
  1853                                   JCExpression t)
  1855         List<JCExpression> args = arguments();
  1856         JCClassDecl body = null;
  1857         if (token.kind == LBRACE) {
  1858             int pos = token.pos;
  1859             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1860             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1861             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1863         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1866     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1867      */
  1868     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1869         accept(LBRACE);
  1870         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1871         if (token.kind == COMMA) {
  1872             nextToken();
  1873         } else if (token.kind != RBRACE) {
  1874             elems.append(variableInitializer());
  1875             while (token.kind == COMMA) {
  1876                 nextToken();
  1877                 if (token.kind == RBRACE) break;
  1878                 elems.append(variableInitializer());
  1881         accept(RBRACE);
  1882         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1885     /** VariableInitializer = ArrayInitializer | Expression
  1886      */
  1887     public JCExpression variableInitializer() {
  1888         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1891     /** ParExpression = "(" Expression ")"
  1892      */
  1893     JCExpression parExpression() {
  1894         int pos = token.pos;
  1895         accept(LPAREN);
  1896         JCExpression t = parseExpression();
  1897         accept(RPAREN);
  1898         return toP(F.at(pos).Parens(t));
  1901     /** Block = "{" BlockStatements "}"
  1902      */
  1903     JCBlock block(int pos, long flags) {
  1904         accept(LBRACE);
  1905         List<JCStatement> stats = blockStatements();
  1906         JCBlock t = F.at(pos).Block(flags, stats);
  1907         while (token.kind == CASE || token.kind == DEFAULT) {
  1908             syntaxError("orphaned", token.kind);
  1909             switchBlockStatementGroups();
  1911         // the Block node has a field "endpos" for first char of last token, which is
  1912         // usually but not necessarily the last char of the last token.
  1913         t.endpos = token.pos;
  1914         accept(RBRACE);
  1915         return toP(t);
  1918     public JCBlock block() {
  1919         return block(token.pos, 0);
  1922     /** BlockStatements = { BlockStatement }
  1923      *  BlockStatement  = LocalVariableDeclarationStatement
  1924      *                  | ClassOrInterfaceOrEnumDeclaration
  1925      *                  | [Ident ":"] Statement
  1926      *  LocalVariableDeclarationStatement
  1927      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1928      */
  1929     @SuppressWarnings("fallthrough")
  1930     List<JCStatement> blockStatements() {
  1931         //todo: skip to anchor on error(?)
  1932         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1933         while (true) {
  1934             List<JCStatement> stat = blockStatement();
  1935             if (stat.isEmpty()) {
  1936                 return stats.toList();
  1937             } else {
  1938                 if (token.pos <= endPosTable.errorEndPos) {
  1939                     skip(false, true, true, true);
  1941                 stats.addAll(stat);
  1946     /*
  1947      * This method parses a statement treating it as a block, relaxing the
  1948      * JLS restrictions, allows us to parse more faulty code, doing so
  1949      * enables us to provide better and accurate diagnostics to the user.
  1950      */
  1951     JCStatement parseStatementAsBlock() {
  1952         int pos = token.pos;
  1953         List<JCStatement> stats = blockStatement();
  1954         if (stats.isEmpty()) {
  1955             JCErroneous e = F.at(pos).Erroneous();
  1956             error(e, "illegal.start.of.stmt");
  1957             return F.at(pos).Exec(e);
  1958         } else {
  1959             JCStatement first = stats.head;
  1960             String error = null;
  1961             switch (first.getTag()) {
  1962             case CLASSDEF:
  1963                 error = "class.not.allowed";
  1964                 break;
  1965             case VARDEF:
  1966                 error = "variable.not.allowed";
  1967                 break;
  1969             if (error != null) {
  1970                 error(first, error);
  1971                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  1972                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  1974             return first;
  1978     @SuppressWarnings("fallthrough")
  1979     List<JCStatement> blockStatement() {
  1980         //todo: skip to anchor on error(?)
  1981         int pos = token.pos;
  1982         switch (token.kind) {
  1983         case RBRACE: case CASE: case DEFAULT: case EOF:
  1984             return List.nil();
  1985         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1986         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1987         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1988             return List.of(parseStatement());
  1989         case MONKEYS_AT:
  1990         case FINAL: {
  1991             Comment dc = token.comment(CommentStyle.JAVADOC);
  1992             JCModifiers mods = modifiersOpt();
  1993             if (token.kind == INTERFACE ||
  1994                 token.kind == CLASS ||
  1995                 allowEnums && token.kind == ENUM) {
  1996                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1997             } else {
  1998                 JCExpression t = parseType();
  1999                 ListBuffer<JCStatement> stats =
  2000                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2001                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2002                 storeEnd(stats.last(), token.endPos);
  2003                 accept(SEMI);
  2004                 return stats.toList();
  2007         case ABSTRACT: case STRICTFP: {
  2008             Comment dc = token.comment(CommentStyle.JAVADOC);
  2009             JCModifiers mods = modifiersOpt();
  2010             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2012         case INTERFACE:
  2013         case CLASS:
  2014             Comment dc = token.comment(CommentStyle.JAVADOC);
  2015             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2016         case ENUM:
  2017         case ASSERT:
  2018             if (allowEnums && token.kind == ENUM) {
  2019                 error(token.pos, "local.enum");
  2020                 dc = token.comment(CommentStyle.JAVADOC);
  2021                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2022             } else if (allowAsserts && token.kind == ASSERT) {
  2023                 return List.of(parseStatement());
  2025             /* fall through to default */
  2026         default:
  2027             Token prevToken = token;
  2028             JCExpression t = term(EXPR | TYPE);
  2029             if (token.kind == COLON && t.hasTag(IDENT)) {
  2030                 nextToken();
  2031                 JCStatement stat = parseStatement();
  2032                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  2033             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2034                 pos = token.pos;
  2035                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2036                 F.at(pos);
  2037                 ListBuffer<JCStatement> stats =
  2038                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2039                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2040                 storeEnd(stats.last(), token.endPos);
  2041                 accept(SEMI);
  2042                 return stats.toList();
  2043             } else {
  2044                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2045                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  2046                 accept(SEMI);
  2047                 return List.<JCStatement>of(expr);
  2052     /** Statement =
  2053      *       Block
  2054      *     | IF ParExpression Statement [ELSE Statement]
  2055      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  2056      *     | FOR "(" FormalParameter : Expression ")" Statement
  2057      *     | WHILE ParExpression Statement
  2058      *     | DO Statement WHILE ParExpression ";"
  2059      *     | TRY Block ( Catches | [Catches] FinallyPart )
  2060      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  2061      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  2062      *     | SYNCHRONIZED ParExpression Block
  2063      *     | RETURN [Expression] ";"
  2064      *     | THROW Expression ";"
  2065      *     | BREAK [Ident] ";"
  2066      *     | CONTINUE [Ident] ";"
  2067      *     | ASSERT Expression [ ":" Expression ] ";"
  2068      *     | ";"
  2069      *     | ExpressionStatement
  2070      *     | Ident ":" Statement
  2071      */
  2072     @SuppressWarnings("fallthrough")
  2073     public JCStatement parseStatement() {
  2074         int pos = token.pos;
  2075         switch (token.kind) {
  2076         case LBRACE:
  2077             return block();
  2078         case IF: {
  2079             nextToken();
  2080             JCExpression cond = parExpression();
  2081             JCStatement thenpart = parseStatementAsBlock();
  2082             JCStatement elsepart = null;
  2083             if (token.kind == ELSE) {
  2084                 nextToken();
  2085                 elsepart = parseStatementAsBlock();
  2087             return F.at(pos).If(cond, thenpart, elsepart);
  2089         case FOR: {
  2090             nextToken();
  2091             accept(LPAREN);
  2092             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  2093             if (inits.length() == 1 &&
  2094                 inits.head.hasTag(VARDEF) &&
  2095                 ((JCVariableDecl) inits.head).init == null &&
  2096                 token.kind == COLON) {
  2097                 checkForeach();
  2098                 JCVariableDecl var = (JCVariableDecl)inits.head;
  2099                 accept(COLON);
  2100                 JCExpression expr = parseExpression();
  2101                 accept(RPAREN);
  2102                 JCStatement body = parseStatementAsBlock();
  2103                 return F.at(pos).ForeachLoop(var, expr, body);
  2104             } else {
  2105                 accept(SEMI);
  2106                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  2107                 accept(SEMI);
  2108                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2109                 accept(RPAREN);
  2110                 JCStatement body = parseStatementAsBlock();
  2111                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2114         case WHILE: {
  2115             nextToken();
  2116             JCExpression cond = parExpression();
  2117             JCStatement body = parseStatementAsBlock();
  2118             return F.at(pos).WhileLoop(cond, body);
  2120         case DO: {
  2121             nextToken();
  2122             JCStatement body = parseStatementAsBlock();
  2123             accept(WHILE);
  2124             JCExpression cond = parExpression();
  2125             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2126             accept(SEMI);
  2127             return t;
  2129         case TRY: {
  2130             nextToken();
  2131             List<JCTree> resources = List.<JCTree>nil();
  2132             if (token.kind == LPAREN) {
  2133                 checkTryWithResources();
  2134                 nextToken();
  2135                 resources = resources();
  2136                 accept(RPAREN);
  2138             JCBlock body = block();
  2139             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2140             JCBlock finalizer = null;
  2141             if (token.kind == CATCH || token.kind == FINALLY) {
  2142                 while (token.kind == CATCH) catchers.append(catchClause());
  2143                 if (token.kind == FINALLY) {
  2144                     nextToken();
  2145                     finalizer = block();
  2147             } else {
  2148                 if (allowTWR) {
  2149                     if (resources.isEmpty())
  2150                         error(pos, "try.without.catch.finally.or.resource.decls");
  2151                 } else
  2152                     error(pos, "try.without.catch.or.finally");
  2154             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2156         case SWITCH: {
  2157             nextToken();
  2158             JCExpression selector = parExpression();
  2159             accept(LBRACE);
  2160             List<JCCase> cases = switchBlockStatementGroups();
  2161             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2162             accept(RBRACE);
  2163             return t;
  2165         case SYNCHRONIZED: {
  2166             nextToken();
  2167             JCExpression lock = parExpression();
  2168             JCBlock body = block();
  2169             return F.at(pos).Synchronized(lock, body);
  2171         case RETURN: {
  2172             nextToken();
  2173             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2174             JCReturn t = to(F.at(pos).Return(result));
  2175             accept(SEMI);
  2176             return t;
  2178         case THROW: {
  2179             nextToken();
  2180             JCExpression exc = parseExpression();
  2181             JCThrow t = to(F.at(pos).Throw(exc));
  2182             accept(SEMI);
  2183             return t;
  2185         case BREAK: {
  2186             nextToken();
  2187             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2188             JCBreak t = to(F.at(pos).Break(label));
  2189             accept(SEMI);
  2190             return t;
  2192         case CONTINUE: {
  2193             nextToken();
  2194             Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
  2195             JCContinue t =  to(F.at(pos).Continue(label));
  2196             accept(SEMI);
  2197             return t;
  2199         case SEMI:
  2200             nextToken();
  2201             return toP(F.at(pos).Skip());
  2202         case ELSE:
  2203             int elsePos = token.pos;
  2204             nextToken();
  2205             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
  2206         case FINALLY:
  2207             int finallyPos = token.pos;
  2208             nextToken();
  2209             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
  2210         case CATCH:
  2211             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
  2212         case ASSERT: {
  2213             if (allowAsserts && token.kind == ASSERT) {
  2214                 nextToken();
  2215                 JCExpression assertion = parseExpression();
  2216                 JCExpression message = null;
  2217                 if (token.kind == COLON) {
  2218                     nextToken();
  2219                     message = parseExpression();
  2221                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2222                 accept(SEMI);
  2223                 return t;
  2225             /* else fall through to default case */
  2227         case ENUM:
  2228         default:
  2229             Token prevToken = token;
  2230             JCExpression expr = parseExpression();
  2231             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2232                 nextToken();
  2233                 JCStatement stat = parseStatement();
  2234                 return F.at(pos).Labelled(prevToken.name(), stat);
  2235             } else {
  2236                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2237                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2238                 accept(SEMI);
  2239                 return stat;
  2244     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
  2245         int errPos = S.errPos();
  2246         JCTree stm = action.doRecover(this);
  2247         S.errPos(errPos);
  2248         return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
  2251     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2252      */
  2253     protected JCCatch catchClause() {
  2254         int pos = token.pos;
  2255         accept(CATCH);
  2256         accept(LPAREN);
  2257         JCModifiers mods = optFinal(Flags.PARAMETER);
  2258         List<JCExpression> catchTypes = catchTypes();
  2259         JCExpression paramType = catchTypes.size() > 1 ?
  2260                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2261                 catchTypes.head;
  2262         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2263         accept(RPAREN);
  2264         JCBlock body = block();
  2265         return F.at(pos).Catch(formal, body);
  2268     List<JCExpression> catchTypes() {
  2269         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2270         catchTypes.add(parseType());
  2271         while (token.kind == BAR) {
  2272             checkMulticatch();
  2273             nextToken();
  2274             catchTypes.add(qualident());
  2276         return catchTypes.toList();
  2279     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2280      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2281      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2282      */
  2283     List<JCCase> switchBlockStatementGroups() {
  2284         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2285         while (true) {
  2286             int pos = token.pos;
  2287             switch (token.kind) {
  2288             case CASE:
  2289             case DEFAULT:
  2290                 cases.append(switchBlockStatementGroup());
  2291                 break;
  2292             case RBRACE: case EOF:
  2293                 return cases.toList();
  2294             default:
  2295                 nextToken(); // to ensure progress
  2296                 syntaxError(pos, "expected3",
  2297                     CASE, DEFAULT, RBRACE);
  2302     protected JCCase switchBlockStatementGroup() {
  2303         int pos = token.pos;
  2304         List<JCStatement> stats;
  2305         JCCase c;
  2306         switch (token.kind) {
  2307         case CASE:
  2308             nextToken();
  2309             JCExpression pat = parseExpression();
  2310             accept(COLON);
  2311             stats = blockStatements();
  2312             c = F.at(pos).Case(pat, stats);
  2313             if (stats.isEmpty())
  2314                 storeEnd(c, S.prevToken().endPos);
  2315             return c;
  2316         case DEFAULT:
  2317             nextToken();
  2318             accept(COLON);
  2319             stats = blockStatements();
  2320             c = F.at(pos).Case(null, stats);
  2321             if (stats.isEmpty())
  2322                 storeEnd(c, S.prevToken().endPos);
  2323             return c;
  2325         throw new AssertionError("should not reach here");
  2328     /** MoreStatementExpressions = { COMMA StatementExpression }
  2329      */
  2330     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2331                                                                     JCExpression first,
  2332                                                                     T stats) {
  2333         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2334         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2335         while (token.kind == COMMA) {
  2336             nextToken();
  2337             pos = token.pos;
  2338             JCExpression t = parseExpression();
  2339             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2340             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2342         return stats;
  2345     /** ForInit = StatementExpression MoreStatementExpressions
  2346      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2347      */
  2348     List<JCStatement> forInit() {
  2349         ListBuffer<JCStatement> stats = lb();
  2350         int pos = token.pos;
  2351         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2352             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2353         } else {
  2354             JCExpression t = term(EXPR | TYPE);
  2355             if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
  2356                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2357             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2358                 error(pos, "bad.initializer", "for-loop");
  2359                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2360             } else {
  2361                 return moreStatementExpressions(pos, t, stats).toList();
  2366     /** ForUpdate = StatementExpression MoreStatementExpressions
  2367      */
  2368     List<JCExpressionStatement> forUpdate() {
  2369         return moreStatementExpressions(token.pos,
  2370                                         parseExpression(),
  2371                                         new ListBuffer<JCExpressionStatement>()).toList();
  2374     /** AnnotationsOpt = { '@' Annotation }
  2375      */
  2376     List<JCAnnotation> annotationsOpt() {
  2377         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2378         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2379         while (token.kind == MONKEYS_AT) {
  2380             int pos = token.pos;
  2381             nextToken();
  2382             buf.append(annotation(pos));
  2384         return buf.toList();
  2387     /** ModifiersOpt = { Modifier }
  2388      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2389      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2390      *           | "@" Annotation
  2391      */
  2392     JCModifiers modifiersOpt() {
  2393         return modifiersOpt(null);
  2395     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2396         long flags;
  2397         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2398         int pos;
  2399         if (partial == null) {
  2400             flags = 0;
  2401             pos = token.pos;
  2402         } else {
  2403             flags = partial.flags;
  2404             annotations.appendList(partial.annotations);
  2405             pos = partial.pos;
  2407         if (token.deprecatedFlag()) {
  2408             flags |= Flags.DEPRECATED;
  2410         int lastPos = Position.NOPOS;
  2411     loop:
  2412         while (true) {
  2413             long flag;
  2414             switch (token.kind) {
  2415             case PRIVATE     : flag = Flags.PRIVATE; break;
  2416             case PROTECTED   : flag = Flags.PROTECTED; break;
  2417             case PUBLIC      : flag = Flags.PUBLIC; break;
  2418             case STATIC      : flag = Flags.STATIC; break;
  2419             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2420             case FINAL       : flag = Flags.FINAL; break;
  2421             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2422             case NATIVE      : flag = Flags.NATIVE; break;
  2423             case VOLATILE    : flag = Flags.VOLATILE; break;
  2424             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2425             case STRICTFP    : flag = Flags.STRICTFP; break;
  2426             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2427             case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
  2428             case ERROR       : flag = 0; nextToken(); break;
  2429             default: break loop;
  2431             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2432             lastPos = token.pos;
  2433             nextToken();
  2434             if (flag == Flags.ANNOTATION) {
  2435                 checkAnnotations();
  2436                 if (token.kind != INTERFACE) {
  2437                     JCAnnotation ann = annotation(lastPos);
  2438                     // if first modifier is an annotation, set pos to annotation's.
  2439                     if (flags == 0 && annotations.isEmpty())
  2440                         pos = ann.pos;
  2441                     annotations.append(ann);
  2442                     lastPos = ann.pos;
  2443                     flag = 0;
  2446             flags |= flag;
  2448         switch (token.kind) {
  2449         case ENUM: flags |= Flags.ENUM; break;
  2450         case INTERFACE: flags |= Flags.INTERFACE; break;
  2451         default: break;
  2454         /* A modifiers tree with no modifier tokens or annotations
  2455          * has no text position. */
  2456         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2457             pos = Position.NOPOS;
  2459         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2460         if (pos != Position.NOPOS)
  2461             storeEnd(mods, S.prevToken().endPos);
  2462         return mods;
  2465     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2466      * @param pos position of "@" token
  2467      */
  2468     JCAnnotation annotation(int pos) {
  2469         // accept(AT); // AT consumed by caller
  2470         checkAnnotations();
  2471         JCTree ident = qualident();
  2472         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2473         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2474         storeEnd(ann, S.prevToken().endPos);
  2475         return ann;
  2478     List<JCExpression> annotationFieldValuesOpt() {
  2479         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2482     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2483     List<JCExpression> annotationFieldValues() {
  2484         accept(LPAREN);
  2485         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2486         if (token.kind != RPAREN) {
  2487             buf.append(annotationFieldValue());
  2488             while (token.kind == COMMA) {
  2489                 nextToken();
  2490                 buf.append(annotationFieldValue());
  2493         accept(RPAREN);
  2494         return buf.toList();
  2497     /** AnnotationFieldValue    = AnnotationValue
  2498      *                          | Identifier "=" AnnotationValue
  2499      */
  2500     JCExpression annotationFieldValue() {
  2501         if (token.kind == IDENTIFIER) {
  2502             mode = EXPR;
  2503             JCExpression t1 = term1();
  2504             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2505                 int pos = token.pos;
  2506                 accept(EQ);
  2507                 JCExpression v = annotationValue();
  2508                 return toP(F.at(pos).Assign(t1, v));
  2509             } else {
  2510                 return t1;
  2513         return annotationValue();
  2516     /* AnnotationValue          = ConditionalExpression
  2517      *                          | Annotation
  2518      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2519      */
  2520     JCExpression annotationValue() {
  2521         int pos;
  2522         switch (token.kind) {
  2523         case MONKEYS_AT:
  2524             pos = token.pos;
  2525             nextToken();
  2526             return annotation(pos);
  2527         case LBRACE:
  2528             pos = token.pos;
  2529             accept(LBRACE);
  2530             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2531             if (token.kind != RBRACE) {
  2532                 buf.append(annotationValue());
  2533                 while (token.kind == COMMA) {
  2534                     nextToken();
  2535                     if (token.kind == RBRACE) break;
  2536                     buf.append(annotationValue());
  2539             accept(RBRACE);
  2540             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2541         default:
  2542             mode = EXPR;
  2543             return term1();
  2547     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2548      */
  2549     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2550                                                                          JCExpression type,
  2551                                                                          T vdefs)
  2553         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2556     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2557      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2559      *  @param reqInit  Is an initializer always required?
  2560      *  @param dc       The documentation comment for the variable declarations, or null.
  2561      */
  2562     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2563                                                                      JCModifiers mods,
  2564                                                                      JCExpression type,
  2565                                                                      Name name,
  2566                                                                      boolean reqInit,
  2567                                                                      Comment dc,
  2568                                                                      T vdefs)
  2570         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2571         while (token.kind == COMMA) {
  2572             // All but last of multiple declarators subsume a comma
  2573             storeEnd((JCTree)vdefs.last(), token.endPos);
  2574             nextToken();
  2575             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2577         return vdefs;
  2580     /** VariableDeclarator = Ident VariableDeclaratorRest
  2581      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2582      */
  2583     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2584         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2587     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2588      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2590      *  @param reqInit  Is an initializer always required?
  2591      *  @param dc       The documentation comment for the variable declarations, or null.
  2592      */
  2593     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2594                                   boolean reqInit, Comment dc) {
  2595         type = bracketsOpt(type);
  2596         JCExpression init = null;
  2597         if (token.kind == EQ) {
  2598             nextToken();
  2599             init = variableInitializer();
  2601         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2602         JCVariableDecl result =
  2603             toP(F.at(pos).VarDef(mods, name, type, init));
  2604         attach(result, dc);
  2605         return result;
  2608     /** VariableDeclaratorId = Ident BracketsOpt
  2609      */
  2610     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2611         return variableDeclaratorId(mods, type, false);
  2613     //where
  2614     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
  2615         int pos = token.pos;
  2616         Name name;
  2617         if (lambdaParameter && token.kind == UNDERSCORE) {
  2618             syntaxError(pos, "expected", IDENTIFIER);
  2619             name = token.name();
  2620         } else {
  2621             name = ident();
  2623         if ((mods.flags & Flags.VARARGS) != 0 &&
  2624                 token.kind == LBRACKET) {
  2625             log.error(token.pos, "varargs.and.old.array.syntax");
  2627         type = bracketsOpt(type);
  2628         return toP(F.at(pos).VarDef(mods, name, type, null));
  2631     /** Resources = Resource { ";" Resources }
  2632      */
  2633     List<JCTree> resources() {
  2634         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2635         defs.append(resource());
  2636         while (token.kind == SEMI) {
  2637             // All but last of multiple declarators must subsume a semicolon
  2638             storeEnd(defs.last(), token.endPos);
  2639             int semiColonPos = token.pos;
  2640             nextToken();
  2641             if (token.kind == RPAREN) { // Optional trailing semicolon
  2642                                        // after last resource
  2643                 break;
  2645             defs.append(resource());
  2647         return defs.toList();
  2650     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2651      */
  2652     protected JCTree resource() {
  2653         JCModifiers optFinal = optFinal(Flags.FINAL);
  2654         JCExpression type = parseType();
  2655         int pos = token.pos;
  2656         Name ident = ident();
  2657         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2660     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2661      */
  2662     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2663         Token firstToken = token;
  2664         JCExpression pid = null;
  2665         JCModifiers mods = null;
  2666         boolean consumedToplevelDoc = false;
  2667         boolean seenImport = false;
  2668         boolean seenPackage = false;
  2669         List<JCAnnotation> packageAnnotations = List.nil();
  2670         if (token.kind == MONKEYS_AT)
  2671             mods = modifiersOpt();
  2673         if (token.kind == PACKAGE) {
  2674             seenPackage = true;
  2675             if (mods != null) {
  2676                 checkNoMods(mods.flags);
  2677                 packageAnnotations = mods.annotations;
  2678                 mods = null;
  2680             nextToken();
  2681             pid = qualident();
  2682             accept(SEMI);
  2684         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2685         boolean checkForImports = true;
  2686         boolean firstTypeDecl = true;
  2687         while (token.kind != EOF) {
  2688             if (token.pos <= endPosTable.errorEndPos) {
  2689                 // error recovery
  2690                 skip(checkForImports, false, false, false);
  2691                 if (token.kind == EOF)
  2692                     break;
  2694             if (checkForImports && mods == null && token.kind == IMPORT) {
  2695                 seenImport = true;
  2696                 defs.append(importDeclaration());
  2697             } else {
  2698                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  2699                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2700                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2701                     consumedToplevelDoc = true;
  2703                 JCTree def = typeDeclaration(mods, docComment);
  2704                 if (def instanceof JCExpressionStatement)
  2705                     def = ((JCExpressionStatement)def).expr;
  2706                 defs.append(def);
  2707                 if (def instanceof JCClassDecl)
  2708                     checkForImports = false;
  2709                 mods = null;
  2710                 firstTypeDecl = false;
  2713         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2714         if (!consumedToplevelDoc)
  2715             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2716         if (defs.isEmpty())
  2717             storeEnd(toplevel, S.prevToken().endPos);
  2718         if (keepDocComments)
  2719             toplevel.docComments = docComments;
  2720         if (keepLineMap)
  2721             toplevel.lineMap = S.getLineMap();
  2722         toplevel.endPositions = this.endPosTable;
  2723         return toplevel;
  2726     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2727      */
  2728     JCTree importDeclaration() {
  2729         int pos = token.pos;
  2730         nextToken();
  2731         boolean importStatic = false;
  2732         if (token.kind == STATIC) {
  2733             checkStaticImports();
  2734             importStatic = true;
  2735             nextToken();
  2737         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2738         do {
  2739             int pos1 = token.pos;
  2740             accept(DOT);
  2741             if (token.kind == STAR) {
  2742                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2743                 nextToken();
  2744                 break;
  2745             } else {
  2746                 pid = toP(F.at(pos1).Select(pid, ident()));
  2748         } while (token.kind == DOT);
  2749         accept(SEMI);
  2750         return toP(F.at(pos).Import(pid, importStatic));
  2753     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2754      *                  | ";"
  2755      */
  2756     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  2757         int pos = token.pos;
  2758         if (mods == null && token.kind == SEMI) {
  2759             nextToken();
  2760             return toP(F.at(pos).Skip());
  2761         } else {
  2762             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2766     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2767      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2768      *  @param mods     Any modifiers starting the class or interface declaration
  2769      *  @param dc       The documentation comment for the class, or null.
  2770      */
  2771     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  2772         if (token.kind == CLASS) {
  2773             return classDeclaration(mods, dc);
  2774         } else if (token.kind == INTERFACE) {
  2775             return interfaceDeclaration(mods, dc);
  2776         } else if (allowEnums) {
  2777             if (token.kind == ENUM) {
  2778                 return enumDeclaration(mods, dc);
  2779             } else {
  2780                 int pos = token.pos;
  2781                 List<JCTree> errs;
  2782                 if (LAX_IDENTIFIER.accepts(token.kind)) {
  2783                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2784                     setErrorEndPos(token.pos);
  2785                 } else {
  2786                     errs = List.<JCTree>of(mods);
  2788                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2789                                               CLASS, INTERFACE, ENUM)));
  2791         } else {
  2792             if (token.kind == ENUM) {
  2793                 error(token.pos, "enums.not.supported.in.source", source.name);
  2794                 allowEnums = true;
  2795                 return enumDeclaration(mods, dc);
  2797             int pos = token.pos;
  2798             List<JCTree> errs;
  2799             if (LAX_IDENTIFIER.accepts(token.kind)) {
  2800                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2801                 setErrorEndPos(token.pos);
  2802             } else {
  2803                 errs = List.<JCTree>of(mods);
  2805             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2806                                           CLASS, INTERFACE)));
  2810     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2811      *                     [IMPLEMENTS TypeList] ClassBody
  2812      *  @param mods    The modifiers starting the class declaration
  2813      *  @param dc       The documentation comment for the class, or null.
  2814      */
  2815     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  2816         int pos = token.pos;
  2817         accept(CLASS);
  2818         Name name = ident();
  2820         List<JCTypeParameter> typarams = typeParametersOpt();
  2822         JCExpression extending = null;
  2823         if (token.kind == EXTENDS) {
  2824             nextToken();
  2825             extending = parseType();
  2827         List<JCExpression> implementing = List.nil();
  2828         if (token.kind == IMPLEMENTS) {
  2829             nextToken();
  2830             implementing = typeList();
  2832         List<JCTree> defs = classOrInterfaceBody(name, false);
  2833         JCClassDecl result = toP(F.at(pos).ClassDef(
  2834             mods, name, typarams, extending, implementing, defs));
  2835         attach(result, dc);
  2836         return result;
  2839     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2840      *                         [EXTENDS TypeList] InterfaceBody
  2841      *  @param mods    The modifiers starting the interface declaration
  2842      *  @param dc       The documentation comment for the interface, or null.
  2843      */
  2844     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  2845         int pos = token.pos;
  2846         accept(INTERFACE);
  2847         Name name = ident();
  2849         List<JCTypeParameter> typarams = typeParametersOpt();
  2851         List<JCExpression> extending = List.nil();
  2852         if (token.kind == EXTENDS) {
  2853             nextToken();
  2854             extending = typeList();
  2856         List<JCTree> defs = classOrInterfaceBody(name, true);
  2857         JCClassDecl result = toP(F.at(pos).ClassDef(
  2858             mods, name, typarams, null, extending, defs));
  2859         attach(result, dc);
  2860         return result;
  2863     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2864      *  @param mods    The modifiers starting the enum declaration
  2865      *  @param dc       The documentation comment for the enum, or null.
  2866      */
  2867     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  2868         int pos = token.pos;
  2869         accept(ENUM);
  2870         Name name = ident();
  2872         List<JCExpression> implementing = List.nil();
  2873         if (token.kind == IMPLEMENTS) {
  2874             nextToken();
  2875             implementing = typeList();
  2878         List<JCTree> defs = enumBody(name);
  2879         mods.flags |= Flags.ENUM;
  2880         JCClassDecl result = toP(F.at(pos).
  2881             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2882                 null, implementing, defs));
  2883         attach(result, dc);
  2884         return result;
  2887     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2888      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2889      */
  2890     List<JCTree> enumBody(Name enumName) {
  2891         accept(LBRACE);
  2892         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2893         if (token.kind == COMMA) {
  2894             nextToken();
  2895         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2896             defs.append(enumeratorDeclaration(enumName));
  2897             while (token.kind == COMMA) {
  2898                 nextToken();
  2899                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2900                 defs.append(enumeratorDeclaration(enumName));
  2902             if (token.kind != SEMI && token.kind != RBRACE) {
  2903                 defs.append(syntaxError(token.pos, "expected3",
  2904                                 COMMA, RBRACE, SEMI));
  2905                 nextToken();
  2908         if (token.kind == SEMI) {
  2909             nextToken();
  2910             while (token.kind != RBRACE && token.kind != EOF) {
  2911                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2912                                                                 false));
  2913                 if (token.pos <= endPosTable.errorEndPos) {
  2914                     // error recovery
  2915                    skip(false, true, true, false);
  2919         accept(RBRACE);
  2920         return defs.toList();
  2923     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2924      */
  2925     JCTree enumeratorDeclaration(Name enumName) {
  2926         Comment dc = token.comment(CommentStyle.JAVADOC);
  2927         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2928         if (token.deprecatedFlag()) {
  2929             flags |= Flags.DEPRECATED;
  2931         int pos = token.pos;
  2932         List<JCAnnotation> annotations = annotationsOpt();
  2933         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2934         List<JCExpression> typeArgs = typeArgumentsOpt();
  2935         int identPos = token.pos;
  2936         Name name = ident();
  2937         int createPos = token.pos;
  2938         List<JCExpression> args = (token.kind == LPAREN)
  2939             ? arguments() : List.<JCExpression>nil();
  2940         JCClassDecl body = null;
  2941         if (token.kind == LBRACE) {
  2942             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2943             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2944             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2946         if (args.isEmpty() && body == null)
  2947             createPos = identPos;
  2948         JCIdent ident = F.at(identPos).Ident(enumName);
  2949         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2950         if (createPos != identPos)
  2951             storeEnd(create, S.prevToken().endPos);
  2952         ident = F.at(identPos).Ident(enumName);
  2953         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2954         attach(result, dc);
  2955         return result;
  2958     /** TypeList = Type {"," Type}
  2959      */
  2960     List<JCExpression> typeList() {
  2961         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2962         ts.append(parseType());
  2963         while (token.kind == COMMA) {
  2964             nextToken();
  2965             ts.append(parseType());
  2967         return ts.toList();
  2970     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2971      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2972      */
  2973     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2974         accept(LBRACE);
  2975         if (token.pos <= endPosTable.errorEndPos) {
  2976             // error recovery
  2977             skip(false, true, false, false);
  2978             if (token.kind == LBRACE)
  2979                 nextToken();
  2981         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2982         while (token.kind != RBRACE && token.kind != EOF) {
  2983             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2984             if (token.pos <= endPosTable.errorEndPos) {
  2985                // error recovery
  2986                skip(false, true, true, false);
  2989         accept(RBRACE);
  2990         return defs.toList();
  2993     /** ClassBodyDeclaration =
  2994      *      ";"
  2995      *    | [STATIC] Block
  2996      *    | ModifiersOpt
  2997      *      ( Type Ident
  2998      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2999      *      | VOID Ident MethodDeclaratorRest
  3000      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  3001      *      | Ident ConstructorDeclaratorRest
  3002      *      | TypeParameters Ident ConstructorDeclaratorRest
  3003      *      | ClassOrInterfaceOrEnumDeclaration
  3004      *      )
  3005      *  InterfaceBodyDeclaration =
  3006      *      ";"
  3007      *    | ModifiersOpt Type Ident
  3008      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  3009      */
  3010     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  3011         if (token.kind == SEMI) {
  3012             nextToken();
  3013             return List.<JCTree>nil();
  3014         } else {
  3015             Comment dc = token.comment(CommentStyle.JAVADOC);
  3016             int pos = token.pos;
  3017             JCModifiers mods = modifiersOpt();
  3018             if (token.kind == CLASS ||
  3019                 token.kind == INTERFACE ||
  3020                 allowEnums && token.kind == ENUM) {
  3021                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  3022             } else if (token.kind == LBRACE && !isInterface &&
  3023                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  3024                        mods.annotations.isEmpty()) {
  3025                 return List.<JCTree>of(block(pos, mods.flags));
  3026             } else {
  3027                 pos = token.pos;
  3028                 List<JCTypeParameter> typarams = typeParametersOpt();
  3029                 // if there are type parameters but no modifiers, save the start
  3030                 // position of the method in the modifiers.
  3031                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  3032                     mods.pos = pos;
  3033                     storeEnd(mods, pos);
  3035                 Token tk = token;
  3036                 pos = token.pos;
  3037                 JCExpression type;
  3038                 boolean isVoid = token.kind == VOID;
  3039                 if (isVoid) {
  3040                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
  3041                     nextToken();
  3042                 } else {
  3043                     type = parseType();
  3045                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  3046                     if (isInterface || tk.name() != className)
  3047                         error(pos, "invalid.meth.decl.ret.type.req");
  3048                     return List.of(methodDeclaratorRest(
  3049                         pos, mods, null, names.init, typarams,
  3050                         isInterface, true, dc));
  3051                 } else {
  3052                     pos = token.pos;
  3053                     Name name = ident();
  3054                     if (token.kind == LPAREN) {
  3055                         return List.of(methodDeclaratorRest(
  3056                             pos, mods, type, name, typarams,
  3057                             isInterface, isVoid, dc));
  3058                     } else if (!isVoid && typarams.isEmpty()) {
  3059                         List<JCTree> defs =
  3060                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  3061                                                     new ListBuffer<JCTree>()).toList();
  3062                         storeEnd(defs.last(), token.endPos);
  3063                         accept(SEMI);
  3064                         return defs;
  3065                     } else {
  3066                         pos = token.pos;
  3067                         List<JCTree> err = isVoid
  3068                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3069                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  3070                             : null;
  3071                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  3078     /** MethodDeclaratorRest =
  3079      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  3080      *  VoidMethodDeclaratorRest =
  3081      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  3082      *  InterfaceMethodDeclaratorRest =
  3083      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  3084      *  VoidInterfaceMethodDeclaratorRest =
  3085      *      FormalParameters [THROWS TypeList] ";"
  3086      *  ConstructorDeclaratorRest =
  3087      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  3088      */
  3089     protected JCTree methodDeclaratorRest(int pos,
  3090                               JCModifiers mods,
  3091                               JCExpression type,
  3092                               Name name,
  3093                               List<JCTypeParameter> typarams,
  3094                               boolean isInterface, boolean isVoid,
  3095                               Comment dc) {
  3096         List<JCVariableDecl> params = formalParameters();
  3097         if (!isVoid) type = bracketsOpt(type);
  3098         List<JCExpression> thrown = List.nil();
  3099         if (token.kind == THROWS) {
  3100             nextToken();
  3101             thrown = qualidentList();
  3103         JCBlock body = null;
  3104         JCExpression defaultValue;
  3105         if (token.kind == LBRACE) {
  3106             body = block();
  3107             defaultValue = null;
  3108         } else {
  3109             if (token.kind == DEFAULT) {
  3110                 accept(DEFAULT);
  3111                 defaultValue = annotationValue();
  3112             } else {
  3113                 defaultValue = null;
  3115             accept(SEMI);
  3116             if (token.pos <= endPosTable.errorEndPos) {
  3117                 // error recovery
  3118                 skip(false, true, false, false);
  3119                 if (token.kind == LBRACE) {
  3120                     body = block();
  3125         JCMethodDecl result =
  3126             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3127                                     params, thrown,
  3128                                     body, defaultValue));
  3129         attach(result, dc);
  3130         return result;
  3133     /** QualidentList = Qualident {"," Qualident}
  3134      */
  3135     List<JCExpression> qualidentList() {
  3136         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3137         ts.append(qualident());
  3138         while (token.kind == COMMA) {
  3139             nextToken();
  3140             ts.append(qualident());
  3142         return ts.toList();
  3145     /**
  3146      *  {@literal
  3147      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3148      *  }
  3149      */
  3150     List<JCTypeParameter> typeParametersOpt() {
  3151         if (token.kind == LT) {
  3152             checkGenerics();
  3153             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3154             nextToken();
  3155             typarams.append(typeParameter());
  3156             while (token.kind == COMMA) {
  3157                 nextToken();
  3158                 typarams.append(typeParameter());
  3160             accept(GT);
  3161             return typarams.toList();
  3162         } else {
  3163             return List.nil();
  3167     /**
  3168      *  {@literal
  3169      *  TypeParameter = TypeVariable [TypeParameterBound]
  3170      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3171      *  TypeVariable = Ident
  3172      *  }
  3173      */
  3174     JCTypeParameter typeParameter() {
  3175         int pos = token.pos;
  3176         Name name = ident();
  3177         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3178         if (token.kind == EXTENDS) {
  3179             nextToken();
  3180             bounds.append(parseType());
  3181             while (token.kind == AMP) {
  3182                 nextToken();
  3183                 bounds.append(parseType());
  3186         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  3189     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3190      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3191      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3192      */
  3193     List<JCVariableDecl> formalParameters() {
  3194         return formalParameters(false);
  3196     List<JCVariableDecl> formalParameters(boolean lambdaParameters) {
  3197         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3198         JCVariableDecl lastParam = null;
  3199         accept(LPAREN);
  3200         if (token.kind != RPAREN) {
  3201             params.append(lastParam = formalParameter(lambdaParameters));
  3202             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3203                 nextToken();
  3204                 params.append(lastParam = formalParameter(lambdaParameters));
  3207         accept(RPAREN);
  3208         return params.toList();
  3211     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3212         if (hasParens) {
  3213             accept(LPAREN);
  3215         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3216         if (token.kind != RPAREN && token.kind != ARROW) {
  3217             params.append(implicitParameter());
  3218             while (token.kind == COMMA) {
  3219                 nextToken();
  3220                 params.append(implicitParameter());
  3223         if (hasParens) {
  3224             accept(RPAREN);
  3226         return params.toList();
  3229     JCModifiers optFinal(long flags) {
  3230         JCModifiers mods = modifiersOpt();
  3231         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3232         mods.flags |= flags;
  3233         return mods;
  3236     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3237      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3238      */
  3239     protected JCVariableDecl formalParameter() {
  3240         return formalParameter(false);
  3242     protected JCVariableDecl formalParameter(boolean lambdaParameter) {
  3243         JCModifiers mods = optFinal(Flags.PARAMETER);
  3244         JCExpression type = parseType();
  3245         if (token.kind == ELLIPSIS) {
  3246             checkVarargs();
  3247             mods.flags |= Flags.VARARGS;
  3248             type = to(F.at(token.pos).TypeArray(type));
  3249             nextToken();
  3251         return variableDeclaratorId(mods, type, lambdaParameter);
  3254     protected JCVariableDecl implicitParameter() {
  3255         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3256         return variableDeclaratorId(mods, null, true);
  3259 /* ---------- auxiliary methods -------------- */
  3261     void error(int pos, String key, Object ... args) {
  3262         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3265     void error(DiagnosticPosition pos, String key, Object ... args) {
  3266         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3269     void warning(int pos, String key, Object ... args) {
  3270         log.warning(pos, key, args);
  3273     /** Check that given tree is a legal expression statement.
  3274      */
  3275     protected JCExpression checkExprStat(JCExpression t) {
  3276         if (!TreeInfo.isExpressionStatement(t)) {
  3277             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3278             error(ret, "not.stmt");
  3279             return ret;
  3280         } else {
  3281             return t;
  3285     /** Return precedence of operator represented by token,
  3286      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3287      */
  3288     static int prec(TokenKind token) {
  3289         JCTree.Tag oc = optag(token);
  3290         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3293     /**
  3294      * Return the lesser of two positions, making allowance for either one
  3295      * being unset.
  3296      */
  3297     static int earlier(int pos1, int pos2) {
  3298         if (pos1 == Position.NOPOS)
  3299             return pos2;
  3300         if (pos2 == Position.NOPOS)
  3301             return pos1;
  3302         return (pos1 < pos2 ? pos1 : pos2);
  3305     /** Return operation tag of binary operator represented by token,
  3306      *  No_TAG if token is not a binary operator.
  3307      */
  3308     static JCTree.Tag optag(TokenKind token) {
  3309         switch (token) {
  3310         case BARBAR:
  3311             return OR;
  3312         case AMPAMP:
  3313             return AND;
  3314         case BAR:
  3315             return BITOR;
  3316         case BAREQ:
  3317             return BITOR_ASG;
  3318         case CARET:
  3319             return BITXOR;
  3320         case CARETEQ:
  3321             return BITXOR_ASG;
  3322         case AMP:
  3323             return BITAND;
  3324         case AMPEQ:
  3325             return BITAND_ASG;
  3326         case EQEQ:
  3327             return JCTree.Tag.EQ;
  3328         case BANGEQ:
  3329             return NE;
  3330         case LT:
  3331             return JCTree.Tag.LT;
  3332         case GT:
  3333             return JCTree.Tag.GT;
  3334         case LTEQ:
  3335             return LE;
  3336         case GTEQ:
  3337             return GE;
  3338         case LTLT:
  3339             return SL;
  3340         case LTLTEQ:
  3341             return SL_ASG;
  3342         case GTGT:
  3343             return SR;
  3344         case GTGTEQ:
  3345             return SR_ASG;
  3346         case GTGTGT:
  3347             return USR;
  3348         case GTGTGTEQ:
  3349             return USR_ASG;
  3350         case PLUS:
  3351             return JCTree.Tag.PLUS;
  3352         case PLUSEQ:
  3353             return PLUS_ASG;
  3354         case SUB:
  3355             return MINUS;
  3356         case SUBEQ:
  3357             return MINUS_ASG;
  3358         case STAR:
  3359             return MUL;
  3360         case STAREQ:
  3361             return MUL_ASG;
  3362         case SLASH:
  3363             return DIV;
  3364         case SLASHEQ:
  3365             return DIV_ASG;
  3366         case PERCENT:
  3367             return MOD;
  3368         case PERCENTEQ:
  3369             return MOD_ASG;
  3370         case INSTANCEOF:
  3371             return TYPETEST;
  3372         default:
  3373             return NO_TAG;
  3377     /** Return operation tag of unary operator represented by token,
  3378      *  No_TAG if token is not a binary operator.
  3379      */
  3380     static JCTree.Tag unoptag(TokenKind token) {
  3381         switch (token) {
  3382         case PLUS:
  3383             return POS;
  3384         case SUB:
  3385             return NEG;
  3386         case BANG:
  3387             return NOT;
  3388         case TILDE:
  3389             return COMPL;
  3390         case PLUSPLUS:
  3391             return PREINC;
  3392         case SUBSUB:
  3393             return PREDEC;
  3394         default:
  3395             return NO_TAG;
  3399     /** Return type tag of basic type represented by token,
  3400      *  NONE if token is not a basic type identifier.
  3401      */
  3402     static TypeTag typetag(TokenKind token) {
  3403         switch (token) {
  3404         case BYTE:
  3405             return TypeTag.BYTE;
  3406         case CHAR:
  3407             return TypeTag.CHAR;
  3408         case SHORT:
  3409             return TypeTag.SHORT;
  3410         case INT:
  3411             return TypeTag.INT;
  3412         case LONG:
  3413             return TypeTag.LONG;
  3414         case FLOAT:
  3415             return TypeTag.FLOAT;
  3416         case DOUBLE:
  3417             return TypeTag.DOUBLE;
  3418         case BOOLEAN:
  3419             return TypeTag.BOOLEAN;
  3420         default:
  3421             return TypeTag.NONE;
  3425     void checkGenerics() {
  3426         if (!allowGenerics) {
  3427             error(token.pos, "generics.not.supported.in.source", source.name);
  3428             allowGenerics = true;
  3431     void checkVarargs() {
  3432         if (!allowVarargs) {
  3433             error(token.pos, "varargs.not.supported.in.source", source.name);
  3434             allowVarargs = true;
  3437     void checkForeach() {
  3438         if (!allowForeach) {
  3439             error(token.pos, "foreach.not.supported.in.source", source.name);
  3440             allowForeach = true;
  3443     void checkStaticImports() {
  3444         if (!allowStaticImport) {
  3445             error(token.pos, "static.import.not.supported.in.source", source.name);
  3446             allowStaticImport = true;
  3449     void checkAnnotations() {
  3450         if (!allowAnnotations) {
  3451             error(token.pos, "annotations.not.supported.in.source", source.name);
  3452             allowAnnotations = true;
  3455     void checkDiamond() {
  3456         if (!allowDiamond) {
  3457             error(token.pos, "diamond.not.supported.in.source", source.name);
  3458             allowDiamond = true;
  3461     void checkMulticatch() {
  3462         if (!allowMulticatch) {
  3463             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3464             allowMulticatch = true;
  3467     void checkTryWithResources() {
  3468         if (!allowTWR) {
  3469             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3470             allowTWR = true;
  3473     void checkLambda() {
  3474         if (!allowLambda) {
  3475             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3476             allowLambda = true;
  3479     void checkMethodReferences() {
  3480         if (!allowMethodReferences) {
  3481             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3482             allowMethodReferences = true;
  3485     void checkDefaultMethods() {
  3486         if (!allowDefaultMethods) {
  3487             log.error(token.pos, "default.methods.not.supported.in.source", source.name);
  3488             allowDefaultMethods = true;
  3491     void checkIntersectionTypesInCast() {
  3492         if (!allowIntersectionTypesInCast) {
  3493             log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
  3494             allowIntersectionTypesInCast = true;
  3498     /*
  3499      * a functional source tree and end position mappings
  3500      */
  3501     protected class SimpleEndPosTable extends AbstractEndPosTable {
  3503         private final Map<JCTree, Integer> endPosMap;
  3505         SimpleEndPosTable() {
  3506             endPosMap = new HashMap<JCTree, Integer>();
  3509         protected void storeEnd(JCTree tree, int endpos) {
  3510             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  3513         protected <T extends JCTree> T to(T t) {
  3514             storeEnd(t, token.endPos);
  3515             return t;
  3518         protected <T extends JCTree> T toP(T t) {
  3519             storeEnd(t, S.prevToken().endPos);
  3520             return t;
  3523         public int getEndPos(JCTree tree) {
  3524             Integer value = endPosMap.get(tree);
  3525             return (value == null) ? Position.NOPOS : value;
  3528         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3529             Integer pos = endPosMap.remove(oldTree);
  3530             if (pos != null) {
  3531                 endPosMap.put(newTree, pos);
  3532                 return pos;
  3534             return Position.NOPOS;
  3538     /*
  3539      * a default skeletal implementation without any mapping overhead.
  3540      */
  3541     protected class EmptyEndPosTable extends AbstractEndPosTable {
  3543         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  3545         protected <T extends JCTree> T to(T t) {
  3546             return t;
  3549         protected <T extends JCTree> T toP(T t) {
  3550             return t;
  3553         public int getEndPos(JCTree tree) {
  3554             return Position.NOPOS;
  3557         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3558             return Position.NOPOS;
  3563     protected abstract class AbstractEndPosTable implements EndPosTable {
  3565         /**
  3566          * Store the last error position.
  3567          */
  3568         protected int errorEndPos;
  3570         /**
  3571          * Store ending position for a tree, the value of which is the greater
  3572          * of last error position and the given ending position.
  3573          * @param tree   The tree.
  3574          * @param endpos The ending position to associate with the tree.
  3575          */
  3576         protected abstract void storeEnd(JCTree tree, int endpos);
  3578         /**
  3579          * Store current token's ending position for a tree, the value of which
  3580          * will be the greater of last error position and the ending position of
  3581          * the current token.
  3582          * @param t The tree.
  3583          */
  3584         protected abstract <T extends JCTree> T to(T t);
  3586         /**
  3587          * Store current token's ending position for a tree, the value of which
  3588          * will be the greater of last error position and the ending position of
  3589          * the previous token.
  3590          * @param t The tree.
  3591          */
  3592         protected abstract <T extends JCTree> T toP(T t);
  3594         /**
  3595          * Set the error position during the parsing phases, the value of which
  3596          * will be set only if it is greater than the last stored error position.
  3597          * @param errPos The error position
  3598          */
  3599         protected void setErrorEndPos(int errPos) {
  3600             if (errPos > errorEndPos) {
  3601                 errorEndPos = errPos;

mercurial