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

Fri, 30 Nov 2012 15:14:36 +0000

author
mcimadamore
date
Fri, 30 Nov 2012 15:14:36 +0000
changeset 1435
9b26c96f5138
parent 1433
4f9853659bf1
child 1436
f6f1fd261f57
permissions
-rw-r--r--

8004101: Add checks for method reference well-formedness
Summary: Bring method reference type-checking in sync with latest EDR
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.keepDocComments = keepDocComments;
   128         docComments = newDocCommentTable(keepDocComments, fac);
   129         this.keepLineMap = keepLineMap;
   130         this.errorTree = F.Erroneous();
   131         endPosTable = newEndPosTable(keepEndPositions);
   132     }
   134     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
   135         return  keepEndPositions
   136                 ? new SimpleEndPosTable()
   137                 : new EmptyEndPosTable();
   138     }
   140     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
   141         return keepDocComments ? new LazyDocCommentTable(fac) : null;
   142     }
   144     /** Switch: Should generics be recognized?
   145      */
   146     boolean allowGenerics;
   148     /** Switch: Should diamond operator be recognized?
   149      */
   150     boolean allowDiamond;
   152     /** Switch: Should multicatch clause be accepted?
   153      */
   154     boolean allowMulticatch;
   156     /** Switch: Should varargs be recognized?
   157      */
   158     boolean allowVarargs;
   160     /** Switch: should we recognize assert statements, or just give a warning?
   161      */
   162     boolean allowAsserts;
   164     /** Switch: should we recognize enums, or just give a warning?
   165      */
   166     boolean allowEnums;
   168     /** Switch: should we recognize foreach?
   169      */
   170     boolean allowForeach;
   172     /** Switch: should we recognize foreach?
   173      */
   174     boolean allowStaticImport;
   176     /** Switch: should we recognize annotations?
   177      */
   178     boolean allowAnnotations;
   180     /** Switch: should we recognize try-with-resources?
   181      */
   182     boolean allowTWR;
   184     /** Switch: should we fold strings?
   185      */
   186     boolean allowStringFolding;
   188     /** Switch: should we recognize lambda expressions?
   189      */
   190     boolean allowLambda;
   192     /** Switch: should we allow method/constructor references?
   193      */
   194     boolean allowMethodReferences;
   196     /** Switch: should we allow default methods in interfaces?
   197      */
   198     boolean allowDefaultMethods;
   200     /** Switch: should we keep docComments?
   201      */
   202     boolean keepDocComments;
   204     /** Switch: should we keep line table?
   205      */
   206     boolean keepLineMap;
   208     /** When terms are parsed, the mode determines which is expected:
   209      *     mode = EXPR        : an expression
   210      *     mode = TYPE        : a type
   211      *     mode = NOPARAMS    : no parameters allowed for type
   212      *     mode = TYPEARG     : type argument
   213      */
   214     static final int EXPR = 0x1;
   215     static final int TYPE = 0x2;
   216     static final int NOPARAMS = 0x4;
   217     static final int TYPEARG = 0x8;
   218     static final int DIAMOND = 0x10;
   220     /** The current mode.
   221      */
   222     private int mode = 0;
   224     /** The mode of the term that was parsed last.
   225      */
   226     private int lastmode = 0;
   228     /* ---------- token management -------------- */
   230     protected Token token;
   232     public Token token() {
   233         return token;
   234     }
   236     public void nextToken() {
   237         S.nextToken();
   238         token = S.token();
   239     }
   241     protected boolean peekToken(TokenKind tk) {
   242         return S.token(1).kind == tk;
   243     }
   245     protected boolean peekToken(TokenKind tk1, TokenKind tk2) {
   246         return S.token(1).kind == tk1 &&
   247                 S.token(2).kind == tk2;
   248     }
   250     protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) {
   251         return S.token(1).kind == tk1 &&
   252                 S.token(2).kind == tk2 &&
   253                 S.token(3).kind == tk3;
   254     }
   256     protected boolean peekToken(TokenKind... kinds) {
   257         for (int lookahead = 0 ; lookahead < kinds.length ; lookahead++) {
   258             if (S.token(lookahead + 1).kind != kinds[lookahead]) {
   259                 return false;
   260             }
   261         }
   262         return true;
   263     }
   265     /* ---------- error recovery -------------- */
   267     private JCErroneous errorTree;
   269     /** Skip forward until a suitable stop token is found.
   270      */
   271     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   272          while (true) {
   273              switch (token.kind) {
   274                 case SEMI:
   275                     nextToken();
   276                     return;
   277                 case PUBLIC:
   278                 case FINAL:
   279                 case ABSTRACT:
   280                 case MONKEYS_AT:
   281                 case EOF:
   282                 case CLASS:
   283                 case INTERFACE:
   284                 case ENUM:
   285                     return;
   286                 case IMPORT:
   287                     if (stopAtImport)
   288                         return;
   289                     break;
   290                 case LBRACE:
   291                 case RBRACE:
   292                 case PRIVATE:
   293                 case PROTECTED:
   294                 case STATIC:
   295                 case TRANSIENT:
   296                 case NATIVE:
   297                 case VOLATILE:
   298                 case SYNCHRONIZED:
   299                 case STRICTFP:
   300                 case LT:
   301                 case BYTE:
   302                 case SHORT:
   303                 case CHAR:
   304                 case INT:
   305                 case LONG:
   306                 case FLOAT:
   307                 case DOUBLE:
   308                 case BOOLEAN:
   309                 case VOID:
   310                     if (stopAtMemberDecl)
   311                         return;
   312                     break;
   313                 case IDENTIFIER:
   314                    if (stopAtIdentifier)
   315                         return;
   316                     break;
   317                 case CASE:
   318                 case DEFAULT:
   319                 case IF:
   320                 case FOR:
   321                 case WHILE:
   322                 case DO:
   323                 case TRY:
   324                 case SWITCH:
   325                 case RETURN:
   326                 case THROW:
   327                 case BREAK:
   328                 case CONTINUE:
   329                 case ELSE:
   330                 case FINALLY:
   331                 case CATCH:
   332                     if (stopAtStatement)
   333                         return;
   334                     break;
   335             }
   336             nextToken();
   337         }
   338     }
   340     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   341         return syntaxError(pos, List.<JCTree>nil(), key, args);
   342     }
   344     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   345         setErrorEndPos(pos);
   346         JCErroneous err = F.at(pos).Erroneous(errs);
   347         reportSyntaxError(err, key, (Object[])args);
   348         if (errs != null) {
   349             JCTree last = errs.last();
   350             if (last != null)
   351                 storeEnd(last, pos);
   352         }
   353         return toP(err);
   354     }
   356     private int errorPos = Position.NOPOS;
   358     /**
   359      * Report a syntax using the given the position parameter and arguments,
   360      * unless one was already reported at the same position.
   361      */
   362     private void reportSyntaxError(int pos, String key, Object... args) {
   363         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   364         reportSyntaxError(diag, key, args);
   365     }
   367     /**
   368      * Report a syntax error using the given DiagnosticPosition object and
   369      * arguments, unless one was already reported at the same position.
   370      */
   371     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   372         int pos = diagPos.getPreferredPosition();
   373         if (pos > S.errPos() || pos == Position.NOPOS) {
   374             if (token.kind == EOF) {
   375                 error(diagPos, "premature.eof");
   376             } else {
   377                 error(diagPos, key, args);
   378             }
   379         }
   380         S.errPos(pos);
   381         if (token.pos == errorPos)
   382             nextToken(); // guarantee progress
   383         errorPos = token.pos;
   384     }
   387     /** Generate a syntax error at current position unless one was already
   388      *  reported at the same position.
   389      */
   390     private JCErroneous syntaxError(String key) {
   391         return syntaxError(token.pos, key);
   392     }
   394     /** Generate a syntax error at current position unless one was
   395      *  already reported at the same position.
   396      */
   397     private JCErroneous syntaxError(String key, TokenKind arg) {
   398         return syntaxError(token.pos, key, arg);
   399     }
   401     /** If next input token matches given token, skip it, otherwise report
   402      *  an error.
   403      */
   404     public void accept(TokenKind tk) {
   405         if (token.kind == tk) {
   406             nextToken();
   407         } else {
   408             setErrorEndPos(token.pos);
   409             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   410         }
   411     }
   413     /** Report an illegal start of expression/type error at given position.
   414      */
   415     JCExpression illegal(int pos) {
   416         setErrorEndPos(pos);
   417         if ((mode & EXPR) != 0)
   418             return syntaxError(pos, "illegal.start.of.expr");
   419         else
   420             return syntaxError(pos, "illegal.start.of.type");
   422     }
   424     /** Report an illegal start of expression/type error at current position.
   425      */
   426     JCExpression illegal() {
   427         return illegal(token.pos);
   428     }
   430     /** Diagnose a modifier flag from the set, if any. */
   431     void checkNoMods(long mods) {
   432         if (mods != 0) {
   433             long lowestMod = mods & -mods;
   434             error(token.pos, "mod.not.allowed.here",
   435                       Flags.asFlagSet(lowestMod));
   436         }
   437     }
   439 /* ---------- doc comments --------- */
   441     /** A table to store all documentation comments
   442      *  indexed by the tree nodes they refer to.
   443      *  defined only if option flag keepDocComment is set.
   444      */
   445     private final DocCommentTable docComments;
   447     /** Make an entry into docComments hashtable,
   448      *  provided flag keepDocComments is set and given doc comment is non-null.
   449      *  @param tree   The tree to be used as index in the hashtable
   450      *  @param dc     The doc comment to associate with the tree, or null.
   451      */
   452     void attach(JCTree tree, Comment dc) {
   453         if (keepDocComments && dc != null) {
   454 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   455             docComments.putComment(tree, dc);
   456         }
   457     }
   459 /* -------- source positions ------- */
   461     private void setErrorEndPos(int errPos) {
   462         endPosTable.setErrorEndPos(errPos);
   463     }
   465     private void storeEnd(JCTree tree, int endpos) {
   466         endPosTable.storeEnd(tree, endpos);
   467     }
   469     private <T extends JCTree> T to(T t) {
   470         return endPosTable.to(t);
   471     }
   473     private <T extends JCTree> T toP(T t) {
   474         return endPosTable.toP(t);
   475     }
   477     /** Get the start position for a tree node.  The start position is
   478      * defined to be the position of the first character of the first
   479      * token of the node's source text.
   480      * @param tree  The tree node
   481      */
   482     public int getStartPos(JCTree tree) {
   483         return TreeInfo.getStartPos(tree);
   484     }
   486     /**
   487      * Get the end position for a tree node.  The end position is
   488      * defined to be the position of the last character of the last
   489      * token of the node's source text.  Returns Position.NOPOS if end
   490      * positions are not generated or the position is otherwise not
   491      * found.
   492      * @param tree  The tree node
   493      */
   494     public int getEndPos(JCTree tree) {
   495         return endPosTable.getEndPos(tree);
   496     }
   500 /* ---------- parsing -------------- */
   502     /**
   503      * Ident = IDENTIFIER
   504      */
   505     Name ident() {
   506         if (token.kind == IDENTIFIER) {
   507             Name name = token.name();
   508             nextToken();
   509             return name;
   510         } else if (token.kind == ASSERT) {
   511             if (allowAsserts) {
   512                 error(token.pos, "assert.as.identifier");
   513                 nextToken();
   514                 return names.error;
   515             } else {
   516                 warning(token.pos, "assert.as.identifier");
   517                 Name name = token.name();
   518                 nextToken();
   519                 return name;
   520             }
   521         } else if (token.kind == ENUM) {
   522             if (allowEnums) {
   523                 error(token.pos, "enum.as.identifier");
   524                 nextToken();
   525                 return names.error;
   526             } else {
   527                 warning(token.pos, "enum.as.identifier");
   528                 Name name = token.name();
   529                 nextToken();
   530                 return name;
   531             }
   532         } else {
   533             accept(IDENTIFIER);
   534             return names.error;
   535         }
   536 }
   538     /**
   539      * Qualident = Ident { DOT Ident }
   540      */
   541     public JCExpression qualident() {
   542         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   543         while (token.kind == DOT) {
   544             int pos = token.pos;
   545             nextToken();
   546             t = toP(F.at(pos).Select(t, ident()));
   547         }
   548         return t;
   549     }
   551     JCExpression literal(Name prefix) {
   552         return literal(prefix, token.pos);
   553     }
   555     /**
   556      * Literal =
   557      *     INTLITERAL
   558      *   | LONGLITERAL
   559      *   | FLOATLITERAL
   560      *   | DOUBLELITERAL
   561      *   | CHARLITERAL
   562      *   | STRINGLITERAL
   563      *   | TRUE
   564      *   | FALSE
   565      *   | NULL
   566      */
   567     JCExpression literal(Name prefix, int pos) {
   568         JCExpression t = errorTree;
   569         switch (token.kind) {
   570         case INTLITERAL:
   571             try {
   572                 t = F.at(pos).Literal(
   573                     TypeTag.INT,
   574                     Convert.string2int(strval(prefix), token.radix()));
   575             } catch (NumberFormatException ex) {
   576                 error(token.pos, "int.number.too.large", strval(prefix));
   577             }
   578             break;
   579         case LONGLITERAL:
   580             try {
   581                 t = F.at(pos).Literal(
   582                     TypeTag.LONG,
   583                     new Long(Convert.string2long(strval(prefix), token.radix())));
   584             } catch (NumberFormatException ex) {
   585                 error(token.pos, "int.number.too.large", strval(prefix));
   586             }
   587             break;
   588         case FLOATLITERAL: {
   589             String proper = token.radix() == 16 ?
   590                     ("0x"+ token.stringVal()) :
   591                     token.stringVal();
   592             Float n;
   593             try {
   594                 n = Float.valueOf(proper);
   595             } catch (NumberFormatException ex) {
   596                 // error already reported in scanner
   597                 n = Float.NaN;
   598             }
   599             if (n.floatValue() == 0.0f && !isZero(proper))
   600                 error(token.pos, "fp.number.too.small");
   601             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   602                 error(token.pos, "fp.number.too.large");
   603             else
   604                 t = F.at(pos).Literal(TypeTag.FLOAT, n);
   605             break;
   606         }
   607         case DOUBLELITERAL: {
   608             String proper = token.radix() == 16 ?
   609                     ("0x"+ token.stringVal()) :
   610                     token.stringVal();
   611             Double n;
   612             try {
   613                 n = Double.valueOf(proper);
   614             } catch (NumberFormatException ex) {
   615                 // error already reported in scanner
   616                 n = Double.NaN;
   617             }
   618             if (n.doubleValue() == 0.0d && !isZero(proper))
   619                 error(token.pos, "fp.number.too.small");
   620             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   621                 error(token.pos, "fp.number.too.large");
   622             else
   623                 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
   624             break;
   625         }
   626         case CHARLITERAL:
   627             t = F.at(pos).Literal(
   628                 TypeTag.CHAR,
   629                 token.stringVal().charAt(0) + 0);
   630             break;
   631         case STRINGLITERAL:
   632             t = F.at(pos).Literal(
   633                 TypeTag.CLASS,
   634                 token.stringVal());
   635             break;
   636         case TRUE: case FALSE:
   637             t = F.at(pos).Literal(
   638                 TypeTag.BOOLEAN,
   639                 (token.kind == TRUE ? 1 : 0));
   640             break;
   641         case NULL:
   642             t = F.at(pos).Literal(
   643                 TypeTag.BOT,
   644                 null);
   645             break;
   646         default:
   647             Assert.error();
   648         }
   649         if (t == errorTree)
   650             t = F.at(pos).Erroneous();
   651         storeEnd(t, token.endPos);
   652         nextToken();
   653         return t;
   654     }
   655 //where
   656         boolean isZero(String s) {
   657             char[] cs = s.toCharArray();
   658             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   659             int i = ((base==16) ? 2 : 0);
   660             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   661             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   662         }
   664         String strval(Name prefix) {
   665             String s = token.stringVal();
   666             return prefix.isEmpty() ? s : prefix + s;
   667         }
   669     /** terms can be either expressions or types.
   670      */
   671     public JCExpression parseExpression() {
   672         return term(EXPR);
   673     }
   675     public JCExpression parseType() {
   676         return term(TYPE);
   677     }
   679     JCExpression term(int newmode) {
   680         int prevmode = mode;
   681         mode = newmode;
   682         JCExpression t = term();
   683         lastmode = mode;
   684         mode = prevmode;
   685         return t;
   686     }
   688     /**
   689      *  {@literal
   690      *  Expression = Expression1 [ExpressionRest]
   691      *  ExpressionRest = [AssignmentOperator Expression1]
   692      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   693      *                       "&=" | "|=" | "^=" |
   694      *                       "%=" | "<<=" | ">>=" | ">>>="
   695      *  Type = Type1
   696      *  TypeNoParams = TypeNoParams1
   697      *  StatementExpression = Expression
   698      *  ConstantExpression = Expression
   699      *  }
   700      */
   701     JCExpression term() {
   702         JCExpression t = term1();
   703         if ((mode & EXPR) != 0 &&
   704             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   705             return termRest(t);
   706         else
   707             return t;
   708     }
   710     JCExpression termRest(JCExpression t) {
   711         switch (token.kind) {
   712         case EQ: {
   713             int pos = token.pos;
   714             nextToken();
   715             mode = EXPR;
   716             JCExpression t1 = term();
   717             return toP(F.at(pos).Assign(t, t1));
   718         }
   719         case PLUSEQ:
   720         case SUBEQ:
   721         case STAREQ:
   722         case SLASHEQ:
   723         case PERCENTEQ:
   724         case AMPEQ:
   725         case BAREQ:
   726         case CARETEQ:
   727         case LTLTEQ:
   728         case GTGTEQ:
   729         case GTGTGTEQ:
   730             int pos = token.pos;
   731             TokenKind tk = token.kind;
   732             nextToken();
   733             mode = EXPR;
   734             JCExpression t1 = term();
   735             return F.at(pos).Assignop(optag(tk), t, t1);
   736         default:
   737             return t;
   738         }
   739     }
   741     /** Expression1   = Expression2 [Expression1Rest]
   742      *  Type1         = Type2
   743      *  TypeNoParams1 = TypeNoParams2
   744      */
   745     JCExpression term1() {
   746         JCExpression t = term2();
   747         if ((mode & EXPR) != 0 && token.kind == QUES) {
   748             mode = EXPR;
   749             return term1Rest(t);
   750         } else {
   751             return t;
   752         }
   753     }
   755     /** Expression1Rest = ["?" Expression ":" Expression1]
   756      */
   757     JCExpression term1Rest(JCExpression t) {
   758         if (token.kind == QUES) {
   759             int pos = token.pos;
   760             nextToken();
   761             JCExpression t1 = term();
   762             accept(COLON);
   763             JCExpression t2 = term1();
   764             return F.at(pos).Conditional(t, t1, t2);
   765         } else {
   766             return t;
   767         }
   768     }
   770     /** Expression2   = Expression3 [Expression2Rest]
   771      *  Type2         = Type3
   772      *  TypeNoParams2 = TypeNoParams3
   773      */
   774     JCExpression term2() {
   775         JCExpression t = term3();
   776         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   777             mode = EXPR;
   778             return term2Rest(t, TreeInfo.orPrec);
   779         } else {
   780             return t;
   781         }
   782     }
   784     /*  Expression2Rest = {infixop Expression3}
   785      *                  | Expression3 instanceof Type
   786      *  infixop         = "||"
   787      *                  | "&&"
   788      *                  | "|"
   789      *                  | "^"
   790      *                  | "&"
   791      *                  | "==" | "!="
   792      *                  | "<" | ">" | "<=" | ">="
   793      *                  | "<<" | ">>" | ">>>"
   794      *                  | "+" | "-"
   795      *                  | "*" | "/" | "%"
   796      */
   797     JCExpression term2Rest(JCExpression t, int minprec) {
   798         List<JCExpression[]> savedOd = odStackSupply.elems;
   799         JCExpression[] odStack = newOdStack();
   800         List<Token[]> savedOp = opStackSupply.elems;
   801         Token[] opStack = newOpStack();
   803         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   804         int top = 0;
   805         odStack[0] = t;
   806         int startPos = token.pos;
   807         Token topOp = Tokens.DUMMY;
   808         while (prec(token.kind) >= minprec) {
   809             opStack[top] = topOp;
   810             top++;
   811             topOp = token;
   812             nextToken();
   813             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   814             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   815                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   816                                         odStack[top]);
   817                 top--;
   818                 topOp = opStack[top];
   819             }
   820         }
   821         Assert.check(top == 0);
   822         t = odStack[0];
   824         if (t.hasTag(JCTree.Tag.PLUS)) {
   825             StringBuilder buf = foldStrings(t);
   826             if (buf != null) {
   827                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
   828             }
   829         }
   831         odStackSupply.elems = savedOd; // optimization
   832         opStackSupply.elems = savedOp; // optimization
   833         return t;
   834     }
   835 //where
   836         /** Construct a binary or type test node.
   837          */
   838         private JCExpression makeOp(int pos,
   839                                     TokenKind topOp,
   840                                     JCExpression od1,
   841                                     JCExpression od2)
   842         {
   843             if (topOp == INSTANCEOF) {
   844                 return F.at(pos).TypeTest(od1, od2);
   845             } else {
   846                 return F.at(pos).Binary(optag(topOp), od1, od2);
   847             }
   848         }
   849         /** If tree is a concatenation of string literals, replace it
   850          *  by a single literal representing the concatenated string.
   851          */
   852         protected StringBuilder foldStrings(JCTree tree) {
   853             if (!allowStringFolding)
   854                 return null;
   855             List<String> buf = List.nil();
   856             while (true) {
   857                 if (tree.hasTag(LITERAL)) {
   858                     JCLiteral lit = (JCLiteral) tree;
   859                     if (lit.typetag == TypeTag.CLASS) {
   860                         StringBuilder sbuf =
   861                             new StringBuilder((String)lit.value);
   862                         while (buf.nonEmpty()) {
   863                             sbuf.append(buf.head);
   864                             buf = buf.tail;
   865                         }
   866                         return sbuf;
   867                     }
   868                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   869                     JCBinary op = (JCBinary)tree;
   870                     if (op.rhs.hasTag(LITERAL)) {
   871                         JCLiteral lit = (JCLiteral) op.rhs;
   872                         if (lit.typetag == TypeTag.CLASS) {
   873                             buf = buf.prepend((String) lit.value);
   874                             tree = op.lhs;
   875                             continue;
   876                         }
   877                     }
   878                 }
   879                 return null;
   880             }
   881         }
   883         /** optimization: To save allocating a new operand/operator stack
   884          *  for every binary operation, we use supplys.
   885          */
   886         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   887         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   889         private JCExpression[] newOdStack() {
   890             if (odStackSupply.elems == odStackSupply.last)
   891                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   892             JCExpression[] odStack = odStackSupply.elems.head;
   893             odStackSupply.elems = odStackSupply.elems.tail;
   894             return odStack;
   895         }
   897         private Token[] newOpStack() {
   898             if (opStackSupply.elems == opStackSupply.last)
   899                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   900             Token[] opStack = opStackSupply.elems.head;
   901             opStackSupply.elems = opStackSupply.elems.tail;
   902             return opStack;
   903         }
   905     /**
   906      *  Expression3    = PrefixOp Expression3
   907      *                 | "(" Expr | TypeNoParams ")" Expression3
   908      *                 | Primary {Selector} {PostfixOp}
   909      *
   910      *  {@literal
   911      *  Primary        = "(" Expression ")"
   912      *                 | Literal
   913      *                 | [TypeArguments] THIS [Arguments]
   914      *                 | [TypeArguments] SUPER SuperSuffix
   915      *                 | NEW [TypeArguments] Creator
   916      *                 | "(" Arguments ")" "->" ( Expression | Block )
   917      *                 | Ident "->" ( Expression | Block )
   918      *                 | Ident { "." Ident }
   919      *                 | Expression3 MemberReferenceSuffix
   920      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   921      *                   | Arguments
   922      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   923      *                   ]
   924      *                 | BasicType BracketsOpt "." CLASS
   925      *  }
   926      *
   927      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   928      *  PostfixOp      = "++" | "--"
   929      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   930      *                 | BasicType
   931      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   932      *  Selector       = "." [TypeArguments] Ident [Arguments]
   933      *                 | "." THIS
   934      *                 | "." [TypeArguments] SUPER SuperSuffix
   935      *                 | "." NEW [TypeArguments] InnerCreator
   936      *                 | "[" Expression "]"
   937      *  TypeSelector   = "." Ident [TypeArguments]
   938      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   939      */
   940     protected JCExpression term3() {
   941         int pos = token.pos;
   942         JCExpression t;
   943         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   944         switch (token.kind) {
   945         case QUES:
   946             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   947                 mode = TYPE;
   948                 return typeArgument();
   949             } else
   950                 return illegal();
   951         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   952             if (typeArgs == null && (mode & EXPR) != 0) {
   953                 TokenKind tk = token.kind;
   954                 nextToken();
   955                 mode = EXPR;
   956                 if (tk == SUB &&
   957                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
   958                     token.radix() == 10) {
   959                     mode = EXPR;
   960                     t = literal(names.hyphen, pos);
   961                 } else {
   962                     t = term3();
   963                     return F.at(pos).Unary(unoptag(tk), t);
   964                 }
   965             } else return illegal();
   966             break;
   967         case LPAREN:
   968             if (typeArgs == null && (mode & EXPR) != 0) {
   969                 if (peekToken(MONKEYS_AT) ||
   970                         peekToken(FINAL) ||
   971                         peekToken(RPAREN) ||
   972                         peekToken(IDENTIFIER, COMMA) ||
   973                         peekToken(IDENTIFIER, RPAREN, ARROW)) {
   974                     //implicit n-ary lambda
   975                     t = lambdaExpressionOrStatement(true, peekToken(MONKEYS_AT) || peekToken(FINAL), pos);
   976                     break;
   977                 } else {
   978                     nextToken();
   979                     mode = EXPR | TYPE | NOPARAMS;
   980                     t = term3();
   981                     if ((mode & TYPE) != 0 && token.kind == LT) {
   982                         // Could be a cast to a parameterized type
   983                         JCTree.Tag op = JCTree.Tag.LT;
   984                         int pos1 = token.pos;
   985                         nextToken();
   986                         mode &= (EXPR | TYPE);
   987                         mode |= TYPEARG;
   988                         JCExpression t1 = term3();
   989                         if ((mode & TYPE) != 0 &&
   990                             (token.kind == COMMA || token.kind == GT)) {
   991                             mode = TYPE;
   992                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   993                             args.append(t1);
   994                             while (token.kind == COMMA) {
   995                                 nextToken();
   996                                 args.append(typeArgument());
   997                             }
   998                             accept(GT);
   999                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1000                             checkGenerics();
  1001                             mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type
  1002                             t = term3Rest(t, typeArgs);
  1003                             if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) {
  1004                                 //explicit lambda (w/ generic type)
  1005                                 mode = EXPR;
  1006                                 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  1007                                 if (token.kind == ELLIPSIS) {
  1008                                     mods.flags = Flags.VARARGS;
  1009                                     t = to(F.at(token.pos).TypeArray(t));
  1010                                     nextToken();
  1012                                 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
  1013                                 break;
  1015                         } else if ((mode & EXPR) != 0) {
  1016                             mode = EXPR;
  1017                             JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
  1018                             t = F.at(pos1).Binary(op, t, e);
  1019                             t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
  1020                         } else {
  1021                             accept(GT);
  1023                     } else if ((mode & TYPE) != 0 &&
  1024                             (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) {
  1025                         //explicit lambda (w/ non-generic type)
  1026                         mode = EXPR;
  1027                         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  1028                         if (token.kind == ELLIPSIS) {
  1029                             mods.flags = Flags.VARARGS;
  1030                             t = to(F.at(token.pos).TypeArray(t));
  1031                             nextToken();
  1033                         t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
  1034                         break;
  1035                     } else {
  1036                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
  1040                 accept(RPAREN);
  1041                 lastmode = mode;
  1042                 mode = EXPR;
  1043                 if ((lastmode & EXPR) == 0) {
  1044                     JCExpression t1 = term3();
  1045                     return F.at(pos).TypeCast(t, t1);
  1046                 } else if ((lastmode & TYPE) != 0) {
  1047                     switch (token.kind) {
  1048                     /*case PLUSPLUS: case SUBSUB: */
  1049                     case BANG: case TILDE:
  1050                     case LPAREN: case THIS: case SUPER:
  1051                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1052                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1053                     case TRUE: case FALSE: case NULL:
  1054                         case NEW: case IDENTIFIER: case ASSERT: case ENUM:
  1055                     case BYTE: case SHORT: case CHAR: case INT:
  1056                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1057                         JCExpression t1 = term3();
  1058                         return F.at(pos).TypeCast(t, t1);
  1061             } else {
  1062                 return illegal();
  1064             t = toP(F.at(pos).Parens(t));
  1065             break;
  1066         case THIS:
  1067             if ((mode & EXPR) != 0) {
  1068                 mode = EXPR;
  1069                 t = to(F.at(pos).Ident(names._this));
  1070                 nextToken();
  1071                 if (typeArgs == null)
  1072                     t = argumentsOpt(null, t);
  1073                 else
  1074                     t = arguments(typeArgs, t);
  1075                 typeArgs = null;
  1076             } else return illegal();
  1077             break;
  1078         case SUPER:
  1079             if ((mode & EXPR) != 0) {
  1080                 mode = EXPR;
  1081                 t = to(F.at(pos).Ident(names._super));
  1082                 t = superSuffix(typeArgs, t);
  1083                 typeArgs = null;
  1084             } else return illegal();
  1085             break;
  1086         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1087         case CHARLITERAL: case STRINGLITERAL:
  1088         case TRUE: case FALSE: case NULL:
  1089             if (typeArgs == null && (mode & EXPR) != 0) {
  1090                 mode = EXPR;
  1091                 t = literal(names.empty);
  1092             } else return illegal();
  1093             break;
  1094         case NEW:
  1095             if (typeArgs != null) return illegal();
  1096             if ((mode & EXPR) != 0) {
  1097                 mode = EXPR;
  1098                 nextToken();
  1099                 if (token.kind == LT) typeArgs = typeArguments(false);
  1100                 t = creator(pos, typeArgs);
  1101                 typeArgs = null;
  1102             } else return illegal();
  1103             break;
  1104         case IDENTIFIER: case ASSERT: case ENUM:
  1105             if (typeArgs != null) return illegal();
  1106             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1107                 t = lambdaExpressionOrStatement(false, false, pos);
  1108             } else {
  1109                 t = toP(F.at(token.pos).Ident(ident()));
  1110                 loop: while (true) {
  1111                     pos = token.pos;
  1112                     switch (token.kind) {
  1113                     case LBRACKET:
  1114                         nextToken();
  1115                         if (token.kind == RBRACKET) {
  1116                             nextToken();
  1117                             t = bracketsOpt(t);
  1118                             t = toP(F.at(pos).TypeArray(t));
  1119                             t = bracketsSuffix(t);
  1120                         } else {
  1121                             if ((mode & EXPR) != 0) {
  1122                                 mode = EXPR;
  1123                                 JCExpression t1 = term();
  1124                                 t = to(F.at(pos).Indexed(t, t1));
  1126                             accept(RBRACKET);
  1128                         break loop;
  1129                     case LPAREN:
  1130                         if ((mode & EXPR) != 0) {
  1131                             mode = EXPR;
  1132                             t = arguments(typeArgs, t);
  1133                             typeArgs = null;
  1135                         break loop;
  1136                     case DOT:
  1137                         nextToken();
  1138                         int oldmode = mode;
  1139                         mode &= ~NOPARAMS;
  1140                         typeArgs = typeArgumentsOpt(EXPR);
  1141                         mode = oldmode;
  1142                         if ((mode & EXPR) != 0) {
  1143                             switch (token.kind) {
  1144                             case CLASS:
  1145                                 if (typeArgs != null) return illegal();
  1146                                 mode = EXPR;
  1147                                 t = to(F.at(pos).Select(t, names._class));
  1148                                 nextToken();
  1149                                 break loop;
  1150                             case THIS:
  1151                                 if (typeArgs != null) return illegal();
  1152                                 mode = EXPR;
  1153                                 t = to(F.at(pos).Select(t, names._this));
  1154                                 nextToken();
  1155                                 break loop;
  1156                             case SUPER:
  1157                                 mode = EXPR;
  1158                                 t = to(F.at(pos).Select(t, names._super));
  1159                                 t = superSuffix(typeArgs, t);
  1160                                 typeArgs = null;
  1161                                 break loop;
  1162                             case NEW:
  1163                                 if (typeArgs != null) return illegal();
  1164                                 mode = EXPR;
  1165                                 int pos1 = token.pos;
  1166                                 nextToken();
  1167                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1168                                 t = innerCreator(pos1, typeArgs, t);
  1169                                 typeArgs = null;
  1170                                 break loop;
  1173                         // typeArgs saved for next loop iteration.
  1174                         t = toP(F.at(pos).Select(t, ident()));
  1175                         break;
  1176                     case LT:
  1177                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1178                             //this is an unbound method reference whose qualifier
  1179                             //is a generic type i.e. A<S>::m
  1180                             int pos1 = token.pos;
  1181                             accept(LT);
  1182                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1183                             args.append(typeArgument());
  1184                             while (token.kind == COMMA) {
  1185                                 nextToken();
  1186                                 args.append(typeArgument());
  1188                             accept(GT);
  1189                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1190                             checkGenerics();
  1191                             while (token.kind == DOT) {
  1192                                 nextToken();
  1193                                 mode = TYPE;
  1194                                 t = toP(F.at(token.pos).Select(t, ident()));
  1195                                 t = typeArgumentsOpt(t);
  1197                             t = bracketsOpt(t);
  1198                             if (token.kind != COLCOL) {
  1199                                 //method reference expected here
  1200                                 t = illegal();
  1202                             mode = EXPR;
  1203                             return term3Rest(t, typeArgs);
  1205                         break loop;
  1206                     default:
  1207                         break loop;
  1211             if (typeArgs != null) illegal();
  1212             t = typeArgumentsOpt(t);
  1213             break;
  1214         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1215         case DOUBLE: case BOOLEAN:
  1216             if (typeArgs != null) illegal();
  1217             t = bracketsSuffix(bracketsOpt(basicType()));
  1218             break;
  1219         case VOID:
  1220             if (typeArgs != null) illegal();
  1221             if ((mode & EXPR) != 0) {
  1222                 nextToken();
  1223                 if (token.kind == DOT) {
  1224                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
  1225                     t = bracketsSuffix(ti);
  1226                 } else {
  1227                     return illegal(pos);
  1229             } else {
  1230                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1231                 // a void type (like other primitive types) to the next phase.
  1232                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1233                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
  1234                 nextToken();
  1235                 return ti;
  1236                 //return illegal();
  1238             break;
  1239         default:
  1240             return illegal();
  1242         return term3Rest(t, typeArgs);
  1245     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1246         if (typeArgs != null) illegal();
  1247         while (true) {
  1248             int pos1 = token.pos;
  1249             if (token.kind == LBRACKET) {
  1250                 nextToken();
  1251                 if ((mode & TYPE) != 0) {
  1252                     int oldmode = mode;
  1253                     mode = TYPE;
  1254                     if (token.kind == RBRACKET) {
  1255                         nextToken();
  1256                         t = bracketsOpt(t);
  1257                         t = toP(F.at(pos1).TypeArray(t));
  1258                         if (token.kind == COLCOL) {
  1259                             mode = EXPR;
  1260                             continue;
  1262                         return t;
  1264                     mode = oldmode;
  1266                 if ((mode & EXPR) != 0) {
  1267                     mode = EXPR;
  1268                     JCExpression t1 = term();
  1269                     t = to(F.at(pos1).Indexed(t, t1));
  1271                 accept(RBRACKET);
  1272             } else if (token.kind == DOT) {
  1273                 nextToken();
  1274                 typeArgs = typeArgumentsOpt(EXPR);
  1275                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1276                     mode = EXPR;
  1277                     t = to(F.at(pos1).Select(t, names._super));
  1278                     nextToken();
  1279                     t = arguments(typeArgs, t);
  1280                     typeArgs = null;
  1281                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1282                     if (typeArgs != null) return illegal();
  1283                     mode = EXPR;
  1284                     int pos2 = token.pos;
  1285                     nextToken();
  1286                     if (token.kind == LT) typeArgs = typeArguments(false);
  1287                     t = innerCreator(pos2, typeArgs, t);
  1288                     typeArgs = null;
  1289                 } else {
  1290                     t = toP(F.at(pos1).Select(t, ident()));
  1291                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1292                     typeArgs = null;
  1294             } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
  1295                 mode = EXPR;
  1296                 if (typeArgs != null) return illegal();
  1297                 accept(COLCOL);
  1298                 t = memberReferenceSuffix(pos1, t);
  1299             } else {
  1300                 break;
  1303         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1304             mode = EXPR;
  1305             t = to(F.at(token.pos).Unary(
  1306                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1307             nextToken();
  1309         return toP(t);
  1312     /**
  1313      * If we see an identifier followed by a '&lt;' it could be an unbound
  1314      * method reference or a binary expression. To disambiguate, look for a
  1315      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1316      */
  1317     @SuppressWarnings("fallthrough")
  1318     boolean isUnboundMemberRef() {
  1319         int pos = 0, depth = 0;
  1320         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1321             switch (t.kind) {
  1322                 case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
  1323                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1324                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1325                 case DOUBLE: case BOOLEAN: case CHAR:
  1326                     break;
  1327                 case LT:
  1328                     depth++; break;
  1329                 case GTGTGT:
  1330                     depth--;
  1331                 case GTGT:
  1332                     depth--;
  1333                 case GT:
  1334                     depth--;
  1335                     if (depth == 0) {
  1336                         TokenKind nextKind = S.token(pos + 1).kind;
  1337                         return
  1338                             nextKind == TokenKind.DOT ||
  1339                             nextKind == TokenKind.LBRACKET ||
  1340                             nextKind == TokenKind.COLCOL;
  1342                     break;
  1343                 default:
  1344                     return false;
  1349     JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
  1350         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  1351         params.append(firstParam);
  1352         JCVariableDecl lastParam = firstParam;
  1353         while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  1354             nextToken();
  1355             params.append(lastParam = formalParameter());
  1357         accept(RPAREN);
  1358         return lambdaExpressionOrStatementRest(params.toList(), pos);
  1361     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1362         List<JCVariableDecl> params = explicitParams ?
  1363                 formalParameters() :
  1364                 implicitParameters(hasParens);
  1366         return lambdaExpressionOrStatementRest(params, pos);
  1369     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1370         checkLambda();
  1371         accept(ARROW);
  1373         return token.kind == LBRACE ?
  1374             lambdaStatement(args, pos, pos) :
  1375             lambdaExpression(args, pos);
  1378     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1379         JCBlock block = block(pos2, 0);
  1380         return toP(F.at(pos).Lambda(args, block));
  1383     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1384         JCTree expr = parseExpression();
  1385         return toP(F.at(pos).Lambda(args, expr));
  1388     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1389      */
  1390     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1391         nextToken();
  1392         if (token.kind == LPAREN || typeArgs != null) {
  1393             t = arguments(typeArgs, t);
  1394         } else if (token.kind == COLCOL) {
  1395             if (typeArgs != null) return illegal();
  1396             t = memberReferenceSuffix(t);
  1397         } else {
  1398             int pos = token.pos;
  1399             accept(DOT);
  1400             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1401             t = toP(F.at(pos).Select(t, ident()));
  1402             t = argumentsOpt(typeArgs, t);
  1404         return t;
  1407     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1408      */
  1409     JCPrimitiveTypeTree basicType() {
  1410         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1411         nextToken();
  1412         return t;
  1415     /** ArgumentsOpt = [ Arguments ]
  1416      */
  1417     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1418         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1419             mode = EXPR;
  1420             return arguments(typeArgs, t);
  1421         } else {
  1422             return t;
  1426     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1427      */
  1428     List<JCExpression> arguments() {
  1429         ListBuffer<JCExpression> args = lb();
  1430         if (token.kind == LPAREN) {
  1431             nextToken();
  1432             if (token.kind != RPAREN) {
  1433                 args.append(parseExpression());
  1434                 while (token.kind == COMMA) {
  1435                     nextToken();
  1436                     args.append(parseExpression());
  1439             accept(RPAREN);
  1440         } else {
  1441             syntaxError(token.pos, "expected", LPAREN);
  1443         return args.toList();
  1446     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1447         int pos = token.pos;
  1448         List<JCExpression> args = arguments();
  1449         return toP(F.at(pos).Apply(typeArgs, t, args));
  1452     /**  TypeArgumentsOpt = [ TypeArguments ]
  1453      */
  1454     JCExpression typeArgumentsOpt(JCExpression t) {
  1455         if (token.kind == LT &&
  1456             (mode & TYPE) != 0 &&
  1457             (mode & NOPARAMS) == 0) {
  1458             mode = TYPE;
  1459             checkGenerics();
  1460             return typeArguments(t, false);
  1461         } else {
  1462             return t;
  1465     List<JCExpression> typeArgumentsOpt() {
  1466         return typeArgumentsOpt(TYPE);
  1469     List<JCExpression> typeArgumentsOpt(int useMode) {
  1470         if (token.kind == LT) {
  1471             checkGenerics();
  1472             if ((mode & useMode) == 0 ||
  1473                 (mode & NOPARAMS) != 0) {
  1474                 illegal();
  1476             mode = useMode;
  1477             return typeArguments(false);
  1479         return null;
  1482     /**
  1483      *  {@literal
  1484      *  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1485      *  }
  1486      */
  1487     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1488         if (token.kind == LT) {
  1489             nextToken();
  1490             if (token.kind == GT && diamondAllowed) {
  1491                 checkDiamond();
  1492                 mode |= DIAMOND;
  1493                 nextToken();
  1494                 return List.nil();
  1495             } else {
  1496                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1497                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1498                 while (token.kind == COMMA) {
  1499                     nextToken();
  1500                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1502                 switch (token.kind) {
  1504                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1505                 case GTGTGT: case GTGT:
  1506                     token = S.split();
  1507                     break;
  1508                 case GT:
  1509                     nextToken();
  1510                     break;
  1511                 default:
  1512                     args.append(syntaxError(token.pos, "expected", GT));
  1513                     break;
  1515                 return args.toList();
  1517         } else {
  1518             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1522     /**
  1523      *  {@literal
  1524      *  TypeArgument = Type
  1525      *               | "?"
  1526      *               | "?" EXTENDS Type {"&" Type}
  1527      *               | "?" SUPER Type
  1528      *  }
  1529      */
  1530     JCExpression typeArgument() {
  1531         if (token.kind != QUES) return parseType();
  1532         int pos = token.pos;
  1533         nextToken();
  1534         if (token.kind == EXTENDS) {
  1535             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1536             nextToken();
  1537             JCExpression bound = parseType();
  1538             return F.at(pos).Wildcard(t, bound);
  1539         } else if (token.kind == SUPER) {
  1540             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1541             nextToken();
  1542             JCExpression bound = parseType();
  1543             return F.at(pos).Wildcard(t, bound);
  1544         } else if (token.kind == IDENTIFIER) {
  1545             //error recovery
  1546             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1547             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1548             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1549             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1550             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1551             return err;
  1552         } else {
  1553             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1554             return toP(F.at(pos).Wildcard(t, null));
  1558     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1559         int pos = token.pos;
  1560         List<JCExpression> args = typeArguments(diamondAllowed);
  1561         return toP(F.at(pos).TypeApply(t, args));
  1564     /** BracketsOpt = {"[" "]"}
  1565      */
  1566     private JCExpression bracketsOpt(JCExpression t) {
  1567         if (token.kind == LBRACKET) {
  1568             int pos = token.pos;
  1569             nextToken();
  1570             t = bracketsOptCont(t, pos);
  1571             F.at(pos);
  1573         return t;
  1576     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1577         accept(RBRACKET);
  1578         t = bracketsOpt(t);
  1579         return toP(F.at(pos).TypeArray(t));
  1582     /** BracketsSuffixExpr = "." CLASS
  1583      *  BracketsSuffixType =
  1584      */
  1585     JCExpression bracketsSuffix(JCExpression t) {
  1586         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1587             mode = EXPR;
  1588             int pos = token.pos;
  1589             nextToken();
  1590             accept(CLASS);
  1591             if (token.pos == endPosTable.errorEndPos) {
  1592                 // error recovery
  1593                 Name name = null;
  1594                 if (token.kind == IDENTIFIER) {
  1595                     name = token.name();
  1596                     nextToken();
  1597                 } else {
  1598                     name = names.error;
  1600                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1601             } else {
  1602                 t = toP(F.at(pos).Select(t, names._class));
  1604         } else if ((mode & TYPE) != 0) {
  1605             if (token.kind != COLCOL) {
  1606                 mode = TYPE;
  1608         } else if (token.kind != COLCOL) {
  1609             syntaxError(token.pos, "dot.class.expected");
  1611         return t;
  1614     /**
  1615      * MemberReferenceSuffix = "::" [TypeArguments] Ident
  1616      *                       | "::" [TypeArguments] "new"
  1617      */
  1618     JCExpression memberReferenceSuffix(JCExpression t) {
  1619         int pos1 = token.pos;
  1620         accept(COLCOL);
  1621         return memberReferenceSuffix(pos1, t);
  1624     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1625         checkMethodReferences();
  1626         mode = EXPR;
  1627         List<JCExpression> typeArgs = null;
  1628         if (token.kind == LT) {
  1629             typeArgs = typeArguments(false);
  1631         Name refName = null;
  1632         ReferenceMode refMode = null;
  1633         if (token.kind == NEW) {
  1634             refMode = ReferenceMode.NEW;
  1635             refName = names.init;
  1636             nextToken();
  1637         } else {
  1638             refMode = ReferenceMode.INVOKE;
  1639             refName = ident();
  1641         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  1644     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1645      */
  1646     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1647         switch (token.kind) {
  1648         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1649         case DOUBLE: case BOOLEAN:
  1650             if (typeArgs == null)
  1651                 return arrayCreatorRest(newpos, basicType());
  1652             break;
  1653         default:
  1655         JCExpression t = qualident();
  1656         int oldmode = mode;
  1657         mode = TYPE;
  1658         boolean diamondFound = false;
  1659         int lastTypeargsPos = -1;
  1660         if (token.kind == LT) {
  1661             checkGenerics();
  1662             lastTypeargsPos = token.pos;
  1663             t = typeArguments(t, true);
  1664             diamondFound = (mode & DIAMOND) != 0;
  1666         while (token.kind == DOT) {
  1667             if (diamondFound) {
  1668                 //cannot select after a diamond
  1669                 illegal();
  1671             int pos = token.pos;
  1672             nextToken();
  1673             t = toP(F.at(pos).Select(t, ident()));
  1674             if (token.kind == LT) {
  1675                 lastTypeargsPos = token.pos;
  1676                 checkGenerics();
  1677                 t = typeArguments(t, true);
  1678                 diamondFound = (mode & DIAMOND) != 0;
  1681         mode = oldmode;
  1682         if (token.kind == LBRACKET) {
  1683             JCExpression e = arrayCreatorRest(newpos, t);
  1684             if (diamondFound) {
  1685                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1686                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1688             else if (typeArgs != null) {
  1689                 int pos = newpos;
  1690                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1691                     // note: this should always happen but we should
  1692                     // not rely on this as the parser is continuously
  1693                     // modified to improve error recovery.
  1694                     pos = typeArgs.head.pos;
  1696                 setErrorEndPos(S.prevToken().endPos);
  1697                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1698                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1699                 return toP(err);
  1701             return e;
  1702         } else if (token.kind == LPAREN) {
  1703             return classCreatorRest(newpos, null, typeArgs, t);
  1704         } else {
  1705             setErrorEndPos(token.pos);
  1706             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1707             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1708             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1712     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1713      */
  1714     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1715         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1716         if (token.kind == LT) {
  1717             int oldmode = mode;
  1718             checkGenerics();
  1719             t = typeArguments(t, true);
  1720             mode = oldmode;
  1722         return classCreatorRest(newpos, encl, typeArgs, t);
  1725     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1726      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1727      */
  1728     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1729         accept(LBRACKET);
  1730         if (token.kind == RBRACKET) {
  1731             accept(RBRACKET);
  1732             elemtype = bracketsOpt(elemtype);
  1733             if (token.kind == LBRACE) {
  1734                 return arrayInitializer(newpos, elemtype);
  1735             } else {
  1736                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1737                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1739         } else {
  1740             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1741             dims.append(parseExpression());
  1742             accept(RBRACKET);
  1743             while (token.kind == LBRACKET) {
  1744                 int pos = token.pos;
  1745                 nextToken();
  1746                 if (token.kind == RBRACKET) {
  1747                     elemtype = bracketsOptCont(elemtype, pos);
  1748                 } else {
  1749                     dims.append(parseExpression());
  1750                     accept(RBRACKET);
  1753             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1757     /** ClassCreatorRest = Arguments [ClassBody]
  1758      */
  1759     JCNewClass classCreatorRest(int newpos,
  1760                                   JCExpression encl,
  1761                                   List<JCExpression> typeArgs,
  1762                                   JCExpression t)
  1764         List<JCExpression> args = arguments();
  1765         JCClassDecl body = null;
  1766         if (token.kind == LBRACE) {
  1767             int pos = token.pos;
  1768             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1769             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1770             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1772         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1775     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1776      */
  1777     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1778         accept(LBRACE);
  1779         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1780         if (token.kind == COMMA) {
  1781             nextToken();
  1782         } else if (token.kind != RBRACE) {
  1783             elems.append(variableInitializer());
  1784             while (token.kind == COMMA) {
  1785                 nextToken();
  1786                 if (token.kind == RBRACE) break;
  1787                 elems.append(variableInitializer());
  1790         accept(RBRACE);
  1791         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1794     /** VariableInitializer = ArrayInitializer | Expression
  1795      */
  1796     public JCExpression variableInitializer() {
  1797         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1800     /** ParExpression = "(" Expression ")"
  1801      */
  1802     JCExpression parExpression() {
  1803         int pos = token.pos;
  1804         accept(LPAREN);
  1805         JCExpression t = parseExpression();
  1806         accept(RPAREN);
  1807         return toP(F.at(pos).Parens(t));
  1810     /** Block = "{" BlockStatements "}"
  1811      */
  1812     JCBlock block(int pos, long flags) {
  1813         accept(LBRACE);
  1814         List<JCStatement> stats = blockStatements();
  1815         JCBlock t = F.at(pos).Block(flags, stats);
  1816         while (token.kind == CASE || token.kind == DEFAULT) {
  1817             syntaxError("orphaned", token.kind);
  1818             switchBlockStatementGroups();
  1820         // the Block node has a field "endpos" for first char of last token, which is
  1821         // usually but not necessarily the last char of the last token.
  1822         t.endpos = token.pos;
  1823         accept(RBRACE);
  1824         return toP(t);
  1827     public JCBlock block() {
  1828         return block(token.pos, 0);
  1831     /** BlockStatements = { BlockStatement }
  1832      *  BlockStatement  = LocalVariableDeclarationStatement
  1833      *                  | ClassOrInterfaceOrEnumDeclaration
  1834      *                  | [Ident ":"] Statement
  1835      *  LocalVariableDeclarationStatement
  1836      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1837      */
  1838     @SuppressWarnings("fallthrough")
  1839     List<JCStatement> blockStatements() {
  1840         //todo: skip to anchor on error(?)
  1841         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1842         while (true) {
  1843             List<JCStatement> stat = blockStatement();
  1844             if (stat.isEmpty()) {
  1845                 return stats.toList();
  1846             } else {
  1847                 if (token.pos <= endPosTable.errorEndPos) {
  1848                     skip(false, true, true, true);
  1850                 stats.addAll(stat);
  1855     /*
  1856      * This method parses a statement treating it as a block, relaxing the
  1857      * JLS restrictions, allows us to parse more faulty code, doing so
  1858      * enables us to provide better and accurate diagnostics to the user.
  1859      */
  1860     JCStatement parseStatementAsBlock() {
  1861         int pos = token.pos;
  1862         List<JCStatement> stats = blockStatement();
  1863         if (stats.isEmpty()) {
  1864             JCErroneous e = F.at(pos).Erroneous();
  1865             error(e, "illegal.start.of.stmt");
  1866             return F.at(pos).Exec(e);
  1867         } else {
  1868             JCStatement first = stats.head;
  1869             String error = null;
  1870             switch (first.getTag()) {
  1871             case CLASSDEF:
  1872                 error = "class.not.allowed";
  1873                 break;
  1874             case VARDEF:
  1875                 error = "variable.not.allowed";
  1876                 break;
  1878             if (error != null) {
  1879                 error(first, error);
  1880                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  1881                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  1883             return first;
  1887     @SuppressWarnings("fallthrough")
  1888     List<JCStatement> blockStatement() {
  1889         //todo: skip to anchor on error(?)
  1890         int pos = token.pos;
  1891         switch (token.kind) {
  1892         case RBRACE: case CASE: case DEFAULT: case EOF:
  1893             return List.nil();
  1894         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1895         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1896         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1897             return List.of(parseStatement());
  1898         case MONKEYS_AT:
  1899         case FINAL: {
  1900             Comment dc = token.comment(CommentStyle.JAVADOC);
  1901             JCModifiers mods = modifiersOpt();
  1902             if (token.kind == INTERFACE ||
  1903                 token.kind == CLASS ||
  1904                 allowEnums && token.kind == ENUM) {
  1905                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1906             } else {
  1907                 JCExpression t = parseType();
  1908                 ListBuffer<JCStatement> stats =
  1909                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1910                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1911                 storeEnd(stats.elems.last(), token.endPos);
  1912                 accept(SEMI);
  1913                 return stats.toList();
  1916         case ABSTRACT: case STRICTFP: {
  1917             Comment dc = token.comment(CommentStyle.JAVADOC);
  1918             JCModifiers mods = modifiersOpt();
  1919             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1921         case INTERFACE:
  1922         case CLASS:
  1923             Comment dc = token.comment(CommentStyle.JAVADOC);
  1924             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1925         case ENUM:
  1926         case ASSERT:
  1927             if (allowEnums && token.kind == ENUM) {
  1928                 error(token.pos, "local.enum");
  1929                 dc = token.comment(CommentStyle.JAVADOC);
  1930                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1931             } else if (allowAsserts && token.kind == ASSERT) {
  1932                 return List.of(parseStatement());
  1934             /* fall through to default */
  1935         default:
  1936             Token prevToken = token;
  1937             JCExpression t = term(EXPR | TYPE);
  1938             if (token.kind == COLON && t.hasTag(IDENT)) {
  1939                 nextToken();
  1940                 JCStatement stat = parseStatement();
  1941                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  1942             } else if ((lastmode & TYPE) != 0 &&
  1943                        (token.kind == IDENTIFIER ||
  1944                         token.kind == ASSERT ||
  1945                         token.kind == ENUM)) {
  1946                 pos = token.pos;
  1947                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1948                 F.at(pos);
  1949                 ListBuffer<JCStatement> stats =
  1950                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1951                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1952                 storeEnd(stats.elems.last(), token.endPos);
  1953                 accept(SEMI);
  1954                 return stats.toList();
  1955             } else {
  1956                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1957                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  1958                 accept(SEMI);
  1959                 return List.<JCStatement>of(expr);
  1964     /** Statement =
  1965      *       Block
  1966      *     | IF ParExpression Statement [ELSE Statement]
  1967      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1968      *     | FOR "(" FormalParameter : Expression ")" Statement
  1969      *     | WHILE ParExpression Statement
  1970      *     | DO Statement WHILE ParExpression ";"
  1971      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1972      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  1973      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1974      *     | SYNCHRONIZED ParExpression Block
  1975      *     | RETURN [Expression] ";"
  1976      *     | THROW Expression ";"
  1977      *     | BREAK [Ident] ";"
  1978      *     | CONTINUE [Ident] ";"
  1979      *     | ASSERT Expression [ ":" Expression ] ";"
  1980      *     | ";"
  1981      *     | ExpressionStatement
  1982      *     | Ident ":" Statement
  1983      */
  1984     @SuppressWarnings("fallthrough")
  1985     public JCStatement parseStatement() {
  1986         int pos = token.pos;
  1987         switch (token.kind) {
  1988         case LBRACE:
  1989             return block();
  1990         case IF: {
  1991             nextToken();
  1992             JCExpression cond = parExpression();
  1993             JCStatement thenpart = parseStatementAsBlock();
  1994             JCStatement elsepart = null;
  1995             if (token.kind == ELSE) {
  1996                 nextToken();
  1997                 elsepart = parseStatementAsBlock();
  1999             return F.at(pos).If(cond, thenpart, elsepart);
  2001         case FOR: {
  2002             nextToken();
  2003             accept(LPAREN);
  2004             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  2005             if (inits.length() == 1 &&
  2006                 inits.head.hasTag(VARDEF) &&
  2007                 ((JCVariableDecl) inits.head).init == null &&
  2008                 token.kind == COLON) {
  2009                 checkForeach();
  2010                 JCVariableDecl var = (JCVariableDecl)inits.head;
  2011                 accept(COLON);
  2012                 JCExpression expr = parseExpression();
  2013                 accept(RPAREN);
  2014                 JCStatement body = parseStatementAsBlock();
  2015                 return F.at(pos).ForeachLoop(var, expr, body);
  2016             } else {
  2017                 accept(SEMI);
  2018                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  2019                 accept(SEMI);
  2020                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  2021                 accept(RPAREN);
  2022                 JCStatement body = parseStatementAsBlock();
  2023                 return F.at(pos).ForLoop(inits, cond, steps, body);
  2026         case WHILE: {
  2027             nextToken();
  2028             JCExpression cond = parExpression();
  2029             JCStatement body = parseStatementAsBlock();
  2030             return F.at(pos).WhileLoop(cond, body);
  2032         case DO: {
  2033             nextToken();
  2034             JCStatement body = parseStatementAsBlock();
  2035             accept(WHILE);
  2036             JCExpression cond = parExpression();
  2037             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2038             accept(SEMI);
  2039             return t;
  2041         case TRY: {
  2042             nextToken();
  2043             List<JCTree> resources = List.<JCTree>nil();
  2044             if (token.kind == LPAREN) {
  2045                 checkTryWithResources();
  2046                 nextToken();
  2047                 resources = resources();
  2048                 accept(RPAREN);
  2050             JCBlock body = block();
  2051             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2052             JCBlock finalizer = null;
  2053             if (token.kind == CATCH || token.kind == FINALLY) {
  2054                 while (token.kind == CATCH) catchers.append(catchClause());
  2055                 if (token.kind == FINALLY) {
  2056                     nextToken();
  2057                     finalizer = block();
  2059             } else {
  2060                 if (allowTWR) {
  2061                     if (resources.isEmpty())
  2062                         error(pos, "try.without.catch.finally.or.resource.decls");
  2063                 } else
  2064                     error(pos, "try.without.catch.or.finally");
  2066             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2068         case SWITCH: {
  2069             nextToken();
  2070             JCExpression selector = parExpression();
  2071             accept(LBRACE);
  2072             List<JCCase> cases = switchBlockStatementGroups();
  2073             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2074             accept(RBRACE);
  2075             return t;
  2077         case SYNCHRONIZED: {
  2078             nextToken();
  2079             JCExpression lock = parExpression();
  2080             JCBlock body = block();
  2081             return F.at(pos).Synchronized(lock, body);
  2083         case RETURN: {
  2084             nextToken();
  2085             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2086             JCReturn t = to(F.at(pos).Return(result));
  2087             accept(SEMI);
  2088             return t;
  2090         case THROW: {
  2091             nextToken();
  2092             JCExpression exc = parseExpression();
  2093             JCThrow t = to(F.at(pos).Throw(exc));
  2094             accept(SEMI);
  2095             return t;
  2097         case BREAK: {
  2098             nextToken();
  2099             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2100             JCBreak t = to(F.at(pos).Break(label));
  2101             accept(SEMI);
  2102             return t;
  2104         case CONTINUE: {
  2105             nextToken();
  2106             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2107             JCContinue t =  to(F.at(pos).Continue(label));
  2108             accept(SEMI);
  2109             return t;
  2111         case SEMI:
  2112             nextToken();
  2113             return toP(F.at(pos).Skip());
  2114         case ELSE:
  2115             int elsePos = token.pos;
  2116             nextToken();
  2117             return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, "else.without.if");
  2118         case FINALLY:
  2119             int finallyPos = token.pos;
  2120             nextToken();
  2121             return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, "finally.without.try");
  2122         case CATCH:
  2123             return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, "catch.without.try");
  2124         case ASSERT: {
  2125             if (allowAsserts && token.kind == ASSERT) {
  2126                 nextToken();
  2127                 JCExpression assertion = parseExpression();
  2128                 JCExpression message = null;
  2129                 if (token.kind == COLON) {
  2130                     nextToken();
  2131                     message = parseExpression();
  2133                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2134                 accept(SEMI);
  2135                 return t;
  2137             /* else fall through to default case */
  2139         case ENUM:
  2140         default:
  2141             Token prevToken = token;
  2142             JCExpression expr = parseExpression();
  2143             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2144                 nextToken();
  2145                 JCStatement stat = parseStatement();
  2146                 return F.at(pos).Labelled(prevToken.name(), stat);
  2147             } else {
  2148                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2149                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2150                 accept(SEMI);
  2151                 return stat;
  2156     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
  2157         int errPos = S.errPos();
  2158         JCTree stm = action.doRecover(this);
  2159         S.errPos(errPos);
  2160         return toP(F.Exec(syntaxError(startPos, List.<JCTree>of(stm), key)));
  2163     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2164      */
  2165     protected JCCatch catchClause() {
  2166         int pos = token.pos;
  2167         accept(CATCH);
  2168         accept(LPAREN);
  2169         JCModifiers mods = optFinal(Flags.PARAMETER);
  2170         List<JCExpression> catchTypes = catchTypes();
  2171         JCExpression paramType = catchTypes.size() > 1 ?
  2172                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2173                 catchTypes.head;
  2174         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2175         accept(RPAREN);
  2176         JCBlock body = block();
  2177         return F.at(pos).Catch(formal, body);
  2180     List<JCExpression> catchTypes() {
  2181         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2182         catchTypes.add(parseType());
  2183         while (token.kind == BAR) {
  2184             checkMulticatch();
  2185             nextToken();
  2186             catchTypes.add(qualident());
  2188         return catchTypes.toList();
  2191     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2192      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2193      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2194      */
  2195     List<JCCase> switchBlockStatementGroups() {
  2196         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2197         while (true) {
  2198             int pos = token.pos;
  2199             switch (token.kind) {
  2200             case CASE:
  2201             case DEFAULT:
  2202                 cases.append(switchBlockStatementGroup());
  2203                 break;
  2204             case RBRACE: case EOF:
  2205                 return cases.toList();
  2206             default:
  2207                 nextToken(); // to ensure progress
  2208                 syntaxError(pos, "expected3",
  2209                     CASE, DEFAULT, RBRACE);
  2214     protected JCCase switchBlockStatementGroup() {
  2215         int pos = token.pos;
  2216         List<JCStatement> stats;
  2217         JCCase c;
  2218         switch (token.kind) {
  2219         case CASE:
  2220             nextToken();
  2221             JCExpression pat = parseExpression();
  2222             accept(COLON);
  2223             stats = blockStatements();
  2224             c = F.at(pos).Case(pat, stats);
  2225             if (stats.isEmpty())
  2226                 storeEnd(c, S.prevToken().endPos);
  2227             return c;
  2228         case DEFAULT:
  2229             nextToken();
  2230             accept(COLON);
  2231             stats = blockStatements();
  2232             c = F.at(pos).Case(null, stats);
  2233             if (stats.isEmpty())
  2234                 storeEnd(c, S.prevToken().endPos);
  2235             return c;
  2237         throw new AssertionError("should not reach here");
  2240     /** MoreStatementExpressions = { COMMA StatementExpression }
  2241      */
  2242     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2243                                                                     JCExpression first,
  2244                                                                     T stats) {
  2245         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2246         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2247         while (token.kind == COMMA) {
  2248             nextToken();
  2249             pos = token.pos;
  2250             JCExpression t = parseExpression();
  2251             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2252             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2254         return stats;
  2257     /** ForInit = StatementExpression MoreStatementExpressions
  2258      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2259      */
  2260     List<JCStatement> forInit() {
  2261         ListBuffer<JCStatement> stats = lb();
  2262         int pos = token.pos;
  2263         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2264             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2265         } else {
  2266             JCExpression t = term(EXPR | TYPE);
  2267             if ((lastmode & TYPE) != 0 &&
  2268                 (token.kind == IDENTIFIER || token.kind == ASSERT ||
  2269                  token.kind == ENUM)) {
  2270                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2271             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2272                 error(pos, "bad.initializer", "for-loop");
  2273                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2274             } else {
  2275                 return moreStatementExpressions(pos, t, stats).toList();
  2280     /** ForUpdate = StatementExpression MoreStatementExpressions
  2281      */
  2282     List<JCExpressionStatement> forUpdate() {
  2283         return moreStatementExpressions(token.pos,
  2284                                         parseExpression(),
  2285                                         new ListBuffer<JCExpressionStatement>()).toList();
  2288     /** AnnotationsOpt = { '@' Annotation }
  2289      */
  2290     List<JCAnnotation> annotationsOpt() {
  2291         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2292         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2293         while (token.kind == MONKEYS_AT) {
  2294             int pos = token.pos;
  2295             nextToken();
  2296             buf.append(annotation(pos));
  2298         return buf.toList();
  2301     /** ModifiersOpt = { Modifier }
  2302      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2303      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2304      *           | "@" Annotation
  2305      */
  2306     JCModifiers modifiersOpt() {
  2307         return modifiersOpt(null);
  2309     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2310         long flags;
  2311         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2312         int pos;
  2313         if (partial == null) {
  2314             flags = 0;
  2315             pos = token.pos;
  2316         } else {
  2317             flags = partial.flags;
  2318             annotations.appendList(partial.annotations);
  2319             pos = partial.pos;
  2321         if (token.deprecatedFlag()) {
  2322             flags |= Flags.DEPRECATED;
  2324         int lastPos = Position.NOPOS;
  2325     loop:
  2326         while (true) {
  2327             long flag;
  2328             switch (token.kind) {
  2329             case PRIVATE     : flag = Flags.PRIVATE; break;
  2330             case PROTECTED   : flag = Flags.PROTECTED; break;
  2331             case PUBLIC      : flag = Flags.PUBLIC; break;
  2332             case STATIC      : flag = Flags.STATIC; break;
  2333             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2334             case FINAL       : flag = Flags.FINAL; break;
  2335             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2336             case NATIVE      : flag = Flags.NATIVE; break;
  2337             case VOLATILE    : flag = Flags.VOLATILE; break;
  2338             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2339             case STRICTFP    : flag = Flags.STRICTFP; break;
  2340             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2341             case DEFAULT     : checkDefaultMethods(); flag = Flags.DEFAULT; break;
  2342             case ERROR       : flag = 0; nextToken(); break;
  2343             default: break loop;
  2345             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2346             lastPos = token.pos;
  2347             nextToken();
  2348             if (flag == Flags.ANNOTATION) {
  2349                 checkAnnotations();
  2350                 if (token.kind != INTERFACE) {
  2351                     JCAnnotation ann = annotation(lastPos);
  2352                     // if first modifier is an annotation, set pos to annotation's.
  2353                     if (flags == 0 && annotations.isEmpty())
  2354                         pos = ann.pos;
  2355                     annotations.append(ann);
  2356                     lastPos = ann.pos;
  2357                     flag = 0;
  2360             flags |= flag;
  2362         switch (token.kind) {
  2363         case ENUM: flags |= Flags.ENUM; break;
  2364         case INTERFACE: flags |= Flags.INTERFACE; break;
  2365         default: break;
  2368         /* A modifiers tree with no modifier tokens or annotations
  2369          * has no text position. */
  2370         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2371             pos = Position.NOPOS;
  2373         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2374         if (pos != Position.NOPOS)
  2375             storeEnd(mods, S.prevToken().endPos);
  2376         return mods;
  2379     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2380      * @param pos position of "@" token
  2381      */
  2382     JCAnnotation annotation(int pos) {
  2383         // accept(AT); // AT consumed by caller
  2384         checkAnnotations();
  2385         JCTree ident = qualident();
  2386         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2387         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2388         storeEnd(ann, S.prevToken().endPos);
  2389         return ann;
  2392     List<JCExpression> annotationFieldValuesOpt() {
  2393         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2396     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2397     List<JCExpression> annotationFieldValues() {
  2398         accept(LPAREN);
  2399         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2400         if (token.kind != RPAREN) {
  2401             buf.append(annotationFieldValue());
  2402             while (token.kind == COMMA) {
  2403                 nextToken();
  2404                 buf.append(annotationFieldValue());
  2407         accept(RPAREN);
  2408         return buf.toList();
  2411     /** AnnotationFieldValue    = AnnotationValue
  2412      *                          | Identifier "=" AnnotationValue
  2413      */
  2414     JCExpression annotationFieldValue() {
  2415         if (token.kind == IDENTIFIER) {
  2416             mode = EXPR;
  2417             JCExpression t1 = term1();
  2418             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2419                 int pos = token.pos;
  2420                 accept(EQ);
  2421                 JCExpression v = annotationValue();
  2422                 return toP(F.at(pos).Assign(t1, v));
  2423             } else {
  2424                 return t1;
  2427         return annotationValue();
  2430     /* AnnotationValue          = ConditionalExpression
  2431      *                          | Annotation
  2432      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2433      */
  2434     JCExpression annotationValue() {
  2435         int pos;
  2436         switch (token.kind) {
  2437         case MONKEYS_AT:
  2438             pos = token.pos;
  2439             nextToken();
  2440             return annotation(pos);
  2441         case LBRACE:
  2442             pos = token.pos;
  2443             accept(LBRACE);
  2444             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2445             if (token.kind != RBRACE) {
  2446                 buf.append(annotationValue());
  2447                 while (token.kind == COMMA) {
  2448                     nextToken();
  2449                     if (token.kind == RBRACE) break;
  2450                     buf.append(annotationValue());
  2453             accept(RBRACE);
  2454             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2455         default:
  2456             mode = EXPR;
  2457             return term1();
  2461     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2462      */
  2463     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2464                                                                          JCExpression type,
  2465                                                                          T vdefs)
  2467         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2470     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2471      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2473      *  @param reqInit  Is an initializer always required?
  2474      *  @param dc       The documentation comment for the variable declarations, or null.
  2475      */
  2476     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2477                                                                      JCModifiers mods,
  2478                                                                      JCExpression type,
  2479                                                                      Name name,
  2480                                                                      boolean reqInit,
  2481                                                                      Comment dc,
  2482                                                                      T vdefs)
  2484         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2485         while (token.kind == COMMA) {
  2486             // All but last of multiple declarators subsume a comma
  2487             storeEnd((JCTree)vdefs.elems.last(), token.endPos);
  2488             nextToken();
  2489             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2491         return vdefs;
  2494     /** VariableDeclarator = Ident VariableDeclaratorRest
  2495      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2496      */
  2497     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2498         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2501     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2502      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2504      *  @param reqInit  Is an initializer always required?
  2505      *  @param dc       The documentation comment for the variable declarations, or null.
  2506      */
  2507     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2508                                   boolean reqInit, Comment dc) {
  2509         type = bracketsOpt(type);
  2510         JCExpression init = null;
  2511         if (token.kind == EQ) {
  2512             nextToken();
  2513             init = variableInitializer();
  2515         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2516         JCVariableDecl result =
  2517             toP(F.at(pos).VarDef(mods, name, type, init));
  2518         attach(result, dc);
  2519         return result;
  2522     /** VariableDeclaratorId = Ident BracketsOpt
  2523      */
  2524     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2525         int pos = token.pos;
  2526         Name name = ident();
  2527         if ((mods.flags & Flags.VARARGS) != 0 &&
  2528                 token.kind == LBRACKET) {
  2529             log.error(token.pos, "varargs.and.old.array.syntax");
  2531         type = bracketsOpt(type);
  2532         return toP(F.at(pos).VarDef(mods, name, type, null));
  2535     /** Resources = Resource { ";" Resources }
  2536      */
  2537     List<JCTree> resources() {
  2538         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2539         defs.append(resource());
  2540         while (token.kind == SEMI) {
  2541             // All but last of multiple declarators must subsume a semicolon
  2542             storeEnd(defs.elems.last(), token.endPos);
  2543             int semiColonPos = token.pos;
  2544             nextToken();
  2545             if (token.kind == RPAREN) { // Optional trailing semicolon
  2546                                        // after last resource
  2547                 break;
  2549             defs.append(resource());
  2551         return defs.toList();
  2554     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2555      */
  2556     protected JCTree resource() {
  2557         JCModifiers optFinal = optFinal(Flags.FINAL);
  2558         JCExpression type = parseType();
  2559         int pos = token.pos;
  2560         Name ident = ident();
  2561         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2564     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2565      */
  2566     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2567         Token firstToken = token;
  2568         JCExpression pid = null;
  2569         JCModifiers mods = null;
  2570         boolean consumedToplevelDoc = false;
  2571         boolean seenImport = false;
  2572         boolean seenPackage = false;
  2573         List<JCAnnotation> packageAnnotations = List.nil();
  2574         if (token.kind == MONKEYS_AT)
  2575             mods = modifiersOpt();
  2577         if (token.kind == PACKAGE) {
  2578             seenPackage = true;
  2579             if (mods != null) {
  2580                 checkNoMods(mods.flags);
  2581                 packageAnnotations = mods.annotations;
  2582                 mods = null;
  2584             nextToken();
  2585             pid = qualident();
  2586             accept(SEMI);
  2588         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2589         boolean checkForImports = true;
  2590         boolean firstTypeDecl = true;
  2591         while (token.kind != EOF) {
  2592             if (token.pos <= endPosTable.errorEndPos) {
  2593                 // error recovery
  2594                 skip(checkForImports, false, false, false);
  2595                 if (token.kind == EOF)
  2596                     break;
  2598             if (checkForImports && mods == null && token.kind == IMPORT) {
  2599                 seenImport = true;
  2600                 defs.append(importDeclaration());
  2601             } else {
  2602                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  2603                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2604                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2605                     consumedToplevelDoc = true;
  2607                 JCTree def = typeDeclaration(mods, docComment);
  2608                 if (def instanceof JCExpressionStatement)
  2609                     def = ((JCExpressionStatement)def).expr;
  2610                 defs.append(def);
  2611                 if (def instanceof JCClassDecl)
  2612                     checkForImports = false;
  2613                 mods = null;
  2614                 firstTypeDecl = false;
  2617         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2618         if (!consumedToplevelDoc)
  2619             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2620         if (defs.elems.isEmpty())
  2621             storeEnd(toplevel, S.prevToken().endPos);
  2622         if (keepDocComments)
  2623             toplevel.docComments = docComments;
  2624         if (keepLineMap)
  2625             toplevel.lineMap = S.getLineMap();
  2626         toplevel.endPositions = this.endPosTable;
  2627         return toplevel;
  2630     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2631      */
  2632     JCTree importDeclaration() {
  2633         int pos = token.pos;
  2634         nextToken();
  2635         boolean importStatic = false;
  2636         if (token.kind == STATIC) {
  2637             checkStaticImports();
  2638             importStatic = true;
  2639             nextToken();
  2641         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2642         do {
  2643             int pos1 = token.pos;
  2644             accept(DOT);
  2645             if (token.kind == STAR) {
  2646                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2647                 nextToken();
  2648                 break;
  2649             } else {
  2650                 pid = toP(F.at(pos1).Select(pid, ident()));
  2652         } while (token.kind == DOT);
  2653         accept(SEMI);
  2654         return toP(F.at(pos).Import(pid, importStatic));
  2657     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2658      *                  | ";"
  2659      */
  2660     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  2661         int pos = token.pos;
  2662         if (mods == null && token.kind == SEMI) {
  2663             nextToken();
  2664             return toP(F.at(pos).Skip());
  2665         } else {
  2666             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2670     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2671      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2672      *  @param mods     Any modifiers starting the class or interface declaration
  2673      *  @param dc       The documentation comment for the class, or null.
  2674      */
  2675     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  2676         if (token.kind == CLASS) {
  2677             return classDeclaration(mods, dc);
  2678         } else if (token.kind == INTERFACE) {
  2679             return interfaceDeclaration(mods, dc);
  2680         } else if (allowEnums) {
  2681             if (token.kind == ENUM) {
  2682                 return enumDeclaration(mods, dc);
  2683             } else {
  2684                 int pos = token.pos;
  2685                 List<JCTree> errs;
  2686                 if (token.kind == IDENTIFIER) {
  2687                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2688                     setErrorEndPos(token.pos);
  2689                 } else {
  2690                     errs = List.<JCTree>of(mods);
  2692                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2693                                               CLASS, INTERFACE, ENUM)));
  2695         } else {
  2696             if (token.kind == ENUM) {
  2697                 error(token.pos, "enums.not.supported.in.source", source.name);
  2698                 allowEnums = true;
  2699                 return enumDeclaration(mods, dc);
  2701             int pos = token.pos;
  2702             List<JCTree> errs;
  2703             if (token.kind == IDENTIFIER) {
  2704                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2705                 setErrorEndPos(token.pos);
  2706             } else {
  2707                 errs = List.<JCTree>of(mods);
  2709             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2710                                           CLASS, INTERFACE)));
  2714     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2715      *                     [IMPLEMENTS TypeList] ClassBody
  2716      *  @param mods    The modifiers starting the class declaration
  2717      *  @param dc       The documentation comment for the class, or null.
  2718      */
  2719     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  2720         int pos = token.pos;
  2721         accept(CLASS);
  2722         Name name = ident();
  2724         List<JCTypeParameter> typarams = typeParametersOpt();
  2726         JCExpression extending = null;
  2727         if (token.kind == EXTENDS) {
  2728             nextToken();
  2729             extending = parseType();
  2731         List<JCExpression> implementing = List.nil();
  2732         if (token.kind == IMPLEMENTS) {
  2733             nextToken();
  2734             implementing = typeList();
  2736         List<JCTree> defs = classOrInterfaceBody(name, false);
  2737         JCClassDecl result = toP(F.at(pos).ClassDef(
  2738             mods, name, typarams, extending, implementing, defs));
  2739         attach(result, dc);
  2740         return result;
  2743     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2744      *                         [EXTENDS TypeList] InterfaceBody
  2745      *  @param mods    The modifiers starting the interface declaration
  2746      *  @param dc       The documentation comment for the interface, or null.
  2747      */
  2748     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  2749         int pos = token.pos;
  2750         accept(INTERFACE);
  2751         Name name = ident();
  2753         List<JCTypeParameter> typarams = typeParametersOpt();
  2755         List<JCExpression> extending = List.nil();
  2756         if (token.kind == EXTENDS) {
  2757             nextToken();
  2758             extending = typeList();
  2760         List<JCTree> defs = classOrInterfaceBody(name, true);
  2761         JCClassDecl result = toP(F.at(pos).ClassDef(
  2762             mods, name, typarams, null, extending, defs));
  2763         attach(result, dc);
  2764         return result;
  2767     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2768      *  @param mods    The modifiers starting the enum declaration
  2769      *  @param dc       The documentation comment for the enum, or null.
  2770      */
  2771     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  2772         int pos = token.pos;
  2773         accept(ENUM);
  2774         Name name = ident();
  2776         List<JCExpression> implementing = List.nil();
  2777         if (token.kind == IMPLEMENTS) {
  2778             nextToken();
  2779             implementing = typeList();
  2782         List<JCTree> defs = enumBody(name);
  2783         mods.flags |= Flags.ENUM;
  2784         JCClassDecl result = toP(F.at(pos).
  2785             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2786                 null, implementing, defs));
  2787         attach(result, dc);
  2788         return result;
  2791     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2792      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2793      */
  2794     List<JCTree> enumBody(Name enumName) {
  2795         accept(LBRACE);
  2796         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2797         if (token.kind == COMMA) {
  2798             nextToken();
  2799         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2800             defs.append(enumeratorDeclaration(enumName));
  2801             while (token.kind == COMMA) {
  2802                 nextToken();
  2803                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2804                 defs.append(enumeratorDeclaration(enumName));
  2806             if (token.kind != SEMI && token.kind != RBRACE) {
  2807                 defs.append(syntaxError(token.pos, "expected3",
  2808                                 COMMA, RBRACE, SEMI));
  2809                 nextToken();
  2812         if (token.kind == SEMI) {
  2813             nextToken();
  2814             while (token.kind != RBRACE && token.kind != EOF) {
  2815                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2816                                                                 false));
  2817                 if (token.pos <= endPosTable.errorEndPos) {
  2818                     // error recovery
  2819                    skip(false, true, true, false);
  2823         accept(RBRACE);
  2824         return defs.toList();
  2827     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2828      */
  2829     JCTree enumeratorDeclaration(Name enumName) {
  2830         Comment dc = token.comment(CommentStyle.JAVADOC);
  2831         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2832         if (token.deprecatedFlag()) {
  2833             flags |= Flags.DEPRECATED;
  2835         int pos = token.pos;
  2836         List<JCAnnotation> annotations = annotationsOpt();
  2837         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2838         List<JCExpression> typeArgs = typeArgumentsOpt();
  2839         int identPos = token.pos;
  2840         Name name = ident();
  2841         int createPos = token.pos;
  2842         List<JCExpression> args = (token.kind == LPAREN)
  2843             ? arguments() : List.<JCExpression>nil();
  2844         JCClassDecl body = null;
  2845         if (token.kind == LBRACE) {
  2846             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2847             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2848             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2850         if (args.isEmpty() && body == null)
  2851             createPos = identPos;
  2852         JCIdent ident = F.at(identPos).Ident(enumName);
  2853         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2854         if (createPos != identPos)
  2855             storeEnd(create, S.prevToken().endPos);
  2856         ident = F.at(identPos).Ident(enumName);
  2857         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2858         attach(result, dc);
  2859         return result;
  2862     /** TypeList = Type {"," Type}
  2863      */
  2864     List<JCExpression> typeList() {
  2865         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2866         ts.append(parseType());
  2867         while (token.kind == COMMA) {
  2868             nextToken();
  2869             ts.append(parseType());
  2871         return ts.toList();
  2874     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2875      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2876      */
  2877     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2878         accept(LBRACE);
  2879         if (token.pos <= endPosTable.errorEndPos) {
  2880             // error recovery
  2881             skip(false, true, false, false);
  2882             if (token.kind == LBRACE)
  2883                 nextToken();
  2885         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2886         while (token.kind != RBRACE && token.kind != EOF) {
  2887             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2888             if (token.pos <= endPosTable.errorEndPos) {
  2889                // error recovery
  2890                skip(false, true, true, false);
  2893         accept(RBRACE);
  2894         return defs.toList();
  2897     /** ClassBodyDeclaration =
  2898      *      ";"
  2899      *    | [STATIC] Block
  2900      *    | ModifiersOpt
  2901      *      ( Type Ident
  2902      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2903      *      | VOID Ident MethodDeclaratorRest
  2904      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2905      *      | Ident ConstructorDeclaratorRest
  2906      *      | TypeParameters Ident ConstructorDeclaratorRest
  2907      *      | ClassOrInterfaceOrEnumDeclaration
  2908      *      )
  2909      *  InterfaceBodyDeclaration =
  2910      *      ";"
  2911      *    | ModifiersOpt Type Ident
  2912      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2913      */
  2914     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2915         if (token.kind == SEMI) {
  2916             nextToken();
  2917             return List.<JCTree>nil();
  2918         } else {
  2919             Comment dc = token.comment(CommentStyle.JAVADOC);
  2920             int pos = token.pos;
  2921             JCModifiers mods = modifiersOpt();
  2922             if (token.kind == CLASS ||
  2923                 token.kind == INTERFACE ||
  2924                 allowEnums && token.kind == ENUM) {
  2925                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2926             } else if (token.kind == LBRACE && !isInterface &&
  2927                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2928                        mods.annotations.isEmpty()) {
  2929                 return List.<JCTree>of(block(pos, mods.flags));
  2930             } else {
  2931                 pos = token.pos;
  2932                 List<JCTypeParameter> typarams = typeParametersOpt();
  2933                 // if there are type parameters but no modifiers, save the start
  2934                 // position of the method in the modifiers.
  2935                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  2936                     mods.pos = pos;
  2937                     storeEnd(mods, pos);
  2939                 Token tk = token;
  2940                 pos = token.pos;
  2941                 JCExpression type;
  2942                 boolean isVoid = token.kind == VOID;
  2943                 if (isVoid) {
  2944                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
  2945                     nextToken();
  2946                 } else {
  2947                     type = parseType();
  2949                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  2950                     if (isInterface || tk.name() != className)
  2951                         error(pos, "invalid.meth.decl.ret.type.req");
  2952                     return List.of(methodDeclaratorRest(
  2953                         pos, mods, null, names.init, typarams,
  2954                         isInterface, true, dc));
  2955                 } else {
  2956                     pos = token.pos;
  2957                     Name name = ident();
  2958                     if (token.kind == LPAREN) {
  2959                         return List.of(methodDeclaratorRest(
  2960                             pos, mods, type, name, typarams,
  2961                             isInterface, isVoid, dc));
  2962                     } else if (!isVoid && typarams.isEmpty()) {
  2963                         List<JCTree> defs =
  2964                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2965                                                     new ListBuffer<JCTree>()).toList();
  2966                         storeEnd(defs.last(), token.endPos);
  2967                         accept(SEMI);
  2968                         return defs;
  2969                     } else {
  2970                         pos = token.pos;
  2971                         List<JCTree> err = isVoid
  2972                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2973                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2974                             : null;
  2975                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  2982     /** MethodDeclaratorRest =
  2983      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2984      *  VoidMethodDeclaratorRest =
  2985      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2986      *  InterfaceMethodDeclaratorRest =
  2987      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2988      *  VoidInterfaceMethodDeclaratorRest =
  2989      *      FormalParameters [THROWS TypeList] ";"
  2990      *  ConstructorDeclaratorRest =
  2991      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2992      */
  2993     protected JCTree methodDeclaratorRest(int pos,
  2994                               JCModifiers mods,
  2995                               JCExpression type,
  2996                               Name name,
  2997                               List<JCTypeParameter> typarams,
  2998                               boolean isInterface, boolean isVoid,
  2999                               Comment dc) {
  3000         List<JCVariableDecl> params = formalParameters();
  3001         if (!isVoid) type = bracketsOpt(type);
  3002         List<JCExpression> thrown = List.nil();
  3003         if (token.kind == THROWS) {
  3004             nextToken();
  3005             thrown = qualidentList();
  3007         JCBlock body = null;
  3008         JCExpression defaultValue;
  3009         if (token.kind == LBRACE) {
  3010             body = block();
  3011             defaultValue = null;
  3012         } else {
  3013             if (token.kind == DEFAULT) {
  3014                 accept(DEFAULT);
  3015                 defaultValue = annotationValue();
  3016             } else {
  3017                 defaultValue = null;
  3019             accept(SEMI);
  3020             if (token.pos <= endPosTable.errorEndPos) {
  3021                 // error recovery
  3022                 skip(false, true, false, false);
  3023                 if (token.kind == LBRACE) {
  3024                     body = block();
  3029         JCMethodDecl result =
  3030             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  3031                                     params, thrown,
  3032                                     body, defaultValue));
  3033         attach(result, dc);
  3034         return result;
  3037     /** QualidentList = Qualident {"," Qualident}
  3038      */
  3039     List<JCExpression> qualidentList() {
  3040         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  3041         ts.append(qualident());
  3042         while (token.kind == COMMA) {
  3043             nextToken();
  3044             ts.append(qualident());
  3046         return ts.toList();
  3049     /**
  3050      *  {@literal
  3051      *  TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  3052      *  }
  3053      */
  3054     List<JCTypeParameter> typeParametersOpt() {
  3055         if (token.kind == LT) {
  3056             checkGenerics();
  3057             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3058             nextToken();
  3059             typarams.append(typeParameter());
  3060             while (token.kind == COMMA) {
  3061                 nextToken();
  3062                 typarams.append(typeParameter());
  3064             accept(GT);
  3065             return typarams.toList();
  3066         } else {
  3067             return List.nil();
  3071     /**
  3072      *  {@literal
  3073      *  TypeParameter = TypeVariable [TypeParameterBound]
  3074      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3075      *  TypeVariable = Ident
  3076      *  }
  3077      */
  3078     JCTypeParameter typeParameter() {
  3079         int pos = token.pos;
  3080         Name name = ident();
  3081         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3082         if (token.kind == EXTENDS) {
  3083             nextToken();
  3084             bounds.append(parseType());
  3085             while (token.kind == AMP) {
  3086                 nextToken();
  3087                 bounds.append(parseType());
  3090         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  3093     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3094      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3095      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3096      */
  3097     List<JCVariableDecl> formalParameters() {
  3098         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3099         JCVariableDecl lastParam = null;
  3100         accept(LPAREN);
  3101         if (token.kind != RPAREN) {
  3102             params.append(lastParam = formalParameter());
  3103             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3104                 nextToken();
  3105                 params.append(lastParam = formalParameter());
  3108         accept(RPAREN);
  3109         return params.toList();
  3112     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3113         if (hasParens) {
  3114             accept(LPAREN);
  3116         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3117         if (token.kind != RPAREN && token.kind != ARROW) {
  3118             params.append(implicitParameter());
  3119             while (token.kind == COMMA) {
  3120                 nextToken();
  3121                 params.append(implicitParameter());
  3124         if (hasParens) {
  3125             accept(RPAREN);
  3127         return params.toList();
  3130     JCModifiers optFinal(long flags) {
  3131         JCModifiers mods = modifiersOpt();
  3132         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3133         mods.flags |= flags;
  3134         return mods;
  3137     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3138      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3139      */
  3140     protected JCVariableDecl formalParameter() {
  3141         JCModifiers mods = optFinal(Flags.PARAMETER);
  3142         JCExpression type = parseType();
  3143         if (token.kind == ELLIPSIS) {
  3144             checkVarargs();
  3145             mods.flags |= Flags.VARARGS;
  3146             type = to(F.at(token.pos).TypeArray(type));
  3147             nextToken();
  3149         return variableDeclaratorId(mods, type);
  3152     protected JCVariableDecl implicitParameter() {
  3153         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3154         return variableDeclaratorId(mods, null);
  3157 /* ---------- auxiliary methods -------------- */
  3159     void error(int pos, String key, Object ... args) {
  3160         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3163     void error(DiagnosticPosition pos, String key, Object ... args) {
  3164         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3167     void warning(int pos, String key, Object ... args) {
  3168         log.warning(pos, key, args);
  3171     /** Check that given tree is a legal expression statement.
  3172      */
  3173     protected JCExpression checkExprStat(JCExpression t) {
  3174         if (!TreeInfo.isExpressionStatement(t)) {
  3175             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3176             error(ret, "not.stmt");
  3177             return ret;
  3178         } else {
  3179             return t;
  3183     /** Return precedence of operator represented by token,
  3184      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3185      */
  3186     static int prec(TokenKind token) {
  3187         JCTree.Tag oc = optag(token);
  3188         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3191     /**
  3192      * Return the lesser of two positions, making allowance for either one
  3193      * being unset.
  3194      */
  3195     static int earlier(int pos1, int pos2) {
  3196         if (pos1 == Position.NOPOS)
  3197             return pos2;
  3198         if (pos2 == Position.NOPOS)
  3199             return pos1;
  3200         return (pos1 < pos2 ? pos1 : pos2);
  3203     /** Return operation tag of binary operator represented by token,
  3204      *  No_TAG if token is not a binary operator.
  3205      */
  3206     static JCTree.Tag optag(TokenKind token) {
  3207         switch (token) {
  3208         case BARBAR:
  3209             return OR;
  3210         case AMPAMP:
  3211             return AND;
  3212         case BAR:
  3213             return BITOR;
  3214         case BAREQ:
  3215             return BITOR_ASG;
  3216         case CARET:
  3217             return BITXOR;
  3218         case CARETEQ:
  3219             return BITXOR_ASG;
  3220         case AMP:
  3221             return BITAND;
  3222         case AMPEQ:
  3223             return BITAND_ASG;
  3224         case EQEQ:
  3225             return JCTree.Tag.EQ;
  3226         case BANGEQ:
  3227             return NE;
  3228         case LT:
  3229             return JCTree.Tag.LT;
  3230         case GT:
  3231             return JCTree.Tag.GT;
  3232         case LTEQ:
  3233             return LE;
  3234         case GTEQ:
  3235             return GE;
  3236         case LTLT:
  3237             return SL;
  3238         case LTLTEQ:
  3239             return SL_ASG;
  3240         case GTGT:
  3241             return SR;
  3242         case GTGTEQ:
  3243             return SR_ASG;
  3244         case GTGTGT:
  3245             return USR;
  3246         case GTGTGTEQ:
  3247             return USR_ASG;
  3248         case PLUS:
  3249             return JCTree.Tag.PLUS;
  3250         case PLUSEQ:
  3251             return PLUS_ASG;
  3252         case SUB:
  3253             return MINUS;
  3254         case SUBEQ:
  3255             return MINUS_ASG;
  3256         case STAR:
  3257             return MUL;
  3258         case STAREQ:
  3259             return MUL_ASG;
  3260         case SLASH:
  3261             return DIV;
  3262         case SLASHEQ:
  3263             return DIV_ASG;
  3264         case PERCENT:
  3265             return MOD;
  3266         case PERCENTEQ:
  3267             return MOD_ASG;
  3268         case INSTANCEOF:
  3269             return TYPETEST;
  3270         default:
  3271             return NO_TAG;
  3275     /** Return operation tag of unary operator represented by token,
  3276      *  No_TAG if token is not a binary operator.
  3277      */
  3278     static JCTree.Tag unoptag(TokenKind token) {
  3279         switch (token) {
  3280         case PLUS:
  3281             return POS;
  3282         case SUB:
  3283             return NEG;
  3284         case BANG:
  3285             return NOT;
  3286         case TILDE:
  3287             return COMPL;
  3288         case PLUSPLUS:
  3289             return PREINC;
  3290         case SUBSUB:
  3291             return PREDEC;
  3292         default:
  3293             return NO_TAG;
  3297     /** Return type tag of basic type represented by token,
  3298      *  NONE if token is not a basic type identifier.
  3299      */
  3300     static TypeTag typetag(TokenKind token) {
  3301         switch (token) {
  3302         case BYTE:
  3303             return TypeTag.BYTE;
  3304         case CHAR:
  3305             return TypeTag.CHAR;
  3306         case SHORT:
  3307             return TypeTag.SHORT;
  3308         case INT:
  3309             return TypeTag.INT;
  3310         case LONG:
  3311             return TypeTag.LONG;
  3312         case FLOAT:
  3313             return TypeTag.FLOAT;
  3314         case DOUBLE:
  3315             return TypeTag.DOUBLE;
  3316         case BOOLEAN:
  3317             return TypeTag.BOOLEAN;
  3318         default:
  3319             return TypeTag.NONE;
  3323     void checkGenerics() {
  3324         if (!allowGenerics) {
  3325             error(token.pos, "generics.not.supported.in.source", source.name);
  3326             allowGenerics = true;
  3329     void checkVarargs() {
  3330         if (!allowVarargs) {
  3331             error(token.pos, "varargs.not.supported.in.source", source.name);
  3332             allowVarargs = true;
  3335     void checkForeach() {
  3336         if (!allowForeach) {
  3337             error(token.pos, "foreach.not.supported.in.source", source.name);
  3338             allowForeach = true;
  3341     void checkStaticImports() {
  3342         if (!allowStaticImport) {
  3343             error(token.pos, "static.import.not.supported.in.source", source.name);
  3344             allowStaticImport = true;
  3347     void checkAnnotations() {
  3348         if (!allowAnnotations) {
  3349             error(token.pos, "annotations.not.supported.in.source", source.name);
  3350             allowAnnotations = true;
  3353     void checkDiamond() {
  3354         if (!allowDiamond) {
  3355             error(token.pos, "diamond.not.supported.in.source", source.name);
  3356             allowDiamond = true;
  3359     void checkMulticatch() {
  3360         if (!allowMulticatch) {
  3361             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3362             allowMulticatch = true;
  3365     void checkTryWithResources() {
  3366         if (!allowTWR) {
  3367             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3368             allowTWR = true;
  3371     void checkLambda() {
  3372         if (!allowLambda) {
  3373             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3374             allowLambda = true;
  3377     void checkMethodReferences() {
  3378         if (!allowMethodReferences) {
  3379             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3380             allowMethodReferences = true;
  3383     void checkDefaultMethods() {
  3384         if (!allowDefaultMethods) {
  3385             log.error(token.pos, "default.methods.not.supported.in.source", source.name);
  3386             allowDefaultMethods = true;
  3390     /*
  3391      * a functional source tree and end position mappings
  3392      */
  3393     protected class SimpleEndPosTable extends AbstractEndPosTable {
  3395         private final Map<JCTree, Integer> endPosMap;
  3397         SimpleEndPosTable() {
  3398             endPosMap = new HashMap<JCTree, Integer>();
  3401         protected void storeEnd(JCTree tree, int endpos) {
  3402             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  3405         protected <T extends JCTree> T to(T t) {
  3406             storeEnd(t, token.endPos);
  3407             return t;
  3410         protected <T extends JCTree> T toP(T t) {
  3411             storeEnd(t, S.prevToken().endPos);
  3412             return t;
  3415         public int getEndPos(JCTree tree) {
  3416             Integer value = endPosMap.get(tree);
  3417             return (value == null) ? Position.NOPOS : value;
  3420         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3421             Integer pos = endPosMap.remove(oldTree);
  3422             if (pos != null) {
  3423                 endPosMap.put(newTree, pos);
  3424                 return pos;
  3426             return Position.NOPOS;
  3430     /*
  3431      * a default skeletal implementation without any mapping overhead.
  3432      */
  3433     protected class EmptyEndPosTable extends AbstractEndPosTable {
  3435         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  3437         protected <T extends JCTree> T to(T t) {
  3438             return t;
  3441         protected <T extends JCTree> T toP(T t) {
  3442             return t;
  3445         public int getEndPos(JCTree tree) {
  3446             return Position.NOPOS;
  3449         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3450             return Position.NOPOS;
  3455     protected abstract class AbstractEndPosTable implements EndPosTable {
  3457         /**
  3458          * Store the last error position.
  3459          */
  3460         protected int errorEndPos;
  3462         /**
  3463          * Store ending position for a tree, the value of which is the greater
  3464          * of last error position and the given ending position.
  3465          * @param tree   The tree.
  3466          * @param endpos The ending position to associate with the tree.
  3467          */
  3468         protected abstract void storeEnd(JCTree tree, int endpos);
  3470         /**
  3471          * Store current token's ending position for a tree, the value of which
  3472          * will be the greater of last error position and the ending position of
  3473          * the current token.
  3474          * @param t The tree.
  3475          */
  3476         protected abstract <T extends JCTree> T to(T t);
  3478         /**
  3479          * Store current token's ending position for a tree, the value of which
  3480          * will be the greater of last error position and the ending position of
  3481          * the previous token.
  3482          * @param t The tree.
  3483          */
  3484         protected abstract <T extends JCTree> T toP(T t);
  3486         /**
  3487          * Set the error position during the parsing phases, the value of which
  3488          * will be set only if it is greater than the last stored error position.
  3489          * @param errPos The error position
  3490          */
  3491         protected void setErrorEndPos(int errPos) {
  3492             if (errPos > errorEndPos) {
  3493                 errorEndPos = errPos;

mercurial