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

Tue, 18 Dec 2012 00:24:54 -0800

author
darcy
date
Tue, 18 Dec 2012 00:24:54 -0800
changeset 1459
bc74006c2d8d
parent 1444
170e486632d9
child 1503
2d2b2be57c78
permissions
-rw-r--r--

8005046: Provide checking for a default method in javax.lang.model
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 =
   128                 source.allowIntersectionTypesInCast() &&
   129                 fac.options.isSet("allowIntersectionTypes");
   130         this.keepDocComments = keepDocComments;
   131         docComments = newDocCommentTable(keepDocComments, fac);
   132         this.keepLineMap = keepLineMap;
   133         this.errorTree = F.Erroneous();
   134         endPosTable = newEndPosTable(keepEndPositions);
   135     }
   137     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
   138         return  keepEndPositions
   139                 ? new SimpleEndPosTable()
   140                 : new EmptyEndPosTable();
   141     }
   143     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
   144         return keepDocComments ? new LazyDocCommentTable(fac) : null;
   145     }
   147     /** Switch: Should generics be recognized?
   148      */
   149     boolean allowGenerics;
   151     /** Switch: Should diamond operator be recognized?
   152      */
   153     boolean allowDiamond;
   155     /** Switch: Should multicatch clause be accepted?
   156      */
   157     boolean allowMulticatch;
   159     /** Switch: Should varargs be recognized?
   160      */
   161     boolean allowVarargs;
   163     /** Switch: should we recognize assert statements, or just give a warning?
   164      */
   165     boolean allowAsserts;
   167     /** Switch: should we recognize enums, or just give a warning?
   168      */
   169     boolean allowEnums;
   171     /** Switch: should we recognize foreach?
   172      */
   173     boolean allowForeach;
   175     /** Switch: should we recognize foreach?
   176      */
   177     boolean allowStaticImport;
   179     /** Switch: should we recognize annotations?
   180      */
   181     boolean allowAnnotations;
   183     /** Switch: should we recognize try-with-resources?
   184      */
   185     boolean allowTWR;
   187     /** Switch: should we fold strings?
   188      */
   189     boolean allowStringFolding;
   191     /** Switch: should we recognize lambda expressions?
   192      */
   193     boolean allowLambda;
   195     /** Switch: should we allow method/constructor references?
   196      */
   197     boolean allowMethodReferences;
   199     /** Switch: should we allow default methods in interfaces?
   200      */
   201     boolean allowDefaultMethods;
   203     /** Switch: should we allow intersection types in cast?
   204      */
   205     boolean allowIntersectionTypesInCast;
   207     /** Switch: should we keep docComments?
   208      */
   209     boolean keepDocComments;
   211     /** Switch: should we keep line table?
   212      */
   213     boolean keepLineMap;
   215     /** When terms are parsed, the mode determines which is expected:
   216      *     mode = EXPR        : an expression
   217      *     mode = TYPE        : a type
   218      *     mode = NOPARAMS    : no parameters allowed for type
   219      *     mode = TYPEARG     : type argument
   220      */
   221     static final int EXPR = 0x1;
   222     static final int TYPE = 0x2;
   223     static final int NOPARAMS = 0x4;
   224     static final int TYPEARG = 0x8;
   225     static final int DIAMOND = 0x10;
   227     /** The current mode.
   228      */
   229     private int mode = 0;
   231     /** The mode of the term that was parsed last.
   232      */
   233     private int lastmode = 0;
   235     /* ---------- token management -------------- */
   237     protected Token token;
   239     public Token token() {
   240         return token;
   241     }
   243     public void nextToken() {
   244         S.nextToken();
   245         token = S.token();
   246     }
   248     protected boolean peekToken(TokenKind tk) {
   249         return peekToken(0, tk);
   250     }
   252     protected boolean peekToken(int lookahead, TokenKind tk) {
   253         return S.token(lookahead + 1).kind == tk;
   254     }
   256     protected boolean peekToken(TokenKind tk1, TokenKind tk2) {
   257         return peekToken(0, tk1, tk2);
   258     }
   260     protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2) {
   261         return S.token(lookahead + 1).kind == tk1 &&
   262                 S.token(lookahead + 2).kind == tk2;
   263     }
   265     protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) {
   266         return peekToken(0, tk1, tk2, tk3);
   267     }
   269     protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2, TokenKind tk3) {
   270         return S.token(lookahead + 1).kind == tk1 &&
   271                 S.token(lookahead + 2).kind == tk2 &&
   272                 S.token(lookahead + 3).kind == tk3;
   273     }
   275     protected boolean peekToken(TokenKind... kinds) {
   276         return peekToken(0, kinds);
   277     }
   279     protected boolean peekToken(int lookahead, TokenKind... kinds) {
   280         for (; lookahead < kinds.length ; lookahead++) {
   281             if (S.token(lookahead + 1).kind != kinds[lookahead]) {
   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 IDENTIFIER:
   337                    if (stopAtIdentifier)
   338                         return;
   339                     break;
   340                 case CASE:
   341                 case DEFAULT:
   342                 case IF:
   343                 case FOR:
   344                 case WHILE:
   345                 case DO:
   346                 case TRY:
   347                 case SWITCH:
   348                 case RETURN:
   349                 case THROW:
   350                 case BREAK:
   351                 case CONTINUE:
   352                 case ELSE:
   353                 case FINALLY:
   354                 case CATCH:
   355                     if (stopAtStatement)
   356                         return;
   357                     break;
   358             }
   359             nextToken();
   360         }
   361     }
   363     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   364         return syntaxError(pos, List.<JCTree>nil(), key, args);
   365     }
   367     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   368         setErrorEndPos(pos);
   369         JCErroneous err = F.at(pos).Erroneous(errs);
   370         reportSyntaxError(err, key, (Object[])args);
   371         if (errs != null) {
   372             JCTree last = errs.last();
   373             if (last != null)
   374                 storeEnd(last, pos);
   375         }
   376         return toP(err);
   377     }
   379     private int errorPos = Position.NOPOS;
   381     /**
   382      * Report a syntax using the given the position parameter and arguments,
   383      * unless one was already reported at the same position.
   384      */
   385     private void reportSyntaxError(int pos, String key, Object... args) {
   386         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   387         reportSyntaxError(diag, key, args);
   388     }
   390     /**
   391      * Report a syntax error using the given DiagnosticPosition object and
   392      * arguments, unless one was already reported at the same position.
   393      */
   394     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   395         int pos = diagPos.getPreferredPosition();
   396         if (pos > S.errPos() || pos == Position.NOPOS) {
   397             if (token.kind == EOF) {
   398                 error(diagPos, "premature.eof");
   399             } else {
   400                 error(diagPos, key, args);
   401             }
   402         }
   403         S.errPos(pos);
   404         if (token.pos == errorPos)
   405             nextToken(); // guarantee progress
   406         errorPos = token.pos;
   407     }
   410     /** Generate a syntax error at current position unless one was already
   411      *  reported at the same position.
   412      */
   413     private JCErroneous syntaxError(String key) {
   414         return syntaxError(token.pos, key);
   415     }
   417     /** Generate a syntax error at current position unless one was
   418      *  already reported at the same position.
   419      */
   420     private JCErroneous syntaxError(String key, TokenKind arg) {
   421         return syntaxError(token.pos, key, arg);
   422     }
   424     /** If next input token matches given token, skip it, otherwise report
   425      *  an error.
   426      */
   427     public void accept(TokenKind tk) {
   428         if (token.kind == tk) {
   429             nextToken();
   430         } else {
   431             setErrorEndPos(token.pos);
   432             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   433         }
   434     }
   436     /** Report an illegal start of expression/type error at given position.
   437      */
   438     JCExpression illegal(int pos) {
   439         setErrorEndPos(pos);
   440         if ((mode & EXPR) != 0)
   441             return syntaxError(pos, "illegal.start.of.expr");
   442         else
   443             return syntaxError(pos, "illegal.start.of.type");
   445     }
   447     /** Report an illegal start of expression/type error at current position.
   448      */
   449     JCExpression illegal() {
   450         return illegal(token.pos);
   451     }
   453     /** Diagnose a modifier flag from the set, if any. */
   454     void checkNoMods(long mods) {
   455         if (mods != 0) {
   456             long lowestMod = mods & -mods;
   457             error(token.pos, "mod.not.allowed.here",
   458                       Flags.asFlagSet(lowestMod));
   459         }
   460     }
   462 /* ---------- doc comments --------- */
   464     /** A table to store all documentation comments
   465      *  indexed by the tree nodes they refer to.
   466      *  defined only if option flag keepDocComment is set.
   467      */
   468     private final DocCommentTable docComments;
   470     /** Make an entry into docComments hashtable,
   471      *  provided flag keepDocComments is set and given doc comment is non-null.
   472      *  @param tree   The tree to be used as index in the hashtable
   473      *  @param dc     The doc comment to associate with the tree, or null.
   474      */
   475     void attach(JCTree tree, Comment dc) {
   476         if (keepDocComments && dc != null) {
   477 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   478             docComments.putComment(tree, dc);
   479         }
   480     }
   482 /* -------- source positions ------- */
   484     private void setErrorEndPos(int errPos) {
   485         endPosTable.setErrorEndPos(errPos);
   486     }
   488     private void storeEnd(JCTree tree, int endpos) {
   489         endPosTable.storeEnd(tree, endpos);
   490     }
   492     private <T extends JCTree> T to(T t) {
   493         return endPosTable.to(t);
   494     }
   496     private <T extends JCTree> T toP(T t) {
   497         return endPosTable.toP(t);
   498     }
   500     /** Get the start position for a tree node.  The start position is
   501      * defined to be the position of the first character of the first
   502      * token of the node's source text.
   503      * @param tree  The tree node
   504      */
   505     public int getStartPos(JCTree tree) {
   506         return TreeInfo.getStartPos(tree);
   507     }
   509     /**
   510      * Get the end position for a tree node.  The end position is
   511      * defined to be the position of the last character of the last
   512      * token of the node's source text.  Returns Position.NOPOS if end
   513      * positions are not generated or the position is otherwise not
   514      * found.
   515      * @param tree  The tree node
   516      */
   517     public int getEndPos(JCTree tree) {
   518         return endPosTable.getEndPos(tree);
   519     }
   523 /* ---------- parsing -------------- */
   525     /**
   526      * Ident = IDENTIFIER
   527      */
   528     Name ident() {
   529         if (token.kind == IDENTIFIER) {
   530             Name name = token.name();
   531             nextToken();
   532             return name;
   533         } else if (token.kind == ASSERT) {
   534             if (allowAsserts) {
   535                 error(token.pos, "assert.as.identifier");
   536                 nextToken();
   537                 return names.error;
   538             } else {
   539                 warning(token.pos, "assert.as.identifier");
   540                 Name name = token.name();
   541                 nextToken();
   542                 return name;
   543             }
   544         } else if (token.kind == ENUM) {
   545             if (allowEnums) {
   546                 error(token.pos, "enum.as.identifier");
   547                 nextToken();
   548                 return names.error;
   549             } else {
   550                 warning(token.pos, "enum.as.identifier");
   551                 Name name = token.name();
   552                 nextToken();
   553                 return name;
   554             }
   555         } else {
   556             accept(IDENTIFIER);
   557             return names.error;
   558         }
   559 }
   561     /**
   562      * Qualident = Ident { DOT Ident }
   563      */
   564     public JCExpression qualident() {
   565         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   566         while (token.kind == DOT) {
   567             int pos = token.pos;
   568             nextToken();
   569             t = toP(F.at(pos).Select(t, ident()));
   570         }
   571         return t;
   572     }
   574     JCExpression literal(Name prefix) {
   575         return literal(prefix, token.pos);
   576     }
   578     /**
   579      * Literal =
   580      *     INTLITERAL
   581      *   | LONGLITERAL
   582      *   | FLOATLITERAL
   583      *   | DOUBLELITERAL
   584      *   | CHARLITERAL
   585      *   | STRINGLITERAL
   586      *   | TRUE
   587      *   | FALSE
   588      *   | NULL
   589      */
   590     JCExpression literal(Name prefix, int pos) {
   591         JCExpression t = errorTree;
   592         switch (token.kind) {
   593         case INTLITERAL:
   594             try {
   595                 t = F.at(pos).Literal(
   596                     TypeTag.INT,
   597                     Convert.string2int(strval(prefix), token.radix()));
   598             } catch (NumberFormatException ex) {
   599                 error(token.pos, "int.number.too.large", strval(prefix));
   600             }
   601             break;
   602         case LONGLITERAL:
   603             try {
   604                 t = F.at(pos).Literal(
   605                     TypeTag.LONG,
   606                     new Long(Convert.string2long(strval(prefix), token.radix())));
   607             } catch (NumberFormatException ex) {
   608                 error(token.pos, "int.number.too.large", strval(prefix));
   609             }
   610             break;
   611         case FLOATLITERAL: {
   612             String proper = token.radix() == 16 ?
   613                     ("0x"+ token.stringVal()) :
   614                     token.stringVal();
   615             Float n;
   616             try {
   617                 n = Float.valueOf(proper);
   618             } catch (NumberFormatException ex) {
   619                 // error already reported in scanner
   620                 n = Float.NaN;
   621             }
   622             if (n.floatValue() == 0.0f && !isZero(proper))
   623                 error(token.pos, "fp.number.too.small");
   624             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   625                 error(token.pos, "fp.number.too.large");
   626             else
   627                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
   628             break;
   629         }
   630         case DOUBLELITERAL: {
   631             String proper = token.radix() == 16 ?
   632                     ("0x"+ token.stringVal()) :
   633                     token.stringVal();
   634             Double n;
   635             try {
   636                 n = Double.valueOf(proper);
   637             } catch (NumberFormatException ex) {
   638                 // error already reported in scanner
   639                 n = Double.NaN;
   640             }
   641             if (n.doubleValue() == 0.0d && !isZero(proper))
   642                 error(token.pos, "fp.number.too.small");
   643             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   644                 error(token.pos, "fp.number.too.large");
   645             else
   646                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
   647             break;
   648         }
   649         case CHARLITERAL:
   650             t = F.at(pos).Literal(
   651                 TypeTag.CHAR,
   652                 token.stringVal().charAt(0) + 0);
   653             break;
   654         case STRINGLITERAL:
   655             t = F.at(pos).Literal(
   656                 TypeTag.CLASS,
   657                 token.stringVal());
   658             break;
   659         case TRUE: case FALSE:
   660             t = F.at(pos).Literal(
   661                 TypeTag.BOOLEAN,
   662                 (token.kind == TRUE ? 1 : 0));
   663             break;
   664         case NULL:
   665             t = F.at(pos).Literal(
   666                 TypeTag.BOT,
   667                 null);
   668             break;
   669         default:
   670             Assert.error();
   671         }
   672         if (t == errorTree)
   673             t = F.at(pos).Erroneous();
   674         storeEnd(t, token.endPos);
   675         nextToken();
   676         return t;
   677     }
   678 //where
   679         boolean isZero(String s) {
   680             char[] cs = s.toCharArray();
   681             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   682             int i = ((base==16) ? 2 : 0);
   683             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   684             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   685         }
   687         String strval(Name prefix) {
   688             String s = token.stringVal();
   689             return prefix.isEmpty() ? s : prefix + s;
   690         }
   692     /** terms can be either expressions or types.
   693      */
   694     public JCExpression parseExpression() {
   695         return term(EXPR);
   696     }
   698     public JCExpression parseType() {
   699         return term(TYPE);
   700     }
   702     JCExpression term(int newmode) {
   703         int prevmode = mode;
   704         mode = newmode;
   705         JCExpression t = term();
   706         lastmode = mode;
   707         mode = prevmode;
   708         return t;
   709     }
   711     /**
   712      *  {@literal
   713      *  Expression = Expression1 [ExpressionRest]
   714      *  ExpressionRest = [AssignmentOperator Expression1]
   715      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   716      *                       "&=" | "|=" | "^=" |
   717      *                       "%=" | "<<=" | ">>=" | ">>>="
   718      *  Type = Type1
   719      *  TypeNoParams = TypeNoParams1
   720      *  StatementExpression = Expression
   721      *  ConstantExpression = Expression
   722      *  }
   723      */
   724     JCExpression term() {
   725         JCExpression t = term1();
   726         if ((mode & EXPR) != 0 &&
   727             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   728             return termRest(t);
   729         else
   730             return t;
   731     }
   733     JCExpression termRest(JCExpression t) {
   734         switch (token.kind) {
   735         case EQ: {
   736             int pos = token.pos;
   737             nextToken();
   738             mode = EXPR;
   739             JCExpression t1 = term();
   740             return toP(F.at(pos).Assign(t, t1));
   741         }
   742         case PLUSEQ:
   743         case SUBEQ:
   744         case STAREQ:
   745         case SLASHEQ:
   746         case PERCENTEQ:
   747         case AMPEQ:
   748         case BAREQ:
   749         case CARETEQ:
   750         case LTLTEQ:
   751         case GTGTEQ:
   752         case GTGTGTEQ:
   753             int pos = token.pos;
   754             TokenKind tk = token.kind;
   755             nextToken();
   756             mode = EXPR;
   757             JCExpression t1 = term();
   758             return F.at(pos).Assignop(optag(tk), t, t1);
   759         default:
   760             return t;
   761         }
   762     }
   764     /** Expression1   = Expression2 [Expression1Rest]
   765      *  Type1         = Type2
   766      *  TypeNoParams1 = TypeNoParams2
   767      */
   768     JCExpression term1() {
   769         JCExpression t = term2();
   770         if ((mode & EXPR) != 0 && token.kind == QUES) {
   771             mode = EXPR;
   772             return term1Rest(t);
   773         } else {
   774             return t;
   775         }
   776     }
   778     /** Expression1Rest = ["?" Expression ":" Expression1]
   779      */
   780     JCExpression term1Rest(JCExpression t) {
   781         if (token.kind == QUES) {
   782             int pos = token.pos;
   783             nextToken();
   784             JCExpression t1 = term();
   785             accept(COLON);
   786             JCExpression t2 = term1();
   787             return F.at(pos).Conditional(t, t1, t2);
   788         } else {
   789             return t;
   790         }
   791     }
   793     /** Expression2   = Expression3 [Expression2Rest]
   794      *  Type2         = Type3
   795      *  TypeNoParams2 = TypeNoParams3
   796      */
   797     JCExpression term2() {
   798         JCExpression t = term3();
   799         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   800             mode = EXPR;
   801             return term2Rest(t, TreeInfo.orPrec);
   802         } else {
   803             return t;
   804         }
   805     }
   807     /*  Expression2Rest = {infixop Expression3}
   808      *                  | Expression3 instanceof Type
   809      *  infixop         = "||"
   810      *                  | "&&"
   811      *                  | "|"
   812      *                  | "^"
   813      *                  | "&"
   814      *                  | "==" | "!="
   815      *                  | "<" | ">" | "<=" | ">="
   816      *                  | "<<" | ">>" | ">>>"
   817      *                  | "+" | "-"
   818      *                  | "*" | "/" | "%"
   819      */
   820     JCExpression term2Rest(JCExpression t, int minprec) {
   821         JCExpression[] odStack = newOdStack();
   822         Token[] opStack = newOpStack();
   824         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   825         int top = 0;
   826         odStack[0] = t;
   827         int startPos = token.pos;
   828         Token topOp = Tokens.DUMMY;
   829         while (prec(token.kind) >= minprec) {
   830             opStack[top] = topOp;
   831             top++;
   832             topOp = token;
   833             nextToken();
   834             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   835             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   836                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   837                                         odStack[top]);
   838                 top--;
   839                 topOp = opStack[top];
   840             }
   841         }
   842         Assert.check(top == 0);
   843         t = odStack[0];
   845         if (t.hasTag(JCTree.Tag.PLUS)) {
   846             StringBuilder buf = foldStrings(t);
   847             if (buf != null) {
   848                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
   849             }
   850         }
   852         odStackSupply.add(odStack);
   853         opStackSupply.add(opStack);
   854         return t;
   855     }
   856 //where
   857         /** Construct a binary or type test node.
   858          */
   859         private JCExpression makeOp(int pos,
   860                                     TokenKind topOp,
   861                                     JCExpression od1,
   862                                     JCExpression od2)
   863         {
   864             if (topOp == INSTANCEOF) {
   865                 return F.at(pos).TypeTest(od1, od2);
   866             } else {
   867                 return F.at(pos).Binary(optag(topOp), od1, od2);
   868             }
   869         }
   870         /** If tree is a concatenation of string literals, replace it
   871          *  by a single literal representing the concatenated string.
   872          */
   873         protected StringBuilder foldStrings(JCTree tree) {
   874             if (!allowStringFolding)
   875                 return null;
   876             List<String> buf = List.nil();
   877             while (true) {
   878                 if (tree.hasTag(LITERAL)) {
   879                     JCLiteral lit = (JCLiteral) tree;
   880                     if (lit.typetag == TypeTag.CLASS) {
   881                         StringBuilder sbuf =
   882                             new StringBuilder((String)lit.value);
   883                         while (buf.nonEmpty()) {
   884                             sbuf.append(buf.head);
   885                             buf = buf.tail;
   886                         }
   887                         return sbuf;
   888                     }
   889                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   890                     JCBinary op = (JCBinary)tree;
   891                     if (op.rhs.hasTag(LITERAL)) {
   892                         JCLiteral lit = (JCLiteral) op.rhs;
   893                         if (lit.typetag == TypeTag.CLASS) {
   894                             buf = buf.prepend((String) lit.value);
   895                             tree = op.lhs;
   896                             continue;
   897                         }
   898                     }
   899                 }
   900                 return null;
   901             }
   902         }
   904         /** optimization: To save allocating a new operand/operator stack
   905          *  for every binary operation, we use supplys.
   906          */
   907         ArrayList<JCExpression[]> odStackSupply = new ArrayList<JCExpression[]>();
   908         ArrayList<Token[]> opStackSupply = new ArrayList<Token[]>();
   910         private JCExpression[] newOdStack() {
   911             if (odStackSupply.isEmpty())
   912                 return new JCExpression[infixPrecedenceLevels + 1];
   913             return odStackSupply.remove(odStackSupply.size() - 1);
   914         }
   916         private Token[] newOpStack() {
   917             if (opStackSupply.isEmpty())
   918                 return new Token[infixPrecedenceLevels + 1];
   919             return opStackSupply.remove(opStackSupply.size() - 1);
   920         }
   922     /**
   923      *  Expression3    = PrefixOp Expression3
   924      *                 | "(" Expr | TypeNoParams ")" Expression3
   925      *                 | Primary {Selector} {PostfixOp}
   926      *
   927      *  {@literal
   928      *  Primary        = "(" Expression ")"
   929      *                 | Literal
   930      *                 | [TypeArguments] THIS [Arguments]
   931      *                 | [TypeArguments] SUPER SuperSuffix
   932      *                 | NEW [TypeArguments] Creator
   933      *                 | "(" Arguments ")" "->" ( Expression | Block )
   934      *                 | Ident "->" ( Expression | Block )
   935      *                 | Ident { "." Ident }
   936      *                 | Expression3 MemberReferenceSuffix
   937      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   938      *                   | Arguments
   939      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   940      *                   ]
   941      *                 | BasicType BracketsOpt "." CLASS
   942      *  }
   943      *
   944      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   945      *  PostfixOp      = "++" | "--"
   946      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   947      *                 | BasicType
   948      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   949      *  Selector       = "." [TypeArguments] Ident [Arguments]
   950      *                 | "." THIS
   951      *                 | "." [TypeArguments] SUPER SuperSuffix
   952      *                 | "." NEW [TypeArguments] InnerCreator
   953      *                 | "[" Expression "]"
   954      *  TypeSelector   = "." Ident [TypeArguments]
   955      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   956      */
   957     protected JCExpression term3() {
   958         int pos = token.pos;
   959         JCExpression t;
   960         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   961         switch (token.kind) {
   962         case QUES:
   963             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   964                 mode = TYPE;
   965                 return typeArgument();
   966             } else
   967                 return illegal();
   968         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   969             if (typeArgs == null && (mode & EXPR) != 0) {
   970                 TokenKind tk = token.kind;
   971                 nextToken();
   972                 mode = EXPR;
   973                 if (tk == SUB &&
   974                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
   975                     token.radix() == 10) {
   976                     mode = EXPR;
   977                     t = literal(names.hyphen, pos);
   978                 } else {
   979                     t = term3();
   980                     return F.at(pos).Unary(unoptag(tk), t);
   981                 }
   982             } else return illegal();
   983             break;
   984         case LPAREN:
   985             if (typeArgs == null && (mode & EXPR) != 0) {
   986                 ParensResult pres = analyzeParens();
   987                 switch (pres) {
   988                     case CAST:
   989                        accept(LPAREN);
   990                        mode = TYPE;
   991                        int pos1 = pos;
   992                        List<JCExpression> targets = List.of(t = term3());
   993                        while (token.kind == AMP) {
   994                            checkIntersectionTypesInCast();
   995                            accept(AMP);
   996                            targets = targets.prepend(term3());
   997                        }
   998                        if (targets.length() > 1) {
   999                            t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
  1001                        accept(RPAREN);
  1002                        mode = EXPR;
  1003                        JCExpression t1 = term3();
  1004                        return F.at(pos).TypeCast(t, t1);
  1005                     case IMPLICIT_LAMBDA:
  1006                     case EXPLICIT_LAMBDA:
  1007                         t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
  1008                         break;
  1009                     default: //PARENS
  1010                         accept(LPAREN);
  1011                         mode = EXPR;
  1012                         t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
  1013                         accept(RPAREN);
  1014                         t = toP(F.at(pos).Parens(t));
  1015                         break;
  1017             } else {
  1018                 return illegal();
  1020             break;
  1021         case THIS:
  1022             if ((mode & EXPR) != 0) {
  1023                 mode = EXPR;
  1024                 t = to(F.at(pos).Ident(names._this));
  1025                 nextToken();
  1026                 if (typeArgs == null)
  1027                     t = argumentsOpt(null, t);
  1028                 else
  1029                     t = arguments(typeArgs, t);
  1030                 typeArgs = null;
  1031             } else return illegal();
  1032             break;
  1033         case SUPER:
  1034             if ((mode & EXPR) != 0) {
  1035                 mode = EXPR;
  1036                 t = to(F.at(pos).Ident(names._super));
  1037                 t = superSuffix(typeArgs, t);
  1038                 typeArgs = null;
  1039             } else return illegal();
  1040             break;
  1041         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1042         case CHARLITERAL: case STRINGLITERAL:
  1043         case TRUE: case FALSE: case NULL:
  1044             if (typeArgs == null && (mode & EXPR) != 0) {
  1045                 mode = EXPR;
  1046                 t = literal(names.empty);
  1047             } else return illegal();
  1048             break;
  1049         case NEW:
  1050             if (typeArgs != null) return illegal();
  1051             if ((mode & EXPR) != 0) {
  1052                 mode = EXPR;
  1053                 nextToken();
  1054                 if (token.kind == LT) typeArgs = typeArguments(false);
  1055                 t = creator(pos, typeArgs);
  1056                 typeArgs = null;
  1057             } else return illegal();
  1058             break;
  1059         case IDENTIFIER: case ASSERT: case ENUM:
  1060             if (typeArgs != null) return illegal();
  1061             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1062                 t = lambdaExpressionOrStatement(false, false, pos);
  1063             } else {
  1064                 t = toP(F.at(token.pos).Ident(ident()));
  1065                 loop: while (true) {
  1066                     pos = token.pos;
  1067                     switch (token.kind) {
  1068                     case LBRACKET:
  1069                         nextToken();
  1070                         if (token.kind == RBRACKET) {
  1071                             nextToken();
  1072                             t = bracketsOpt(t);
  1073                             t = toP(F.at(pos).TypeArray(t));
  1074                             t = bracketsSuffix(t);
  1075                         } else {
  1076                             if ((mode & EXPR) != 0) {
  1077                                 mode = EXPR;
  1078                                 JCExpression t1 = term();
  1079                                 t = to(F.at(pos).Indexed(t, t1));
  1081                             accept(RBRACKET);
  1083                         break loop;
  1084                     case LPAREN:
  1085                         if ((mode & EXPR) != 0) {
  1086                             mode = EXPR;
  1087                             t = arguments(typeArgs, t);
  1088                             typeArgs = null;
  1090                         break loop;
  1091                     case DOT:
  1092                         nextToken();
  1093                         int oldmode = mode;
  1094                         mode &= ~NOPARAMS;
  1095                         typeArgs = typeArgumentsOpt(EXPR);
  1096                         mode = oldmode;
  1097                         if ((mode & EXPR) != 0) {
  1098                             switch (token.kind) {
  1099                             case CLASS:
  1100                                 if (typeArgs != null) return illegal();
  1101                                 mode = EXPR;
  1102                                 t = to(F.at(pos).Select(t, names._class));
  1103                                 nextToken();
  1104                                 break loop;
  1105                             case THIS:
  1106                                 if (typeArgs != null) return illegal();
  1107                                 mode = EXPR;
  1108                                 t = to(F.at(pos).Select(t, names._this));
  1109                                 nextToken();
  1110                                 break loop;
  1111                             case SUPER:
  1112                                 mode = EXPR;
  1113                                 t = to(F.at(pos).Select(t, names._super));
  1114                                 t = superSuffix(typeArgs, t);
  1115                                 typeArgs = null;
  1116                                 break loop;
  1117                             case NEW:
  1118                                 if (typeArgs != null) return illegal();
  1119                                 mode = EXPR;
  1120                                 int pos1 = token.pos;
  1121                                 nextToken();
  1122                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1123                                 t = innerCreator(pos1, typeArgs, t);
  1124                                 typeArgs = null;
  1125                                 break loop;
  1128                         // typeArgs saved for next loop iteration.
  1129                         t = toP(F.at(pos).Select(t, ident()));
  1130                         break;
  1131                     case LT:
  1132                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1133                             //this is an unbound method reference whose qualifier
  1134                             //is a generic type i.e. A<S>::m
  1135                             int pos1 = token.pos;
  1136                             accept(LT);
  1137                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1138                             args.append(typeArgument());
  1139                             while (token.kind == COMMA) {
  1140                                 nextToken();
  1141                                 args.append(typeArgument());
  1143                             accept(GT);
  1144                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1145                             checkGenerics();
  1146                             while (token.kind == DOT) {
  1147                                 nextToken();
  1148                                 mode = TYPE;
  1149                                 t = toP(F.at(token.pos).Select(t, ident()));
  1150                                 t = typeArgumentsOpt(t);
  1152                             t = bracketsOpt(t);
  1153                             if (token.kind != COLCOL) {
  1154                                 //method reference expected here
  1155                                 t = illegal();
  1157                             mode = EXPR;
  1158                             return term3Rest(t, typeArgs);
  1160                         break loop;
  1161                     default:
  1162                         break loop;
  1166             if (typeArgs != null) illegal();
  1167             t = typeArgumentsOpt(t);
  1168             break;
  1169         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1170         case DOUBLE: case BOOLEAN:
  1171             if (typeArgs != null) illegal();
  1172             t = bracketsSuffix(bracketsOpt(basicType()));
  1173             break;
  1174         case VOID:
  1175             if (typeArgs != null) illegal();
  1176             if ((mode & EXPR) != 0) {
  1177                 nextToken();
  1178                 if (token.kind == DOT) {
  1179                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
  1180                     t = bracketsSuffix(ti);
  1181                 } else {
  1182                     return illegal(pos);
  1184             } else {
  1185                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1186                 // a void type (like other primitive types) to the next phase.
  1187                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1188                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
  1189                 nextToken();
  1190                 return ti;
  1191                 //return illegal();
  1193             break;
  1194         default:
  1195             return illegal();
  1197         return term3Rest(t, typeArgs);
  1200     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1201         if (typeArgs != null) illegal();
  1202         while (true) {
  1203             int pos1 = token.pos;
  1204             if (token.kind == LBRACKET) {
  1205                 nextToken();
  1206                 if ((mode & TYPE) != 0) {
  1207                     int oldmode = mode;
  1208                     mode = TYPE;
  1209                     if (token.kind == RBRACKET) {
  1210                         nextToken();
  1211                         t = bracketsOpt(t);
  1212                         t = toP(F.at(pos1).TypeArray(t));
  1213                         if (token.kind == COLCOL) {
  1214                             mode = EXPR;
  1215                             continue;
  1217                         return t;
  1219                     mode = oldmode;
  1221                 if ((mode & EXPR) != 0) {
  1222                     mode = EXPR;
  1223                     JCExpression t1 = term();
  1224                     t = to(F.at(pos1).Indexed(t, t1));
  1226                 accept(RBRACKET);
  1227             } else if (token.kind == DOT) {
  1228                 nextToken();
  1229                 typeArgs = typeArgumentsOpt(EXPR);
  1230                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1231                     mode = EXPR;
  1232                     t = to(F.at(pos1).Select(t, names._super));
  1233                     nextToken();
  1234                     t = arguments(typeArgs, t);
  1235                     typeArgs = null;
  1236                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1237                     if (typeArgs != null) return illegal();
  1238                     mode = EXPR;
  1239                     int pos2 = token.pos;
  1240                     nextToken();
  1241                     if (token.kind == LT) typeArgs = typeArguments(false);
  1242                     t = innerCreator(pos2, typeArgs, t);
  1243                     typeArgs = null;
  1244                 } else {
  1245                     t = toP(F.at(pos1).Select(t, ident()));
  1246                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1247                     typeArgs = null;
  1249             } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
  1250                 mode = EXPR;
  1251                 if (typeArgs != null) return illegal();
  1252                 accept(COLCOL);
  1253                 t = memberReferenceSuffix(pos1, t);
  1254             } else {
  1255                 break;
  1258         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1259             mode = EXPR;
  1260             t = to(F.at(token.pos).Unary(
  1261                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1262             nextToken();
  1264         return toP(t);
  1267     /**
  1268      * If we see an identifier followed by a '&lt;' it could be an unbound
  1269      * method reference or a binary expression. To disambiguate, look for a
  1270      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1271      */
  1272     @SuppressWarnings("fallthrough")
  1273     boolean isUnboundMemberRef() {
  1274         int pos = 0, depth = 0;
  1275         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1276             switch (t.kind) {
  1277                 case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
  1278                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1279                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1280                 case DOUBLE: case BOOLEAN: case CHAR:
  1281                     break;
  1282                 case LT:
  1283                     depth++; break;
  1284                 case GTGTGT:
  1285                     depth--;
  1286                 case GTGT:
  1287                     depth--;
  1288                 case GT:
  1289                     depth--;
  1290                     if (depth == 0) {
  1291                         TokenKind nextKind = S.token(pos + 1).kind;
  1292                         return
  1293                             nextKind == TokenKind.DOT ||
  1294                             nextKind == TokenKind.LBRACKET ||
  1295                             nextKind == TokenKind.COLCOL;
  1297                     break;
  1298                 default:
  1299                     return false;
  1304     /**
  1305      * If we see an identifier followed by a '&lt;' it could be an unbound
  1306      * method reference or a binary expression. To disambiguate, look for a
  1307      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1308      */
  1309     @SuppressWarnings("fallthrough")
  1310     ParensResult analyzeParens() {
  1311         int depth = 0;
  1312         boolean type = false;
  1313         for (int lookahead = 0 ; ; lookahead++) {
  1314             TokenKind tk = S.token(lookahead).kind;
  1315             switch (tk) {
  1316                 case EXTENDS: case SUPER: case COMMA:
  1317                     type = true;
  1318                 case QUES: case DOT: case AMP:
  1319                     //skip
  1320                     break;
  1321                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1322                 case DOUBLE: case BOOLEAN: case CHAR:
  1323                     if (peekToken(lookahead, RPAREN)) {
  1324                         //Type, ')' -> cast
  1325                         return ParensResult.CAST;
  1326                     } else if (peekToken(lookahead, IDENTIFIER)) {
  1327                         //Type, 'Identifier -> explicit lambda
  1328                         return ParensResult.EXPLICIT_LAMBDA;
  1330                     break;
  1331                 case LPAREN:
  1332                     if (lookahead != 0) {
  1333                         // '(' in a non-starting position -> parens
  1334                         return ParensResult.PARENS;
  1335                     } else if (peekToken(lookahead, RPAREN)) {
  1336                         // '(', ')' -> explicit lambda
  1337                         return ParensResult.EXPLICIT_LAMBDA;
  1339                     break;
  1340                 case RPAREN:
  1341                     // if we have seen something that looks like a type,
  1342                     // then it's a cast expression
  1343                     if (type) return ParensResult.CAST;
  1344                     // otherwise, disambiguate cast vs. parenthesized expression
  1345                     // based on subsequent token.
  1346                     switch (S.token(lookahead + 1).kind) {
  1347                         /*case PLUSPLUS: case SUBSUB: */
  1348                         case BANG: case TILDE:
  1349                         case LPAREN: case THIS: case SUPER:
  1350                         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1351                         case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1352                         case TRUE: case FALSE: case NULL:
  1353                             case NEW: case IDENTIFIER: case ASSERT: case ENUM:
  1354                         case BYTE: case SHORT: case CHAR: case INT:
  1355                         case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1356                             return ParensResult.CAST;
  1357                         default:
  1358                             return ParensResult.PARENS;
  1360                 case IDENTIFIER:
  1361                     if (peekToken(lookahead, IDENTIFIER)) {
  1362                         // Identifier, Identifier -> explicit lambda
  1363                         return ParensResult.EXPLICIT_LAMBDA;
  1364                     } else if (peekToken(lookahead, RPAREN, ARROW)) {
  1365                         // Identifier, ')' '->' -> implicit lambda
  1366                         return ParensResult.IMPLICIT_LAMBDA;
  1368                     break;
  1369                 case FINAL:
  1370                 case ELLIPSIS:
  1371                 case MONKEYS_AT:
  1372                     //those can only appear in explicit lambdas
  1373                     return ParensResult.EXPLICIT_LAMBDA;
  1374                 case LBRACKET:
  1375                     if (peekToken(lookahead, RBRACKET, IDENTIFIER)) {
  1376                         // '[', ']', Identifier -> explicit lambda
  1377                         return ParensResult.EXPLICIT_LAMBDA;
  1378                     } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
  1379                             peekToken(lookahead, RBRACKET, AMP)) {
  1380                         // '[', ']', ')' -> cast
  1381                         // '[', ']', '&' -> cast (intersection type)
  1382                         return ParensResult.CAST;
  1383                     } else if (peekToken(lookahead, RBRACKET)) {
  1384                         //consume the ']' and skip
  1385                         type = true;
  1386                         lookahead++;
  1387                         break;
  1388                     } else {
  1389                         return ParensResult.PARENS;
  1391                 case LT:
  1392                     depth++; break;
  1393                 case GTGTGT:
  1394                     depth--;
  1395                 case GTGT:
  1396                     depth--;
  1397                 case GT:
  1398                     depth--;
  1399                     if (depth == 0) {
  1400                         if (peekToken(lookahead, RPAREN) ||
  1401                                 peekToken(lookahead, AMP)) {
  1402                             // '>', ')' -> cast
  1403                             // '>', '&' -> cast
  1404                             return ParensResult.CAST;
  1405                         } else if (peekToken(lookahead, IDENTIFIER, COMMA) ||
  1406                                 peekToken(lookahead, IDENTIFIER, RPAREN, ARROW) ||
  1407                                 peekToken(lookahead, ELLIPSIS)) {
  1408                             // '>', Identifier, ',' -> explicit lambda
  1409                             // '>', Identifier, ')', '->' -> explicit lambda
  1410                             // '>', '...' -> explicit lambda
  1411                             return ParensResult.EXPLICIT_LAMBDA;
  1413                         //it looks a type, but could still be (i) a cast to generic type,
  1414                         //(ii) an unbound method reference or (iii) an explicit lambda
  1415                         type = true;
  1416                         break;
  1417                     } else if (depth < 0) {
  1418                         //unbalanced '<', '>' - not a generic type
  1419                         return ParensResult.PARENS;
  1421                     break;
  1422                 default:
  1423                     //this includes EOF
  1424                     return ParensResult.PARENS;
  1429     enum ParensResult {
  1430         CAST,
  1431         EXPLICIT_LAMBDA,
  1432         IMPLICIT_LAMBDA,
  1433         PARENS;
  1436     JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
  1437         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  1438         params.append(firstParam);
  1439         JCVariableDecl lastParam = firstParam;
  1440         while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  1441             nextToken();
  1442             params.append(lastParam = formalParameter());
  1444         accept(RPAREN);
  1445         return lambdaExpressionOrStatementRest(params.toList(), pos);
  1448     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1449         List<JCVariableDecl> params = explicitParams ?
  1450                 formalParameters() :
  1451                 implicitParameters(hasParens);
  1453         return lambdaExpressionOrStatementRest(params, pos);
  1456     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1457         checkLambda();
  1458         accept(ARROW);
  1460         return token.kind == LBRACE ?
  1461             lambdaStatement(args, pos, pos) :
  1462             lambdaExpression(args, pos);
  1465     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1466         JCBlock block = block(pos2, 0);
  1467         return toP(F.at(pos).Lambda(args, block));
  1470     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1471         JCTree expr = parseExpression();
  1472         return toP(F.at(pos).Lambda(args, expr));
  1475     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1476      */
  1477     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1478         nextToken();
  1479         if (token.kind == LPAREN || typeArgs != null) {
  1480             t = arguments(typeArgs, t);
  1481         } else if (token.kind == COLCOL) {
  1482             if (typeArgs != null) return illegal();
  1483             t = memberReferenceSuffix(t);
  1484         } else {
  1485             int pos = token.pos;
  1486             accept(DOT);
  1487             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1488             t = toP(F.at(pos).Select(t, ident()));
  1489             t = argumentsOpt(typeArgs, t);
  1491         return t;
  1494     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1495      */
  1496     JCPrimitiveTypeTree basicType() {
  1497         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1498         nextToken();
  1499         return t;
  1502     /** ArgumentsOpt = [ Arguments ]
  1503      */
  1504     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1505         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1506             mode = EXPR;
  1507             return arguments(typeArgs, t);
  1508         } else {
  1509             return t;
  1513     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1514      */
  1515     List<JCExpression> arguments() {
  1516         ListBuffer<JCExpression> args = lb();
  1517         if (token.kind == LPAREN) {
  1518             nextToken();
  1519             if (token.kind != RPAREN) {
  1520                 args.append(parseExpression());
  1521                 while (token.kind == COMMA) {
  1522                     nextToken();
  1523                     args.append(parseExpression());
  1526             accept(RPAREN);
  1527         } else {
  1528             syntaxError(token.pos, "expected", LPAREN);
  1530         return args.toList();
  1533     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1534         int pos = token.pos;
  1535         List<JCExpression> args = arguments();
  1536         return toP(F.at(pos).Apply(typeArgs, t, args));
  1539     /**  TypeArgumentsOpt = [ TypeArguments ]
  1540      */
  1541     JCExpression typeArgumentsOpt(JCExpression t) {
  1542         if (token.kind == LT &&
  1543             (mode & TYPE) != 0 &&
  1544             (mode & NOPARAMS) == 0) {
  1545             mode = TYPE;
  1546             checkGenerics();
  1547             return typeArguments(t, false);
  1548         } else {
  1549             return t;
  1552     List<JCExpression> typeArgumentsOpt() {
  1553         return typeArgumentsOpt(TYPE);
  1556     List<JCExpression> typeArgumentsOpt(int useMode) {
  1557         if (token.kind == LT) {
  1558             checkGenerics();
  1559             if ((mode & useMode) == 0 ||
  1560                 (mode & NOPARAMS) != 0) {
  1561                 illegal();
  1563             mode = useMode;
  1564             return typeArguments(false);
  1566         return null;
  1569     /**
  1570      *  {@literal
  1571      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1572      *  }
  1573      */
  1574     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1575         if (token.kind == LT) {
  1576             nextToken();
  1577             if (token.kind == GT && diamondAllowed) {
  1578                 checkDiamond();
  1579                 mode |= DIAMOND;
  1580                 nextToken();
  1581                 return List.nil();
  1582             } else {
  1583                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1584                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1585                 while (token.kind == COMMA) {
  1586                     nextToken();
  1587                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1589                 switch (token.kind) {
  1591                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1592                 case GTGTGT: case GTGT:
  1593                     token = S.split();
  1594                     break;
  1595                 case GT:
  1596                     nextToken();
  1597                     break;
  1598                 default:
  1599                     args.append(syntaxError(token.pos, "expected", GT));
  1600                     break;
  1602                 return args.toList();
  1604         } else {
  1605             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1609     /**
  1610      *  {@literal
  1611      *  TypeArgument = Type
  1612      *               | "?"
  1613      *               | "?" EXTENDS Type {"&" Type}
  1614      *               | "?" SUPER Type
  1615      *  }
  1616      */
  1617     JCExpression typeArgument() {
  1618         if (token.kind != QUES) return parseType();
  1619         int pos = token.pos;
  1620         nextToken();
  1621         if (token.kind == EXTENDS) {
  1622             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1623             nextToken();
  1624             JCExpression bound = parseType();
  1625             return F.at(pos).Wildcard(t, bound);
  1626         } else if (token.kind == SUPER) {
  1627             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1628             nextToken();
  1629             JCExpression bound = parseType();
  1630             return F.at(pos).Wildcard(t, bound);
  1631         } else if (token.kind == IDENTIFIER) {
  1632             //error recovery
  1633             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1634             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1635             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1636             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1637             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1638             return err;
  1639         } else {
  1640             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1641             return toP(F.at(pos).Wildcard(t, null));
  1645     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1646         int pos = token.pos;
  1647         List<JCExpression> args = typeArguments(diamondAllowed);
  1648         return toP(F.at(pos).TypeApply(t, args));
  1651     /** BracketsOpt = {"[" "]"}
  1652      */
  1653     private JCExpression bracketsOpt(JCExpression t) {
  1654         if (token.kind == LBRACKET) {
  1655             int pos = token.pos;
  1656             nextToken();
  1657             t = bracketsOptCont(t, pos);
  1658             F.at(pos);
  1660         return t;
  1663     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1664         accept(RBRACKET);
  1665         t = bracketsOpt(t);
  1666         return toP(F.at(pos).TypeArray(t));
  1669     /** BracketsSuffixExpr = "." CLASS
  1670      *  BracketsSuffixType =
  1671      */
  1672     JCExpression bracketsSuffix(JCExpression t) {
  1673         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1674             mode = EXPR;
  1675             int pos = token.pos;
  1676             nextToken();
  1677             accept(CLASS);
  1678             if (token.pos == endPosTable.errorEndPos) {
  1679                 // error recovery
  1680                 Name name = null;
  1681                 if (token.kind == IDENTIFIER) {
  1682                     name = token.name();
  1683                     nextToken();
  1684                 } else {
  1685                     name = names.error;
  1687                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1688             } else {
  1689                 t = toP(F.at(pos).Select(t, names._class));
  1691         } else if ((mode & TYPE) != 0) {
  1692             if (token.kind != COLCOL) {
  1693                 mode = TYPE;
  1695         } else if (token.kind != COLCOL) {
  1696             syntaxError(token.pos, "dot.class.expected");
  1698         return t;
  1701     /**
  1702      * MemberReferenceSuffix = "::" [TypeArguments] Ident
  1703      *                       | "::" [TypeArguments] "new"
  1704      */
  1705     JCExpression memberReferenceSuffix(JCExpression t) {
  1706         int pos1 = token.pos;
  1707         accept(COLCOL);
  1708         return memberReferenceSuffix(pos1, t);
  1711     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1712         checkMethodReferences();
  1713         mode = EXPR;
  1714         List<JCExpression> typeArgs = null;
  1715         if (token.kind == LT) {
  1716             typeArgs = typeArguments(false);
  1718         Name refName = null;
  1719         ReferenceMode refMode = null;
  1720         if (token.kind == NEW) {
  1721             refMode = ReferenceMode.NEW;
  1722             refName = names.init;
  1723             nextToken();
  1724         } else {
  1725             refMode = ReferenceMode.INVOKE;
  1726             refName = ident();
  1728         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  1731     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1732      */
  1733     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1734         switch (token.kind) {
  1735         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1736         case DOUBLE: case BOOLEAN:
  1737             if (typeArgs == null)
  1738                 return arrayCreatorRest(newpos, basicType());
  1739             break;
  1740         default:
  1742         JCExpression t = qualident();
  1743         int oldmode = mode;
  1744         mode = TYPE;
  1745         boolean diamondFound = false;
  1746         int lastTypeargsPos = -1;
  1747         if (token.kind == LT) {
  1748             checkGenerics();
  1749             lastTypeargsPos = token.pos;
  1750             t = typeArguments(t, true);
  1751             diamondFound = (mode & DIAMOND) != 0;
  1753         while (token.kind == DOT) {
  1754             if (diamondFound) {
  1755                 //cannot select after a diamond
  1756                 illegal();
  1758             int pos = token.pos;
  1759             nextToken();
  1760             t = toP(F.at(pos).Select(t, ident()));
  1761             if (token.kind == LT) {
  1762                 lastTypeargsPos = token.pos;
  1763                 checkGenerics();
  1764                 t = typeArguments(t, true);
  1765                 diamondFound = (mode & DIAMOND) != 0;
  1768         mode = oldmode;
  1769         if (token.kind == LBRACKET) {
  1770             JCExpression e = arrayCreatorRest(newpos, t);
  1771             if (diamondFound) {
  1772                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1773                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1775             else if (typeArgs != null) {
  1776                 int pos = newpos;
  1777                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1778                     // note: this should always happen but we should
  1779                     // not rely on this as the parser is continuously
  1780                     // modified to improve error recovery.
  1781                     pos = typeArgs.head.pos;
  1783                 setErrorEndPos(S.prevToken().endPos);
  1784                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1785                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1786                 return toP(err);
  1788             return e;
  1789         } else if (token.kind == LPAREN) {
  1790             return classCreatorRest(newpos, null, typeArgs, t);
  1791         } else {
  1792             setErrorEndPos(token.pos);
  1793             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1794             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1795             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1799     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1800      */
  1801     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1802         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1803         if (token.kind == LT) {
  1804             int oldmode = mode;
  1805             checkGenerics();
  1806             t = typeArguments(t, true);
  1807             mode = oldmode;
  1809         return classCreatorRest(newpos, encl, typeArgs, t);
  1812     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1813      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1814      */
  1815     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1816         accept(LBRACKET);
  1817         if (token.kind == RBRACKET) {
  1818             accept(RBRACKET);
  1819             elemtype = bracketsOpt(elemtype);
  1820             if (token.kind == LBRACE) {
  1821                 return arrayInitializer(newpos, elemtype);
  1822             } else {
  1823                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1824                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1826         } else {
  1827             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1828             dims.append(parseExpression());
  1829             accept(RBRACKET);
  1830             while (token.kind == LBRACKET) {
  1831                 int pos = token.pos;
  1832                 nextToken();
  1833                 if (token.kind == RBRACKET) {
  1834                     elemtype = bracketsOptCont(elemtype, pos);
  1835                 } else {
  1836                     dims.append(parseExpression());
  1837                     accept(RBRACKET);
  1840             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1844     /** ClassCreatorRest = Arguments [ClassBody]
  1845      */
  1846     JCNewClass classCreatorRest(int newpos,
  1847                                   JCExpression encl,
  1848                                   List<JCExpression> typeArgs,
  1849                                   JCExpression t)
  1851         List<JCExpression> args = arguments();
  1852         JCClassDecl body = null;
  1853         if (token.kind == LBRACE) {
  1854             int pos = token.pos;
  1855             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1856             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1857             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1859         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1862     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1863      */
  1864     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1865         accept(LBRACE);
  1866         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1867         if (token.kind == COMMA) {
  1868             nextToken();
  1869         } else if (token.kind != RBRACE) {
  1870             elems.append(variableInitializer());
  1871             while (token.kind == COMMA) {
  1872                 nextToken();
  1873                 if (token.kind == RBRACE) break;
  1874                 elems.append(variableInitializer());
  1877         accept(RBRACE);
  1878         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1881     /** VariableInitializer = ArrayInitializer | Expression
  1882      */
  1883     public JCExpression variableInitializer() {
  1884         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1887     /** ParExpression = "(" Expression ")"
  1888      */
  1889     JCExpression parExpression() {
  1890         int pos = token.pos;
  1891         accept(LPAREN);
  1892         JCExpression t = parseExpression();
  1893         accept(RPAREN);
  1894         return toP(F.at(pos).Parens(t));
  1897     /** Block = "{" BlockStatements "}"
  1898      */
  1899     JCBlock block(int pos, long flags) {
  1900         accept(LBRACE);
  1901         List<JCStatement> stats = blockStatements();
  1902         JCBlock t = F.at(pos).Block(flags, stats);
  1903         while (token.kind == CASE || token.kind == DEFAULT) {
  1904             syntaxError("orphaned", token.kind);
  1905             switchBlockStatementGroups();
  1907         // the Block node has a field "endpos" for first char of last token, which is
  1908         // usually but not necessarily the last char of the last token.
  1909         t.endpos = token.pos;
  1910         accept(RBRACE);
  1911         return toP(t);
  1914     public JCBlock block() {
  1915         return block(token.pos, 0);
  1918     /** BlockStatements = { BlockStatement }
  1919      *  BlockStatement  = LocalVariableDeclarationStatement
  1920      *                  | ClassOrInterfaceOrEnumDeclaration
  1921      *                  | [Ident ":"] Statement
  1922      *  LocalVariableDeclarationStatement
  1923      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1924      */
  1925     @SuppressWarnings("fallthrough")
  1926     List<JCStatement> blockStatements() {
  1927         //todo: skip to anchor on error(?)
  1928         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1929         while (true) {
  1930             List<JCStatement> stat = blockStatement();
  1931             if (stat.isEmpty()) {
  1932                 return stats.toList();
  1933             } else {
  1934                 if (token.pos <= endPosTable.errorEndPos) {
  1935                     skip(false, true, true, true);
  1937                 stats.addAll(stat);
  1942     /*
  1943      * This method parses a statement treating it as a block, relaxing the
  1944      * JLS restrictions, allows us to parse more faulty code, doing so
  1945      * enables us to provide better and accurate diagnostics to the user.
  1946      */
  1947     JCStatement parseStatementAsBlock() {
  1948         int pos = token.pos;
  1949         List<JCStatement> stats = blockStatement();
  1950         if (stats.isEmpty()) {
  1951             JCErroneous e = F.at(pos).Erroneous();
  1952             error(e, "illegal.start.of.stmt");
  1953             return F.at(pos).Exec(e);
  1954         } else {
  1955             JCStatement first = stats.head;
  1956             String error = null;
  1957             switch (first.getTag()) {
  1958             case CLASSDEF:
  1959                 error = "class.not.allowed";
  1960                 break;
  1961             case VARDEF:
  1962                 error = "variable.not.allowed";
  1963                 break;
  1965             if (error != null) {
  1966                 error(first, error);
  1967                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  1968                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  1970             return first;
  1974     @SuppressWarnings("fallthrough")
  1975     List<JCStatement> blockStatement() {
  1976         //todo: skip to anchor on error(?)
  1977         int pos = token.pos;
  1978         switch (token.kind) {
  1979         case RBRACE: case CASE: case DEFAULT: case EOF:
  1980             return List.nil();
  1981         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1982         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1983         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1984             return List.of(parseStatement());
  1985         case MONKEYS_AT:
  1986         case FINAL: {
  1987             Comment dc = token.comment(CommentStyle.JAVADOC);
  1988             JCModifiers mods = modifiersOpt();
  1989             if (token.kind == INTERFACE ||
  1990                 token.kind == CLASS ||
  1991                 allowEnums && token.kind == ENUM) {
  1992                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1993             } else {
  1994                 JCExpression t = parseType();
  1995                 ListBuffer<JCStatement> stats =
  1996                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1997                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1998                 storeEnd(stats.last(), token.endPos);
  1999                 accept(SEMI);
  2000                 return stats.toList();
  2003         case ABSTRACT: case STRICTFP: {
  2004             Comment dc = token.comment(CommentStyle.JAVADOC);
  2005             JCModifiers mods = modifiersOpt();
  2006             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2008         case INTERFACE:
  2009         case CLASS:
  2010             Comment dc = token.comment(CommentStyle.JAVADOC);
  2011             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2012         case ENUM:
  2013         case ASSERT:
  2014             if (allowEnums && token.kind == ENUM) {
  2015                 error(token.pos, "local.enum");
  2016                 dc = token.comment(CommentStyle.JAVADOC);
  2017                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  2018             } else if (allowAsserts && token.kind == ASSERT) {
  2019                 return List.of(parseStatement());
  2021             /* fall through to default */
  2022         default:
  2023             Token prevToken = token;
  2024             JCExpression t = term(EXPR | TYPE);
  2025             if (token.kind == COLON && t.hasTag(IDENT)) {
  2026                 nextToken();
  2027                 JCStatement stat = parseStatement();
  2028                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  2029             } else if ((lastmode & TYPE) != 0 &&
  2030                        (token.kind == IDENTIFIER ||
  2031                         token.kind == ASSERT ||
  2032                         token.kind == ENUM)) {
  2033                 pos = token.pos;
  2034                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  2035                 F.at(pos);
  2036                 ListBuffer<JCStatement> stats =
  2037                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  2038                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  2039                 storeEnd(stats.last(), token.endPos);
  2040                 accept(SEMI);
  2041                 return stats.toList();
  2042             } else {
  2043                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2044                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  2045                 accept(SEMI);
  2046                 return List.<JCStatement>of(expr);
  2051     /** Statement =
  2052      *       Block
  2053      *     | IF ParExpression Statement [ELSE Statement]
  2054      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  2055      *     | FOR "(" FormalParameter : Expression ")" Statement
  2056      *     | WHILE ParExpression Statement
  2057      *     | DO Statement WHILE ParExpression ";"
  2058      *     | TRY Block ( Catches | [Catches] FinallyPart )
  2059      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  2060      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  2061      *     | SYNCHRONIZED ParExpression Block
  2062      *     | RETURN [Expression] ";"
  2063      *     | THROW Expression ";"
  2064      *     | BREAK [Ident] ";"
  2065      *     | CONTINUE [Ident] ";"
  2066      *     | ASSERT Expression [ ":" Expression ] ";"
  2067      *     | ";"
  2068      *     | ExpressionStatement
  2069      *     | Ident ":" Statement
  2070      */
  2071     @SuppressWarnings("fallthrough")
  2072     public JCStatement parseStatement() {
  2073         int pos = token.pos;
  2074         switch (token.kind) {
  2075         case LBRACE:
  2076             return block();
  2077         case IF: {
  2078             nextToken();
  2079             JCExpression cond = parExpression();
  2080             JCStatement thenpart = parseStatementAsBlock();
  2081             JCStatement elsepart = null;
  2082             if (token.kind == ELSE) {
  2083                 nextToken();
  2084                 elsepart = parseStatementAsBlock();
  2086             return F.at(pos).If(cond, thenpart, elsepart);
  2088         case FOR: {
  2089             nextToken();
  2090             accept(LPAREN);
  2091             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  2092             if (inits.length() == 1 &&
  2093                 inits.head.hasTag(VARDEF) &&
  2094                 ((JCVariableDecl) inits.head).init == null &&
  2095                 token.kind == COLON) {
  2096                 checkForeach();
  2097                 JCVariableDecl var = (JCVariableDecl)inits.head;
  2098                 accept(COLON);
  2099                 JCExpression expr = parseExpression();
  2100                 accept(RPAREN);
  2101                 JCStatement body = parseStatementAsBlock();
  2102                 return F.at(pos).ForeachLoop(var, expr, body);
  2103             } else {
  2104                 accept(SEMI);
  2105                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  2106                 accept(SEMI);
  2107                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2108                 accept(RPAREN);
  2109                 JCStatement body = parseStatementAsBlock();
  2110                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2113         case WHILE: {
  2114             nextToken();
  2115             JCExpression cond = parExpression();
  2116             JCStatement body = parseStatementAsBlock();
  2117             return F.at(pos).WhileLoop(cond, body);
  2119         case DO: {
  2120             nextToken();
  2121             JCStatement body = parseStatementAsBlock();
  2122             accept(WHILE);
  2123             JCExpression cond = parExpression();
  2124             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2125             accept(SEMI);
  2126             return t;
  2128         case TRY: {
  2129             nextToken();
  2130             List<JCTree> resources = List.<JCTree>nil();
  2131             if (token.kind == LPAREN) {
  2132                 checkTryWithResources();
  2133                 nextToken();
  2134                 resources = resources();
  2135                 accept(RPAREN);
  2137             JCBlock body = block();
  2138             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2139             JCBlock finalizer = null;
  2140             if (token.kind == CATCH || token.kind == FINALLY) {
  2141                 while (token.kind == CATCH) catchers.append(catchClause());
  2142                 if (token.kind == FINALLY) {
  2143                     nextToken();
  2144                     finalizer = block();
  2146             } else {
  2147                 if (allowTWR) {
  2148                     if (resources.isEmpty())
  2149                         error(pos, "try.without.catch.finally.or.resource.decls");
  2150                 } else
  2151                     error(pos, "try.without.catch.or.finally");
  2153             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2155         case SWITCH: {
  2156             nextToken();
  2157             JCExpression selector = parExpression();
  2158             accept(LBRACE);
  2159             List<JCCase> cases = switchBlockStatementGroups();
  2160             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2161             accept(RBRACE);
  2162             return t;
  2164         case SYNCHRONIZED: {
  2165             nextToken();
  2166             JCExpression lock = parExpression();
  2167             JCBlock body = block();
  2168             return F.at(pos).Synchronized(lock, body);
  2170         case RETURN: {
  2171             nextToken();
  2172             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2173             JCReturn t = to(F.at(pos).Return(result));
  2174             accept(SEMI);
  2175             return t;
  2177         case THROW: {
  2178             nextToken();
  2179             JCExpression exc = parseExpression();
  2180             JCThrow t = to(F.at(pos).Throw(exc));
  2181             accept(SEMI);
  2182             return t;
  2184         case BREAK: {
  2185             nextToken();
  2186             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2187             JCBreak t = to(F.at(pos).Break(label));
  2188             accept(SEMI);
  2189             return t;
  2191         case CONTINUE: {
  2192             nextToken();
  2193             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2194             JCContinue t =  to(F.at(pos).Continue(label));
  2195             accept(SEMI);
  2196             return t;
  2198         case SEMI:
  2199             nextToken();
  2200             return toP(F.at(pos).Skip());
  2201         case ELSE:
  2202             int elsePos = token.pos;
  2203             nextToken();
  2204             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
  2205         case FINALLY:
  2206             int finallyPos = token.pos;
  2207             nextToken();
  2208             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
  2209         case CATCH:
  2210             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
  2211         case ASSERT: {
  2212             if (allowAsserts && token.kind == ASSERT) {
  2213                 nextToken();
  2214                 JCExpression assertion = parseExpression();
  2215                 JCExpression message = null;
  2216                 if (token.kind == COLON) {
  2217                     nextToken();
  2218                     message = parseExpression();
  2220                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2221                 accept(SEMI);
  2222                 return t;
  2224             /* else fall through to default case */
  2226         case ENUM:
  2227         default:
  2228             Token prevToken = token;
  2229             JCExpression expr = parseExpression();
  2230             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2231                 nextToken();
  2232                 JCStatement stat = parseStatement();
  2233                 return F.at(pos).Labelled(prevToken.name(), stat);
  2234             } else {
  2235                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2236                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2237                 accept(SEMI);
  2238                 return stat;
  2243     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
  2244         int errPos = S.errPos();
  2245         JCTree stm = action.doRecover(this);
  2246         S.errPos(errPos);
  2247         return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
  2250     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2251      */
  2252     protected JCCatch catchClause() {
  2253         int pos = token.pos;
  2254         accept(CATCH);
  2255         accept(LPAREN);
  2256         JCModifiers mods = optFinal(Flags.PARAMETER);
  2257         List<JCExpression> catchTypes = catchTypes();
  2258         JCExpression paramType = catchTypes.size() > 1 ?
  2259                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2260                 catchTypes.head;
  2261         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2262         accept(RPAREN);
  2263         JCBlock body = block();
  2264         return F.at(pos).Catch(formal, body);
  2267     List<JCExpression> catchTypes() {
  2268         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2269         catchTypes.add(parseType());
  2270         while (token.kind == BAR) {
  2271             checkMulticatch();
  2272             nextToken();
  2273             catchTypes.add(qualident());
  2275         return catchTypes.toList();
  2278     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2279      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2280      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2281      */
  2282     List<JCCase> switchBlockStatementGroups() {
  2283         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2284         while (true) {
  2285             int pos = token.pos;
  2286             switch (token.kind) {
  2287             case CASE:
  2288             case DEFAULT:
  2289                 cases.append(switchBlockStatementGroup());
  2290                 break;
  2291             case RBRACE: case EOF:
  2292                 return cases.toList();
  2293             default:
  2294                 nextToken(); // to ensure progress
  2295                 syntaxError(pos, "expected3",
  2296                     CASE, DEFAULT, RBRACE);
  2301     protected JCCase switchBlockStatementGroup() {
  2302         int pos = token.pos;
  2303         List<JCStatement> stats;
  2304         JCCase c;
  2305         switch (token.kind) {
  2306         case CASE:
  2307             nextToken();
  2308             JCExpression pat = parseExpression();
  2309             accept(COLON);
  2310             stats = blockStatements();
  2311             c = F.at(pos).Case(pat, stats);
  2312             if (stats.isEmpty())
  2313                 storeEnd(c, S.prevToken().endPos);
  2314             return c;
  2315         case DEFAULT:
  2316             nextToken();
  2317             accept(COLON);
  2318             stats = blockStatements();
  2319             c = F.at(pos).Case(null, stats);
  2320             if (stats.isEmpty())
  2321                 storeEnd(c, S.prevToken().endPos);
  2322             return c;
  2324         throw new AssertionError("should not reach here");
  2327     /** MoreStatementExpressions = { COMMA StatementExpression }
  2328      */
  2329     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2330                                                                     JCExpression first,
  2331                                                                     T stats) {
  2332         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2333         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2334         while (token.kind == COMMA) {
  2335             nextToken();
  2336             pos = token.pos;
  2337             JCExpression t = parseExpression();
  2338             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2339             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2341         return stats;
  2344     /** ForInit = StatementExpression MoreStatementExpressions
  2345      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2346      */
  2347     List<JCStatement> forInit() {
  2348         ListBuffer<JCStatement> stats = lb();
  2349         int pos = token.pos;
  2350         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2351             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2352         } else {
  2353             JCExpression t = term(EXPR | TYPE);
  2354             if ((lastmode & TYPE) != 0 &&
  2355                 (token.kind == IDENTIFIER || token.kind == ASSERT ||
  2356                  token.kind == ENUM)) {
  2357                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2358             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2359                 error(pos, "bad.initializer", "for-loop");
  2360                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2361             } else {
  2362                 return moreStatementExpressions(pos, t, stats).toList();
  2367     /** ForUpdate = StatementExpression MoreStatementExpressions
  2368      */
  2369     List<JCExpressionStatement> forUpdate() {
  2370         return moreStatementExpressions(token.pos,
  2371                                         parseExpression(),
  2372                                         new ListBuffer<JCExpressionStatement>()).toList();
  2375     /** AnnotationsOpt = { '@' Annotation }
  2376      */
  2377     List<JCAnnotation> annotationsOpt() {
  2378         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2379         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2380         while (token.kind == MONKEYS_AT) {
  2381             int pos = token.pos;
  2382             nextToken();
  2383             buf.append(annotation(pos));
  2385         return buf.toList();
  2388     /** ModifiersOpt = { Modifier }
  2389      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2390      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2391      *           | "@" Annotation
  2392      */
  2393     JCModifiers modifiersOpt() {
  2394         return modifiersOpt(null);
  2396     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2397         long flags;
  2398         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2399         int pos;
  2400         if (partial == null) {
  2401             flags = 0;
  2402             pos = token.pos;
  2403         } else {
  2404             flags = partial.flags;
  2405             annotations.appendList(partial.annotations);
  2406             pos = partial.pos;
  2408         if (token.deprecatedFlag()) {
  2409             flags |= Flags.DEPRECATED;
  2411         int lastPos = Position.NOPOS;
  2412     loop:
  2413         while (true) {
  2414             long flag;
  2415             switch (token.kind) {
  2416             case PRIVATE     : flag = Flags.PRIVATE; break;
  2417             case PROTECTED   : flag = Flags.PROTECTED; break;
  2418             case PUBLIC      : flag = Flags.PUBLIC; break;
  2419             case STATIC      : flag = Flags.STATIC; break;
  2420             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2421             case FINAL       : flag = Flags.FINAL; break;
  2422             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2423             case NATIVE      : flag = Flags.NATIVE; break;
  2424             case VOLATILE    : flag = Flags.VOLATILE; break;
  2425             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2426             case STRICTFP    : flag = Flags.STRICTFP; break;
  2427             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2428             case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
  2429             case ERROR       : flag = 0; nextToken(); break;
  2430             default: break loop;
  2432             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2433             lastPos = token.pos;
  2434             nextToken();
  2435             if (flag == Flags.ANNOTATION) {
  2436                 checkAnnotations();
  2437                 if (token.kind != INTERFACE) {
  2438                     JCAnnotation ann = annotation(lastPos);
  2439                     // if first modifier is an annotation, set pos to annotation's.
  2440                     if (flags == 0 && annotations.isEmpty())
  2441                         pos = ann.pos;
  2442                     annotations.append(ann);
  2443                     lastPos = ann.pos;
  2444                     flag = 0;
  2447             flags |= flag;
  2449         switch (token.kind) {
  2450         case ENUM: flags |= Flags.ENUM; break;
  2451         case INTERFACE: flags |= Flags.INTERFACE; break;
  2452         default: break;
  2455         /* A modifiers tree with no modifier tokens or annotations
  2456          * has no text position. */
  2457         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2458             pos = Position.NOPOS;
  2460         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2461         if (pos != Position.NOPOS)
  2462             storeEnd(mods, S.prevToken().endPos);
  2463         return mods;
  2466     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2467      * @param pos position of "@" token
  2468      */
  2469     JCAnnotation annotation(int pos) {
  2470         // accept(AT); // AT consumed by caller
  2471         checkAnnotations();
  2472         JCTree ident = qualident();
  2473         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2474         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2475         storeEnd(ann, S.prevToken().endPos);
  2476         return ann;
  2479     List<JCExpression> annotationFieldValuesOpt() {
  2480         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2483     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2484     List<JCExpression> annotationFieldValues() {
  2485         accept(LPAREN);
  2486         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2487         if (token.kind != RPAREN) {
  2488             buf.append(annotationFieldValue());
  2489             while (token.kind == COMMA) {
  2490                 nextToken();
  2491                 buf.append(annotationFieldValue());
  2494         accept(RPAREN);
  2495         return buf.toList();
  2498     /** AnnotationFieldValue    = AnnotationValue
  2499      *                          | Identifier "=" AnnotationValue
  2500      */
  2501     JCExpression annotationFieldValue() {
  2502         if (token.kind == IDENTIFIER) {
  2503             mode = EXPR;
  2504             JCExpression t1 = term1();
  2505             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2506                 int pos = token.pos;
  2507                 accept(EQ);
  2508                 JCExpression v = annotationValue();
  2509                 return toP(F.at(pos).Assign(t1, v));
  2510             } else {
  2511                 return t1;
  2514         return annotationValue();
  2517     /* AnnotationValue          = ConditionalExpression
  2518      *                          | Annotation
  2519      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2520      */
  2521     JCExpression annotationValue() {
  2522         int pos;
  2523         switch (token.kind) {
  2524         case MONKEYS_AT:
  2525             pos = token.pos;
  2526             nextToken();
  2527             return annotation(pos);
  2528         case LBRACE:
  2529             pos = token.pos;
  2530             accept(LBRACE);
  2531             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2532             if (token.kind != RBRACE) {
  2533                 buf.append(annotationValue());
  2534                 while (token.kind == COMMA) {
  2535                     nextToken();
  2536                     if (token.kind == RBRACE) break;
  2537                     buf.append(annotationValue());
  2540             accept(RBRACE);
  2541             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2542         default:
  2543             mode = EXPR;
  2544             return term1();
  2548     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2549      */
  2550     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2551                                                                          JCExpression type,
  2552                                                                          T vdefs)
  2554         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2557     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2558      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2560      *  @param reqInit  Is an initializer always required?
  2561      *  @param dc       The documentation comment for the variable declarations, or null.
  2562      */
  2563     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2564                                                                      JCModifiers mods,
  2565                                                                      JCExpression type,
  2566                                                                      Name name,
  2567                                                                      boolean reqInit,
  2568                                                                      Comment dc,
  2569                                                                      T vdefs)
  2571         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2572         while (token.kind == COMMA) {
  2573             // All but last of multiple declarators subsume a comma
  2574             storeEnd((JCTree)vdefs.last(), token.endPos);
  2575             nextToken();
  2576             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2578         return vdefs;
  2581     /** VariableDeclarator = Ident VariableDeclaratorRest
  2582      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2583      */
  2584     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2585         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2588     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2589      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2591      *  @param reqInit  Is an initializer always required?
  2592      *  @param dc       The documentation comment for the variable declarations, or null.
  2593      */
  2594     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2595                                   boolean reqInit, Comment dc) {
  2596         type = bracketsOpt(type);
  2597         JCExpression init = null;
  2598         if (token.kind == EQ) {
  2599             nextToken();
  2600             init = variableInitializer();
  2602         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2603         JCVariableDecl result =
  2604             toP(F.at(pos).VarDef(mods, name, type, init));
  2605         attach(result, dc);
  2606         return result;
  2609     /** VariableDeclaratorId = Ident BracketsOpt
  2610      */
  2611     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2612         int pos = token.pos;
  2613         Name name = ident();
  2614         if ((mods.flags & Flags.VARARGS) != 0 &&
  2615                 token.kind == LBRACKET) {
  2616             log.error(token.pos, "varargs.and.old.array.syntax");
  2618         type = bracketsOpt(type);
  2619         return toP(F.at(pos).VarDef(mods, name, type, null));
  2622     /** Resources = Resource { ";" Resources }
  2623      */
  2624     List<JCTree> resources() {
  2625         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2626         defs.append(resource());
  2627         while (token.kind == SEMI) {
  2628             // All but last of multiple declarators must subsume a semicolon
  2629             storeEnd(defs.last(), token.endPos);
  2630             int semiColonPos = token.pos;
  2631             nextToken();
  2632             if (token.kind == RPAREN) { // Optional trailing semicolon
  2633                                        // after last resource
  2634                 break;
  2636             defs.append(resource());
  2638         return defs.toList();
  2641     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2642      */
  2643     protected JCTree resource() {
  2644         JCModifiers optFinal = optFinal(Flags.FINAL);
  2645         JCExpression type = parseType();
  2646         int pos = token.pos;
  2647         Name ident = ident();
  2648         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2651     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2652      */
  2653     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2654         Token firstToken = token;
  2655         JCExpression pid = null;
  2656         JCModifiers mods = null;
  2657         boolean consumedToplevelDoc = false;
  2658         boolean seenImport = false;
  2659         boolean seenPackage = false;
  2660         List<JCAnnotation> packageAnnotations = List.nil();
  2661         if (token.kind == MONKEYS_AT)
  2662             mods = modifiersOpt();
  2664         if (token.kind == PACKAGE) {
  2665             seenPackage = true;
  2666             if (mods != null) {
  2667                 checkNoMods(mods.flags);
  2668                 packageAnnotations = mods.annotations;
  2669                 mods = null;
  2671             nextToken();
  2672             pid = qualident();
  2673             accept(SEMI);
  2675         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2676         boolean checkForImports = true;
  2677         boolean firstTypeDecl = true;
  2678         while (token.kind != EOF) {
  2679             if (token.pos <= endPosTable.errorEndPos) {
  2680                 // error recovery
  2681                 skip(checkForImports, false, false, false);
  2682                 if (token.kind == EOF)
  2683                     break;
  2685             if (checkForImports && mods == null && token.kind == IMPORT) {
  2686                 seenImport = true;
  2687                 defs.append(importDeclaration());
  2688             } else {
  2689                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  2690                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2691                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2692                     consumedToplevelDoc = true;
  2694                 JCTree def = typeDeclaration(mods, docComment);
  2695                 if (def instanceof JCExpressionStatement)
  2696                     def = ((JCExpressionStatement)def).expr;
  2697                 defs.append(def);
  2698                 if (def instanceof JCClassDecl)
  2699                     checkForImports = false;
  2700                 mods = null;
  2701                 firstTypeDecl = false;
  2704         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2705         if (!consumedToplevelDoc)
  2706             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2707         if (defs.isEmpty())
  2708             storeEnd(toplevel, S.prevToken().endPos);
  2709         if (keepDocComments)
  2710             toplevel.docComments = docComments;
  2711         if (keepLineMap)
  2712             toplevel.lineMap = S.getLineMap();
  2713         toplevel.endPositions = this.endPosTable;
  2714         return toplevel;
  2717     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2718      */
  2719     JCTree importDeclaration() {
  2720         int pos = token.pos;
  2721         nextToken();
  2722         boolean importStatic = false;
  2723         if (token.kind == STATIC) {
  2724             checkStaticImports();
  2725             importStatic = true;
  2726             nextToken();
  2728         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2729         do {
  2730             int pos1 = token.pos;
  2731             accept(DOT);
  2732             if (token.kind == STAR) {
  2733                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2734                 nextToken();
  2735                 break;
  2736             } else {
  2737                 pid = toP(F.at(pos1).Select(pid, ident()));
  2739         } while (token.kind == DOT);
  2740         accept(SEMI);
  2741         return toP(F.at(pos).Import(pid, importStatic));
  2744     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2745      *                  | ";"
  2746      */
  2747     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  2748         int pos = token.pos;
  2749         if (mods == null && token.kind == SEMI) {
  2750             nextToken();
  2751             return toP(F.at(pos).Skip());
  2752         } else {
  2753             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2757     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2758      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2759      *  @param mods     Any modifiers starting the class or interface declaration
  2760      *  @param dc       The documentation comment for the class, or null.
  2761      */
  2762     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  2763         if (token.kind == CLASS) {
  2764             return classDeclaration(mods, dc);
  2765         } else if (token.kind == INTERFACE) {
  2766             return interfaceDeclaration(mods, dc);
  2767         } else if (allowEnums) {
  2768             if (token.kind == ENUM) {
  2769                 return enumDeclaration(mods, dc);
  2770             } else {
  2771                 int pos = token.pos;
  2772                 List<JCTree> errs;
  2773                 if (token.kind == IDENTIFIER) {
  2774                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2775                     setErrorEndPos(token.pos);
  2776                 } else {
  2777                     errs = List.<JCTree>of(mods);
  2779                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2780                                               CLASS, INTERFACE, ENUM)));
  2782         } else {
  2783             if (token.kind == ENUM) {
  2784                 error(token.pos, "enums.not.supported.in.source", source.name);
  2785                 allowEnums = true;
  2786                 return enumDeclaration(mods, dc);
  2788             int pos = token.pos;
  2789             List<JCTree> errs;
  2790             if (token.kind == IDENTIFIER) {
  2791                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2792                 setErrorEndPos(token.pos);
  2793             } else {
  2794                 errs = List.<JCTree>of(mods);
  2796             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2797                                           CLASS, INTERFACE)));
  2801     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2802      *                     [IMPLEMENTS TypeList] ClassBody
  2803      *  @param mods    The modifiers starting the class declaration
  2804      *  @param dc       The documentation comment for the class, or null.
  2805      */
  2806     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  2807         int pos = token.pos;
  2808         accept(CLASS);
  2809         Name name = ident();
  2811         List<JCTypeParameter> typarams = typeParametersOpt();
  2813         JCExpression extending = null;
  2814         if (token.kind == EXTENDS) {
  2815             nextToken();
  2816             extending = parseType();
  2818         List<JCExpression> implementing = List.nil();
  2819         if (token.kind == IMPLEMENTS) {
  2820             nextToken();
  2821             implementing = typeList();
  2823         List<JCTree> defs = classOrInterfaceBody(name, false);
  2824         JCClassDecl result = toP(F.at(pos).ClassDef(
  2825             mods, name, typarams, extending, implementing, defs));
  2826         attach(result, dc);
  2827         return result;
  2830     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2831      *                         [EXTENDS TypeList] InterfaceBody
  2832      *  @param mods    The modifiers starting the interface declaration
  2833      *  @param dc       The documentation comment for the interface, or null.
  2834      */
  2835     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  2836         int pos = token.pos;
  2837         accept(INTERFACE);
  2838         Name name = ident();
  2840         List<JCTypeParameter> typarams = typeParametersOpt();
  2842         List<JCExpression> extending = List.nil();
  2843         if (token.kind == EXTENDS) {
  2844             nextToken();
  2845             extending = typeList();
  2847         List<JCTree> defs = classOrInterfaceBody(name, true);
  2848         JCClassDecl result = toP(F.at(pos).ClassDef(
  2849             mods, name, typarams, null, extending, defs));
  2850         attach(result, dc);
  2851         return result;
  2854     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2855      *  @param mods    The modifiers starting the enum declaration
  2856      *  @param dc       The documentation comment for the enum, or null.
  2857      */
  2858     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  2859         int pos = token.pos;
  2860         accept(ENUM);
  2861         Name name = ident();
  2863         List<JCExpression> implementing = List.nil();
  2864         if (token.kind == IMPLEMENTS) {
  2865             nextToken();
  2866             implementing = typeList();
  2869         List<JCTree> defs = enumBody(name);
  2870         mods.flags |= Flags.ENUM;
  2871         JCClassDecl result = toP(F.at(pos).
  2872             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2873                 null, implementing, defs));
  2874         attach(result, dc);
  2875         return result;
  2878     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2879      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2880      */
  2881     List<JCTree> enumBody(Name enumName) {
  2882         accept(LBRACE);
  2883         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2884         if (token.kind == COMMA) {
  2885             nextToken();
  2886         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2887             defs.append(enumeratorDeclaration(enumName));
  2888             while (token.kind == COMMA) {
  2889                 nextToken();
  2890                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2891                 defs.append(enumeratorDeclaration(enumName));
  2893             if (token.kind != SEMI && token.kind != RBRACE) {
  2894                 defs.append(syntaxError(token.pos, "expected3",
  2895                                 COMMA, RBRACE, SEMI));
  2896                 nextToken();
  2899         if (token.kind == SEMI) {
  2900             nextToken();
  2901             while (token.kind != RBRACE && token.kind != EOF) {
  2902                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2903                                                                 false));
  2904                 if (token.pos <= endPosTable.errorEndPos) {
  2905                     // error recovery
  2906                    skip(false, true, true, false);
  2910         accept(RBRACE);
  2911         return defs.toList();
  2914     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2915      */
  2916     JCTree enumeratorDeclaration(Name enumName) {
  2917         Comment dc = token.comment(CommentStyle.JAVADOC);
  2918         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2919         if (token.deprecatedFlag()) {
  2920             flags |= Flags.DEPRECATED;
  2922         int pos = token.pos;
  2923         List<JCAnnotation> annotations = annotationsOpt();
  2924         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2925         List<JCExpression> typeArgs = typeArgumentsOpt();
  2926         int identPos = token.pos;
  2927         Name name = ident();
  2928         int createPos = token.pos;
  2929         List<JCExpression> args = (token.kind == LPAREN)
  2930             ? arguments() : List.<JCExpression>nil();
  2931         JCClassDecl body = null;
  2932         if (token.kind == LBRACE) {
  2933             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2934             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2935             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2937         if (args.isEmpty() && body == null)
  2938             createPos = identPos;
  2939         JCIdent ident = F.at(identPos).Ident(enumName);
  2940         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2941         if (createPos != identPos)
  2942             storeEnd(create, S.prevToken().endPos);
  2943         ident = F.at(identPos).Ident(enumName);
  2944         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2945         attach(result, dc);
  2946         return result;
  2949     /** TypeList = Type {"," Type}
  2950      */
  2951     List<JCExpression> typeList() {
  2952         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2953         ts.append(parseType());
  2954         while (token.kind == COMMA) {
  2955             nextToken();
  2956             ts.append(parseType());
  2958         return ts.toList();
  2961     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2962      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2963      */
  2964     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2965         accept(LBRACE);
  2966         if (token.pos <= endPosTable.errorEndPos) {
  2967             // error recovery
  2968             skip(false, true, false, false);
  2969             if (token.kind == LBRACE)
  2970                 nextToken();
  2972         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2973         while (token.kind != RBRACE && token.kind != EOF) {
  2974             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2975             if (token.pos <= endPosTable.errorEndPos) {
  2976                // error recovery
  2977                skip(false, true, true, false);
  2980         accept(RBRACE);
  2981         return defs.toList();
  2984     /** ClassBodyDeclaration =
  2985      *      ";"
  2986      *    | [STATIC] Block
  2987      *    | ModifiersOpt
  2988      *      ( Type Ident
  2989      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2990      *      | VOID Ident MethodDeclaratorRest
  2991      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2992      *      | Ident ConstructorDeclaratorRest
  2993      *      | TypeParameters Ident ConstructorDeclaratorRest
  2994      *      | ClassOrInterfaceOrEnumDeclaration
  2995      *      )
  2996      *  InterfaceBodyDeclaration =
  2997      *      ";"
  2998      *    | ModifiersOpt Type Ident
  2999      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  3000      */
  3001     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  3002         if (token.kind == SEMI) {
  3003             nextToken();
  3004             return List.<JCTree>nil();
  3005         } else {
  3006             Comment dc = token.comment(CommentStyle.JAVADOC);
  3007             int pos = token.pos;
  3008             JCModifiers mods = modifiersOpt();
  3009             if (token.kind == CLASS ||
  3010                 token.kind == INTERFACE ||
  3011                 allowEnums && token.kind == ENUM) {
  3012                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  3013             } else if (token.kind == LBRACE && !isInterface &&
  3014                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  3015                        mods.annotations.isEmpty()) {
  3016                 return List.<JCTree>of(block(pos, mods.flags));
  3017             } else {
  3018                 pos = token.pos;
  3019                 List<JCTypeParameter> typarams = typeParametersOpt();
  3020                 // if there are type parameters but no modifiers, save the start
  3021                 // position of the method in the modifiers.
  3022                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  3023                     mods.pos = pos;
  3024                     storeEnd(mods, pos);
  3026                 Token tk = token;
  3027                 pos = token.pos;
  3028                 JCExpression type;
  3029                 boolean isVoid = token.kind == VOID;
  3030                 if (isVoid) {
  3031                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
  3032                     nextToken();
  3033                 } else {
  3034                     type = parseType();
  3036                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  3037                     if (isInterface || tk.name() != className)
  3038                         error(pos, "invalid.meth.decl.ret.type.req");
  3039                     return List.of(methodDeclaratorRest(
  3040                         pos, mods, null, names.init, typarams,
  3041                         isInterface, true, dc));
  3042                 } else {
  3043                     pos = token.pos;
  3044                     Name name = ident();
  3045                     if (token.kind == LPAREN) {
  3046                         return List.of(methodDeclaratorRest(
  3047                             pos, mods, type, name, typarams,
  3048                             isInterface, isVoid, dc));
  3049                     } else if (!isVoid && typarams.isEmpty()) {
  3050                         List<JCTree> defs =
  3051                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  3052                                                     new ListBuffer<JCTree>()).toList();
  3053                         storeEnd(defs.last(), token.endPos);
  3054                         accept(SEMI);
  3055                         return defs;
  3056                     } else {
  3057                         pos = token.pos;
  3058                         List<JCTree> err = isVoid
  3059                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3060                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  3061                             : null;
  3062                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  3069     /** MethodDeclaratorRest =
  3070      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  3071      *  VoidMethodDeclaratorRest =
  3072      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  3073      *  InterfaceMethodDeclaratorRest =
  3074      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  3075      *  VoidInterfaceMethodDeclaratorRest =
  3076      *      FormalParameters [THROWS TypeList] ";"
  3077      *  ConstructorDeclaratorRest =
  3078      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  3079      */
  3080     protected JCTree methodDeclaratorRest(int pos,
  3081                               JCModifiers mods,
  3082                               JCExpression type,
  3083                               Name name,
  3084                               List<JCTypeParameter> typarams,
  3085                               boolean isInterface, boolean isVoid,
  3086                               Comment dc) {
  3087         List<JCVariableDecl> params = formalParameters();
  3088         if (!isVoid) type = bracketsOpt(type);
  3089         List<JCExpression> thrown = List.nil();
  3090         if (token.kind == THROWS) {
  3091             nextToken();
  3092             thrown = qualidentList();
  3094         JCBlock body = null;
  3095         JCExpression defaultValue;
  3096         if (token.kind == LBRACE) {
  3097             body = block();
  3098             defaultValue = null;
  3099         } else {
  3100             if (token.kind == DEFAULT) {
  3101                 accept(DEFAULT);
  3102                 defaultValue = annotationValue();
  3103             } else {
  3104                 defaultValue = null;
  3106             accept(SEMI);
  3107             if (token.pos <= endPosTable.errorEndPos) {
  3108                 // error recovery
  3109                 skip(false, true, false, false);
  3110                 if (token.kind == LBRACE) {
  3111                     body = block();
  3116         JCMethodDecl result =
  3117             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3118                                     params, thrown,
  3119                                     body, defaultValue));
  3120         attach(result, dc);
  3121         return result;
  3124     /** QualidentList = Qualident {"," Qualident}
  3125      */
  3126     List<JCExpression> qualidentList() {
  3127         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3128         ts.append(qualident());
  3129         while (token.kind == COMMA) {
  3130             nextToken();
  3131             ts.append(qualident());
  3133         return ts.toList();
  3136     /**
  3137      *  {@literal
  3138      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3139      *  }
  3140      */
  3141     List<JCTypeParameter> typeParametersOpt() {
  3142         if (token.kind == LT) {
  3143             checkGenerics();
  3144             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3145             nextToken();
  3146             typarams.append(typeParameter());
  3147             while (token.kind == COMMA) {
  3148                 nextToken();
  3149                 typarams.append(typeParameter());
  3151             accept(GT);
  3152             return typarams.toList();
  3153         } else {
  3154             return List.nil();
  3158     /**
  3159      *  {@literal
  3160      *  TypeParameter = TypeVariable [TypeParameterBound]
  3161      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3162      *  TypeVariable = Ident
  3163      *  }
  3164      */
  3165     JCTypeParameter typeParameter() {
  3166         int pos = token.pos;
  3167         Name name = ident();
  3168         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3169         if (token.kind == EXTENDS) {
  3170             nextToken();
  3171             bounds.append(parseType());
  3172             while (token.kind == AMP) {
  3173                 nextToken();
  3174                 bounds.append(parseType());
  3177         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  3180     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3181      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3182      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3183      */
  3184     List<JCVariableDecl> formalParameters() {
  3185         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3186         JCVariableDecl lastParam = null;
  3187         accept(LPAREN);
  3188         if (token.kind != RPAREN) {
  3189             params.append(lastParam = formalParameter());
  3190             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3191                 nextToken();
  3192                 params.append(lastParam = formalParameter());
  3195         accept(RPAREN);
  3196         return params.toList();
  3199     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3200         if (hasParens) {
  3201             accept(LPAREN);
  3203         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3204         if (token.kind != RPAREN && token.kind != ARROW) {
  3205             params.append(implicitParameter());
  3206             while (token.kind == COMMA) {
  3207                 nextToken();
  3208                 params.append(implicitParameter());
  3211         if (hasParens) {
  3212             accept(RPAREN);
  3214         return params.toList();
  3217     JCModifiers optFinal(long flags) {
  3218         JCModifiers mods = modifiersOpt();
  3219         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3220         mods.flags |= flags;
  3221         return mods;
  3224     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3225      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3226      */
  3227     protected JCVariableDecl formalParameter() {
  3228         JCModifiers mods = optFinal(Flags.PARAMETER);
  3229         JCExpression type = parseType();
  3230         if (token.kind == ELLIPSIS) {
  3231             checkVarargs();
  3232             mods.flags |= Flags.VARARGS;
  3233             type = to(F.at(token.pos).TypeArray(type));
  3234             nextToken();
  3236         return variableDeclaratorId(mods, type);
  3239     protected JCVariableDecl implicitParameter() {
  3240         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3241         return variableDeclaratorId(mods, null);
  3244 /* ---------- auxiliary methods -------------- */
  3246     void error(int pos, String key, Object ... args) {
  3247         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3250     void error(DiagnosticPosition pos, String key, Object ... args) {
  3251         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3254     void warning(int pos, String key, Object ... args) {
  3255         log.warning(pos, key, args);
  3258     /** Check that given tree is a legal expression statement.
  3259      */
  3260     protected JCExpression checkExprStat(JCExpression t) {
  3261         if (!TreeInfo.isExpressionStatement(t)) {
  3262             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3263             error(ret, "not.stmt");
  3264             return ret;
  3265         } else {
  3266             return t;
  3270     /** Return precedence of operator represented by token,
  3271      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3272      */
  3273     static int prec(TokenKind token) {
  3274         JCTree.Tag oc = optag(token);
  3275         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3278     /**
  3279      * Return the lesser of two positions, making allowance for either one
  3280      * being unset.
  3281      */
  3282     static int earlier(int pos1, int pos2) {
  3283         if (pos1 == Position.NOPOS)
  3284             return pos2;
  3285         if (pos2 == Position.NOPOS)
  3286             return pos1;
  3287         return (pos1 < pos2 ? pos1 : pos2);
  3290     /** Return operation tag of binary operator represented by token,
  3291      *  No_TAG if token is not a binary operator.
  3292      */
  3293     static JCTree.Tag optag(TokenKind token) {
  3294         switch (token) {
  3295         case BARBAR:
  3296             return OR;
  3297         case AMPAMP:
  3298             return AND;
  3299         case BAR:
  3300             return BITOR;
  3301         case BAREQ:
  3302             return BITOR_ASG;
  3303         case CARET:
  3304             return BITXOR;
  3305         case CARETEQ:
  3306             return BITXOR_ASG;
  3307         case AMP:
  3308             return BITAND;
  3309         case AMPEQ:
  3310             return BITAND_ASG;
  3311         case EQEQ:
  3312             return JCTree.Tag.EQ;
  3313         case BANGEQ:
  3314             return NE;
  3315         case LT:
  3316             return JCTree.Tag.LT;
  3317         case GT:
  3318             return JCTree.Tag.GT;
  3319         case LTEQ:
  3320             return LE;
  3321         case GTEQ:
  3322             return GE;
  3323         case LTLT:
  3324             return SL;
  3325         case LTLTEQ:
  3326             return SL_ASG;
  3327         case GTGT:
  3328             return SR;
  3329         case GTGTEQ:
  3330             return SR_ASG;
  3331         case GTGTGT:
  3332             return USR;
  3333         case GTGTGTEQ:
  3334             return USR_ASG;
  3335         case PLUS:
  3336             return JCTree.Tag.PLUS;
  3337         case PLUSEQ:
  3338             return PLUS_ASG;
  3339         case SUB:
  3340             return MINUS;
  3341         case SUBEQ:
  3342             return MINUS_ASG;
  3343         case STAR:
  3344             return MUL;
  3345         case STAREQ:
  3346             return MUL_ASG;
  3347         case SLASH:
  3348             return DIV;
  3349         case SLASHEQ:
  3350             return DIV_ASG;
  3351         case PERCENT:
  3352             return MOD;
  3353         case PERCENTEQ:
  3354             return MOD_ASG;
  3355         case INSTANCEOF:
  3356             return TYPETEST;
  3357         default:
  3358             return NO_TAG;
  3362     /** Return operation tag of unary operator represented by token,
  3363      *  No_TAG if token is not a binary operator.
  3364      */
  3365     static JCTree.Tag unoptag(TokenKind token) {
  3366         switch (token) {
  3367         case PLUS:
  3368             return POS;
  3369         case SUB:
  3370             return NEG;
  3371         case BANG:
  3372             return NOT;
  3373         case TILDE:
  3374             return COMPL;
  3375         case PLUSPLUS:
  3376             return PREINC;
  3377         case SUBSUB:
  3378             return PREDEC;
  3379         default:
  3380             return NO_TAG;
  3384     /** Return type tag of basic type represented by token,
  3385      *  NONE if token is not a basic type identifier.
  3386      */
  3387     static TypeTag typetag(TokenKind token) {
  3388         switch (token) {
  3389         case BYTE:
  3390             return TypeTag.BYTE;
  3391         case CHAR:
  3392             return TypeTag.CHAR;
  3393         case SHORT:
  3394             return TypeTag.SHORT;
  3395         case INT:
  3396             return TypeTag.INT;
  3397         case LONG:
  3398             return TypeTag.LONG;
  3399         case FLOAT:
  3400             return TypeTag.FLOAT;
  3401         case DOUBLE:
  3402             return TypeTag.DOUBLE;
  3403         case BOOLEAN:
  3404             return TypeTag.BOOLEAN;
  3405         default:
  3406             return TypeTag.NONE;
  3410     void checkGenerics() {
  3411         if (!allowGenerics) {
  3412             error(token.pos, "generics.not.supported.in.source", source.name);
  3413             allowGenerics = true;
  3416     void checkVarargs() {
  3417         if (!allowVarargs) {
  3418             error(token.pos, "varargs.not.supported.in.source", source.name);
  3419             allowVarargs = true;
  3422     void checkForeach() {
  3423         if (!allowForeach) {
  3424             error(token.pos, "foreach.not.supported.in.source", source.name);
  3425             allowForeach = true;
  3428     void checkStaticImports() {
  3429         if (!allowStaticImport) {
  3430             error(token.pos, "static.import.not.supported.in.source", source.name);
  3431             allowStaticImport = true;
  3434     void checkAnnotations() {
  3435         if (!allowAnnotations) {
  3436             error(token.pos, "annotations.not.supported.in.source", source.name);
  3437             allowAnnotations = true;
  3440     void checkDiamond() {
  3441         if (!allowDiamond) {
  3442             error(token.pos, "diamond.not.supported.in.source", source.name);
  3443             allowDiamond = true;
  3446     void checkMulticatch() {
  3447         if (!allowMulticatch) {
  3448             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3449             allowMulticatch = true;
  3452     void checkTryWithResources() {
  3453         if (!allowTWR) {
  3454             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3455             allowTWR = true;
  3458     void checkLambda() {
  3459         if (!allowLambda) {
  3460             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3461             allowLambda = true;
  3464     void checkMethodReferences() {
  3465         if (!allowMethodReferences) {
  3466             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3467             allowMethodReferences = true;
  3470     void checkDefaultMethods() {
  3471         if (!allowDefaultMethods) {
  3472             log.error(token.pos, "default.methods.not.supported.in.source", source.name);
  3473             allowDefaultMethods = true;
  3476     void checkIntersectionTypesInCast() {
  3477         if (!allowIntersectionTypesInCast) {
  3478             log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name);
  3479             allowIntersectionTypesInCast = true;
  3483     /*
  3484      * a functional source tree and end position mappings
  3485      */
  3486     protected class SimpleEndPosTable extends AbstractEndPosTable {
  3488         private final Map<JCTree, Integer> endPosMap;
  3490         SimpleEndPosTable() {
  3491             endPosMap = new HashMap<JCTree, Integer>();
  3494         protected void storeEnd(JCTree tree, int endpos) {
  3495             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  3498         protected <T extends JCTree> T to(T t) {
  3499             storeEnd(t, token.endPos);
  3500             return t;
  3503         protected <T extends JCTree> T toP(T t) {
  3504             storeEnd(t, S.prevToken().endPos);
  3505             return t;
  3508         public int getEndPos(JCTree tree) {
  3509             Integer value = endPosMap.get(tree);
  3510             return (value == null) ? Position.NOPOS : value;
  3513         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3514             Integer pos = endPosMap.remove(oldTree);
  3515             if (pos != null) {
  3516                 endPosMap.put(newTree, pos);
  3517                 return pos;
  3519             return Position.NOPOS;
  3523     /*
  3524      * a default skeletal implementation without any mapping overhead.
  3525      */
  3526     protected class EmptyEndPosTable extends AbstractEndPosTable {
  3528         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  3530         protected <T extends JCTree> T to(T t) {
  3531             return t;
  3534         protected <T extends JCTree> T toP(T t) {
  3535             return t;
  3538         public int getEndPos(JCTree tree) {
  3539             return Position.NOPOS;
  3542         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3543             return Position.NOPOS;
  3548     protected abstract class AbstractEndPosTable implements EndPosTable {
  3550         /**
  3551          * Store the last error position.
  3552          */
  3553         protected int errorEndPos;
  3555         /**
  3556          * Store ending position for a tree, the value of which is the greater
  3557          * of last error position and the given ending position.
  3558          * @param tree   The tree.
  3559          * @param endpos The ending position to associate with the tree.
  3560          */
  3561         protected abstract void storeEnd(JCTree tree, int endpos);
  3563         /**
  3564          * Store current token's ending position for a tree, the value of which
  3565          * will be the greater of last error position and the ending position of
  3566          * the current token.
  3567          * @param t The tree.
  3568          */
  3569         protected abstract <T extends JCTree> T to(T t);
  3571         /**
  3572          * Store current token's ending position for a tree, the value of which
  3573          * will be the greater of last error position and the ending position of
  3574          * the previous token.
  3575          * @param t The tree.
  3576          */
  3577         protected abstract <T extends JCTree> T toP(T t);
  3579         /**
  3580          * Set the error position during the parsing phases, the value of which
  3581          * will be set only if it is greater than the last stored error position.
  3582          * @param errPos The error position
  3583          */
  3584         protected void setErrorEndPos(int errPos) {
  3585             if (errPos > errorEndPos) {
  3586                 errorEndPos = errPos;

mercurial