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

Wed, 15 Aug 2012 13:48:46 -0700

author
jjh
date
Wed, 15 Aug 2012 13:48:46 -0700
changeset 1305
9d47f4850714
parent 1297
e5cf1569d3a4
child 1326
30c36e23f154
permissions
-rw-r--r--

7191449: update copyright year to match last edit in jdk8 langtools repository
Reviewed-by: jjh
Contributed-by: steve.sides@oracle.com

     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.util.ListBuffer.lb;
    51 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    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     /** Construct a parser from a given scanner, tree factory and log.
    92      */
    93     protected JavacParser(ParserFactory fac,
    94                      Lexer S,
    95                      boolean keepDocComments,
    96                      boolean keepLineMap,
    97                      boolean keepEndPositions) {
    98         this.S = S;
    99         nextToken(); // prime the pump
   100         this.F = fac.F;
   101         this.log = fac.log;
   102         this.names = fac.names;
   103         this.source = fac.source;
   104         this.allowGenerics = source.allowGenerics();
   105         this.allowVarargs = source.allowVarargs();
   106         this.allowAsserts = source.allowAsserts();
   107         this.allowEnums = source.allowEnums();
   108         this.allowForeach = source.allowForeach();
   109         this.allowStaticImport = source.allowStaticImport();
   110         this.allowAnnotations = source.allowAnnotations();
   111         this.allowTWR = source.allowTryWithResources();
   112         this.allowDiamond = source.allowDiamond();
   113         this.allowMulticatch = source.allowMulticatch();
   114         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
   115         this.allowLambda = source.allowLambda() &&
   116                 fac.options.isSet("allowLambda"); //pre-lambda guard
   117         this.allowMethodReferences = source.allowMethodReferences() &&
   118                 fac.options.isSet("allowMethodReferences"); //pre-lambda guard
   119         this.keepDocComments = keepDocComments;
   120         docComments = newDocCommentTable(keepDocComments);
   121         this.keepLineMap = keepLineMap;
   122         this.errorTree = F.Erroneous();
   123         endPosTable = newEndPosTable(keepEndPositions);
   124     }
   126     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
   127         return  keepEndPositions
   128                 ? new SimpleEndPosTable()
   129                 : new EmptyEndPosTable();
   130     }
   132     protected DocCommentTable newDocCommentTable(boolean keepDocComments) {
   133         return keepDocComments ? new SimpleDocCommentTable() : null;
   134     }
   136     /** Switch: Should generics be recognized?
   137      */
   138     boolean allowGenerics;
   140     /** Switch: Should diamond operator be recognized?
   141      */
   142     boolean allowDiamond;
   144     /** Switch: Should multicatch clause be accepted?
   145      */
   146     boolean allowMulticatch;
   148     /** Switch: Should varargs be recognized?
   149      */
   150     boolean allowVarargs;
   152     /** Switch: should we recognize assert statements, or just give a warning?
   153      */
   154     boolean allowAsserts;
   156     /** Switch: should we recognize enums, or just give a warning?
   157      */
   158     boolean allowEnums;
   160     /** Switch: should we recognize foreach?
   161      */
   162     boolean allowForeach;
   164     /** Switch: should we recognize foreach?
   165      */
   166     boolean allowStaticImport;
   168     /** Switch: should we recognize annotations?
   169      */
   170     boolean allowAnnotations;
   172     /** Switch: should we recognize try-with-resources?
   173      */
   174     boolean allowTWR;
   176     /** Switch: should we fold strings?
   177      */
   178     boolean allowStringFolding;
   180     /** Switch: should we recognize lambda expressions?
   181      */
   182     boolean allowLambda;
   184     /** Switch: should we allow method/constructor references?
   185      */
   186     boolean allowMethodReferences;
   188     /** Switch: should we keep docComments?
   189      */
   190     boolean keepDocComments;
   192     /** Switch: should we keep line table?
   193      */
   194     boolean keepLineMap;
   196     /** When terms are parsed, the mode determines which is expected:
   197      *     mode = EXPR        : an expression
   198      *     mode = TYPE        : a type
   199      *     mode = NOPARAMS    : no parameters allowed for type
   200      *     mode = TYPEARG     : type argument
   201      */
   202     static final int EXPR = 0x1;
   203     static final int TYPE = 0x2;
   204     static final int NOPARAMS = 0x4;
   205     static final int TYPEARG = 0x8;
   206     static final int DIAMOND = 0x10;
   208     /** The current mode.
   209      */
   210     private int mode = 0;
   212     /** The mode of the term that was parsed last.
   213      */
   214     private int lastmode = 0;
   216     /* ---------- token management -------------- */
   218     protected Token token;
   220     protected void nextToken() {
   221         S.nextToken();
   222         token = S.token();
   223     }
   225     protected boolean peekToken(TokenKind tk) {
   226         return S.token(1).kind == tk;
   227     }
   229     protected boolean peekToken(TokenKind tk1, TokenKind tk2) {
   230         return S.token(1).kind == tk1 &&
   231                 S.token(2).kind == tk2;
   232     }
   234     protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) {
   235         return S.token(1).kind == tk1 &&
   236                 S.token(2).kind == tk2 &&
   237                 S.token(3).kind == tk3;
   238     }
   240     protected boolean peekToken(TokenKind... kinds) {
   241         for (int lookahead = 0 ; lookahead < kinds.length ; lookahead++) {
   242             if (S.token(lookahead + 1).kind != kinds[lookahead]) {
   243                 return false;
   244             }
   245         }
   246         return true;
   247     }
   249     /* ---------- error recovery -------------- */
   251     private JCErroneous errorTree;
   253     /** Skip forward until a suitable stop token is found.
   254      */
   255     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
   256          while (true) {
   257              switch (token.kind) {
   258                 case SEMI:
   259                     nextToken();
   260                     return;
   261                 case PUBLIC:
   262                 case FINAL:
   263                 case ABSTRACT:
   264                 case MONKEYS_AT:
   265                 case EOF:
   266                 case CLASS:
   267                 case INTERFACE:
   268                 case ENUM:
   269                     return;
   270                 case IMPORT:
   271                     if (stopAtImport)
   272                         return;
   273                     break;
   274                 case LBRACE:
   275                 case RBRACE:
   276                 case PRIVATE:
   277                 case PROTECTED:
   278                 case STATIC:
   279                 case TRANSIENT:
   280                 case NATIVE:
   281                 case VOLATILE:
   282                 case SYNCHRONIZED:
   283                 case STRICTFP:
   284                 case LT:
   285                 case BYTE:
   286                 case SHORT:
   287                 case CHAR:
   288                 case INT:
   289                 case LONG:
   290                 case FLOAT:
   291                 case DOUBLE:
   292                 case BOOLEAN:
   293                 case VOID:
   294                     if (stopAtMemberDecl)
   295                         return;
   296                     break;
   297                 case IDENTIFIER:
   298                    if (stopAtIdentifier)
   299                         return;
   300                     break;
   301                 case CASE:
   302                 case DEFAULT:
   303                 case IF:
   304                 case FOR:
   305                 case WHILE:
   306                 case DO:
   307                 case TRY:
   308                 case SWITCH:
   309                 case RETURN:
   310                 case THROW:
   311                 case BREAK:
   312                 case CONTINUE:
   313                 case ELSE:
   314                 case FINALLY:
   315                 case CATCH:
   316                     if (stopAtStatement)
   317                         return;
   318                     break;
   319             }
   320             nextToken();
   321         }
   322     }
   324     private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
   325         return syntaxError(pos, List.<JCTree>nil(), key, args);
   326     }
   328     private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
   329         setErrorEndPos(pos);
   330         JCErroneous err = F.at(pos).Erroneous(errs);
   331         reportSyntaxError(err, key, (Object[])args);
   332         if (errs != null) {
   333             JCTree last = errs.last();
   334             if (last != null)
   335                 storeEnd(last, pos);
   336         }
   337         return toP(err);
   338     }
   340     private int errorPos = Position.NOPOS;
   342     /**
   343      * Report a syntax using the given the position parameter and arguments,
   344      * unless one was already reported at the same position.
   345      */
   346     private void reportSyntaxError(int pos, String key, Object... args) {
   347         JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
   348         reportSyntaxError(diag, key, args);
   349     }
   351     /**
   352      * Report a syntax error using the given DiagnosticPosition object and
   353      * arguments, unless one was already reported at the same position.
   354      */
   355     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
   356         int pos = diagPos.getPreferredPosition();
   357         if (pos > S.errPos() || pos == Position.NOPOS) {
   358             if (token.kind == EOF) {
   359                 error(diagPos, "premature.eof");
   360             } else {
   361                 error(diagPos, key, args);
   362             }
   363         }
   364         S.errPos(pos);
   365         if (token.pos == errorPos)
   366             nextToken(); // guarantee progress
   367         errorPos = token.pos;
   368     }
   371     /** Generate a syntax error at current position unless one was already
   372      *  reported at the same position.
   373      */
   374     private JCErroneous syntaxError(String key) {
   375         return syntaxError(token.pos, key);
   376     }
   378     /** Generate a syntax error at current position unless one was
   379      *  already reported at the same position.
   380      */
   381     private JCErroneous syntaxError(String key, TokenKind arg) {
   382         return syntaxError(token.pos, key, arg);
   383     }
   385     /** If next input token matches given token, skip it, otherwise report
   386      *  an error.
   387      */
   388     public void accept(TokenKind tk) {
   389         if (token.kind == tk) {
   390             nextToken();
   391         } else {
   392             setErrorEndPos(token.pos);
   393             reportSyntaxError(S.prevToken().endPos, "expected", tk);
   394         }
   395     }
   397     /** Report an illegal start of expression/type error at given position.
   398      */
   399     JCExpression illegal(int pos) {
   400         setErrorEndPos(pos);
   401         if ((mode & EXPR) != 0)
   402             return syntaxError(pos, "illegal.start.of.expr");
   403         else
   404             return syntaxError(pos, "illegal.start.of.type");
   406     }
   408     /** Report an illegal start of expression/type error at current position.
   409      */
   410     JCExpression illegal() {
   411         return illegal(token.pos);
   412     }
   414     /** Diagnose a modifier flag from the set, if any. */
   415     void checkNoMods(long mods) {
   416         if (mods != 0) {
   417             long lowestMod = mods & -mods;
   418             error(token.pos, "mod.not.allowed.here",
   419                       Flags.asFlagSet(lowestMod));
   420         }
   421     }
   423 /* ---------- doc comments --------- */
   425     /** A table to store all documentation comments
   426      *  indexed by the tree nodes they refer to.
   427      *  defined only if option flag keepDocComment is set.
   428      */
   429     private final DocCommentTable docComments;
   431     /** Make an entry into docComments hashtable,
   432      *  provided flag keepDocComments is set and given doc comment is non-null.
   433      *  @param tree   The tree to be used as index in the hashtable
   434      *  @param dc     The doc comment to associate with the tree, or null.
   435      */
   436     void attach(JCTree tree, Comment dc) {
   437         if (keepDocComments && dc != null) {
   438 //          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
   439             docComments.putComment(tree, dc);
   440         }
   441     }
   443 /* -------- source positions ------- */
   445     private void setErrorEndPos(int errPos) {
   446         endPosTable.setErrorEndPos(errPos);
   447     }
   449     private void storeEnd(JCTree tree, int endpos) {
   450         endPosTable.storeEnd(tree, endpos);
   451     }
   453     private <T extends JCTree> T to(T t) {
   454         return endPosTable.to(t);
   455     }
   457     private <T extends JCTree> T toP(T t) {
   458         return endPosTable.toP(t);
   459     }
   461     /** Get the start position for a tree node.  The start position is
   462      * defined to be the position of the first character of the first
   463      * token of the node's source text.
   464      * @param tree  The tree node
   465      */
   466     public int getStartPos(JCTree tree) {
   467         return TreeInfo.getStartPos(tree);
   468     }
   470     /**
   471      * Get the end position for a tree node.  The end position is
   472      * defined to be the position of the last character of the last
   473      * token of the node's source text.  Returns Position.NOPOS if end
   474      * positions are not generated or the position is otherwise not
   475      * found.
   476      * @param tree  The tree node
   477      */
   478     public int getEndPos(JCTree tree) {
   479         return endPosTable.getEndPos(tree);
   480     }
   484 /* ---------- parsing -------------- */
   486     /**
   487      * Ident = IDENTIFIER
   488      */
   489     Name ident() {
   490         if (token.kind == IDENTIFIER) {
   491             Name name = token.name();
   492             nextToken();
   493             return name;
   494         } else if (token.kind == ASSERT) {
   495             if (allowAsserts) {
   496                 error(token.pos, "assert.as.identifier");
   497                 nextToken();
   498                 return names.error;
   499             } else {
   500                 warning(token.pos, "assert.as.identifier");
   501                 Name name = token.name();
   502                 nextToken();
   503                 return name;
   504             }
   505         } else if (token.kind == ENUM) {
   506             if (allowEnums) {
   507                 error(token.pos, "enum.as.identifier");
   508                 nextToken();
   509                 return names.error;
   510             } else {
   511                 warning(token.pos, "enum.as.identifier");
   512                 Name name = token.name();
   513                 nextToken();
   514                 return name;
   515             }
   516         } else {
   517             accept(IDENTIFIER);
   518             return names.error;
   519         }
   520 }
   522     /**
   523      * Qualident = Ident { DOT Ident }
   524      */
   525     public JCExpression qualident() {
   526         JCExpression t = toP(F.at(token.pos).Ident(ident()));
   527         while (token.kind == DOT) {
   528             int pos = token.pos;
   529             nextToken();
   530             t = toP(F.at(pos).Select(t, ident()));
   531         }
   532         return t;
   533     }
   535     JCExpression literal(Name prefix) {
   536         return literal(prefix, token.pos);
   537     }
   539     /**
   540      * Literal =
   541      *     INTLITERAL
   542      *   | LONGLITERAL
   543      *   | FLOATLITERAL
   544      *   | DOUBLELITERAL
   545      *   | CHARLITERAL
   546      *   | STRINGLITERAL
   547      *   | TRUE
   548      *   | FALSE
   549      *   | NULL
   550      */
   551     JCExpression literal(Name prefix, int pos) {
   552         JCExpression t = errorTree;
   553         switch (token.kind) {
   554         case INTLITERAL:
   555             try {
   556                 t = F.at(pos).Literal(
   557                     TypeTags.INT,
   558                     Convert.string2int(strval(prefix), token.radix()));
   559             } catch (NumberFormatException ex) {
   560                 error(token.pos, "int.number.too.large", strval(prefix));
   561             }
   562             break;
   563         case LONGLITERAL:
   564             try {
   565                 t = F.at(pos).Literal(
   566                     TypeTags.LONG,
   567                     new Long(Convert.string2long(strval(prefix), token.radix())));
   568             } catch (NumberFormatException ex) {
   569                 error(token.pos, "int.number.too.large", strval(prefix));
   570             }
   571             break;
   572         case FLOATLITERAL: {
   573             String proper = token.radix() == 16 ?
   574                     ("0x"+ token.stringVal()) :
   575                     token.stringVal();
   576             Float n;
   577             try {
   578                 n = Float.valueOf(proper);
   579             } catch (NumberFormatException ex) {
   580                 // error already reported in scanner
   581                 n = Float.NaN;
   582             }
   583             if (n.floatValue() == 0.0f && !isZero(proper))
   584                 error(token.pos, "fp.number.too.small");
   585             else if (n.floatValue() == Float.POSITIVE_INFINITY)
   586                 error(token.pos, "fp.number.too.large");
   587             else
   588                 t = F.at(pos).Literal(TypeTags.FLOAT, n);
   589             break;
   590         }
   591         case DOUBLELITERAL: {
   592             String proper = token.radix() == 16 ?
   593                     ("0x"+ token.stringVal()) :
   594                     token.stringVal();
   595             Double n;
   596             try {
   597                 n = Double.valueOf(proper);
   598             } catch (NumberFormatException ex) {
   599                 // error already reported in scanner
   600                 n = Double.NaN;
   601             }
   602             if (n.doubleValue() == 0.0d && !isZero(proper))
   603                 error(token.pos, "fp.number.too.small");
   604             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
   605                 error(token.pos, "fp.number.too.large");
   606             else
   607                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   608             break;
   609         }
   610         case CHARLITERAL:
   611             t = F.at(pos).Literal(
   612                 TypeTags.CHAR,
   613                 token.stringVal().charAt(0) + 0);
   614             break;
   615         case STRINGLITERAL:
   616             t = F.at(pos).Literal(
   617                 TypeTags.CLASS,
   618                 token.stringVal());
   619             break;
   620         case TRUE: case FALSE:
   621             t = F.at(pos).Literal(
   622                 TypeTags.BOOLEAN,
   623                 (token.kind == TRUE ? 1 : 0));
   624             break;
   625         case NULL:
   626             t = F.at(pos).Literal(
   627                 TypeTags.BOT,
   628                 null);
   629             break;
   630         default:
   631             Assert.error();
   632         }
   633         if (t == errorTree)
   634             t = F.at(pos).Erroneous();
   635         storeEnd(t, token.endPos);
   636         nextToken();
   637         return t;
   638     }
   639 //where
   640         boolean isZero(String s) {
   641             char[] cs = s.toCharArray();
   642             int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
   643             int i = ((base==16) ? 2 : 0);
   644             while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
   645             return !(i < cs.length && (Character.digit(cs[i], base) > 0));
   646         }
   648         String strval(Name prefix) {
   649             String s = token.stringVal();
   650             return prefix.isEmpty() ? s : prefix + s;
   651         }
   653     /** terms can be either expressions or types.
   654      */
   655     public JCExpression parseExpression() {
   656         return term(EXPR);
   657     }
   659     public JCExpression parseType() {
   660         return term(TYPE);
   661     }
   663     JCExpression term(int newmode) {
   664         int prevmode = mode;
   665         mode = newmode;
   666         JCExpression t = term();
   667         lastmode = mode;
   668         mode = prevmode;
   669         return t;
   670     }
   672     /**
   673      *  Expression = Expression1 [ExpressionRest]
   674      *  ExpressionRest = [AssignmentOperator Expression1]
   675      *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
   676      *                       "&=" | "|=" | "^=" |
   677      *                       "%=" | "<<=" | ">>=" | ">>>="
   678      *  Type = Type1
   679      *  TypeNoParams = TypeNoParams1
   680      *  StatementExpression = Expression
   681      *  ConstantExpression = Expression
   682      */
   683     JCExpression term() {
   684         JCExpression t = term1();
   685         if ((mode & EXPR) != 0 &&
   686             token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
   687             return termRest(t);
   688         else
   689             return t;
   690     }
   692     JCExpression termRest(JCExpression t) {
   693         switch (token.kind) {
   694         case EQ: {
   695             int pos = token.pos;
   696             nextToken();
   697             mode = EXPR;
   698             JCExpression t1 = term();
   699             return toP(F.at(pos).Assign(t, t1));
   700         }
   701         case PLUSEQ:
   702         case SUBEQ:
   703         case STAREQ:
   704         case SLASHEQ:
   705         case PERCENTEQ:
   706         case AMPEQ:
   707         case BAREQ:
   708         case CARETEQ:
   709         case LTLTEQ:
   710         case GTGTEQ:
   711         case GTGTGTEQ:
   712             int pos = token.pos;
   713             TokenKind tk = token.kind;
   714             nextToken();
   715             mode = EXPR;
   716             JCExpression t1 = term();
   717             return F.at(pos).Assignop(optag(tk), t, t1);
   718         default:
   719             return t;
   720         }
   721     }
   723     /** Expression1   = Expression2 [Expression1Rest]
   724      *  Type1         = Type2
   725      *  TypeNoParams1 = TypeNoParams2
   726      */
   727     JCExpression term1() {
   728         JCExpression t = term2();
   729         if ((mode & EXPR) != 0 && token.kind == QUES) {
   730             mode = EXPR;
   731             return term1Rest(t);
   732         } else {
   733             return t;
   734         }
   735     }
   737     /** Expression1Rest = ["?" Expression ":" Expression1]
   738      */
   739     JCExpression term1Rest(JCExpression t) {
   740         if (token.kind == QUES) {
   741             int pos = token.pos;
   742             nextToken();
   743             JCExpression t1 = term();
   744             accept(COLON);
   745             JCExpression t2 = term1();
   746             return F.at(pos).Conditional(t, t1, t2);
   747         } else {
   748             return t;
   749         }
   750     }
   752     /** Expression2   = Expression3 [Expression2Rest]
   753      *  Type2         = Type3
   754      *  TypeNoParams2 = TypeNoParams3
   755      */
   756     JCExpression term2() {
   757         JCExpression t = term3();
   758         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
   759             mode = EXPR;
   760             return term2Rest(t, TreeInfo.orPrec);
   761         } else {
   762             return t;
   763         }
   764     }
   766     /*  Expression2Rest = {infixop Expression3}
   767      *                  | Expression3 instanceof Type
   768      *  infixop         = "||"
   769      *                  | "&&"
   770      *                  | "|"
   771      *                  | "^"
   772      *                  | "&"
   773      *                  | "==" | "!="
   774      *                  | "<" | ">" | "<=" | ">="
   775      *                  | "<<" | ">>" | ">>>"
   776      *                  | "+" | "-"
   777      *                  | "*" | "/" | "%"
   778      */
   779     JCExpression term2Rest(JCExpression t, int minprec) {
   780         List<JCExpression[]> savedOd = odStackSupply.elems;
   781         JCExpression[] odStack = newOdStack();
   782         List<Token[]> savedOp = opStackSupply.elems;
   783         Token[] opStack = newOpStack();
   785         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
   786         int top = 0;
   787         odStack[0] = t;
   788         int startPos = token.pos;
   789         Token topOp = Tokens.DUMMY;
   790         while (prec(token.kind) >= minprec) {
   791             opStack[top] = topOp;
   792             top++;
   793             topOp = token;
   794             nextToken();
   795             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
   796             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
   797                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
   798                                         odStack[top]);
   799                 top--;
   800                 topOp = opStack[top];
   801             }
   802         }
   803         Assert.check(top == 0);
   804         t = odStack[0];
   806         if (t.hasTag(JCTree.Tag.PLUS)) {
   807             StringBuffer buf = foldStrings(t);
   808             if (buf != null) {
   809                 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
   810             }
   811         }
   813         odStackSupply.elems = savedOd; // optimization
   814         opStackSupply.elems = savedOp; // optimization
   815         return t;
   816     }
   817 //where
   818         /** Construct a binary or type test node.
   819          */
   820         private JCExpression makeOp(int pos,
   821                                     TokenKind topOp,
   822                                     JCExpression od1,
   823                                     JCExpression od2)
   824         {
   825             if (topOp == INSTANCEOF) {
   826                 return F.at(pos).TypeTest(od1, od2);
   827             } else {
   828                 return F.at(pos).Binary(optag(topOp), od1, od2);
   829             }
   830         }
   831         /** If tree is a concatenation of string literals, replace it
   832          *  by a single literal representing the concatenated string.
   833          */
   834         protected StringBuffer foldStrings(JCTree tree) {
   835             if (!allowStringFolding)
   836                 return null;
   837             List<String> buf = List.nil();
   838             while (true) {
   839                 if (tree.hasTag(LITERAL)) {
   840                     JCLiteral lit = (JCLiteral) tree;
   841                     if (lit.typetag == TypeTags.CLASS) {
   842                         StringBuffer sbuf =
   843                             new StringBuffer((String)lit.value);
   844                         while (buf.nonEmpty()) {
   845                             sbuf.append(buf.head);
   846                             buf = buf.tail;
   847                         }
   848                         return sbuf;
   849                     }
   850                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
   851                     JCBinary op = (JCBinary)tree;
   852                     if (op.rhs.hasTag(LITERAL)) {
   853                         JCLiteral lit = (JCLiteral) op.rhs;
   854                         if (lit.typetag == TypeTags.CLASS) {
   855                             buf = buf.prepend((String) lit.value);
   856                             tree = op.lhs;
   857                             continue;
   858                         }
   859                     }
   860                 }
   861                 return null;
   862             }
   863         }
   865         /** optimization: To save allocating a new operand/operator stack
   866          *  for every binary operation, we use supplys.
   867          */
   868         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
   869         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
   871         private JCExpression[] newOdStack() {
   872             if (odStackSupply.elems == odStackSupply.last)
   873                 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
   874             JCExpression[] odStack = odStackSupply.elems.head;
   875             odStackSupply.elems = odStackSupply.elems.tail;
   876             return odStack;
   877         }
   879         private Token[] newOpStack() {
   880             if (opStackSupply.elems == opStackSupply.last)
   881                 opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
   882             Token[] opStack = opStackSupply.elems.head;
   883             opStackSupply.elems = opStackSupply.elems.tail;
   884             return opStack;
   885         }
   887     /** Expression3    = PrefixOp Expression3
   888      *                 | "(" Expr | TypeNoParams ")" Expression3
   889      *                 | Primary {Selector} {PostfixOp}
   890      *  Primary        = "(" Expression ")"
   891      *                 | Literal
   892      *                 | [TypeArguments] THIS [Arguments]
   893      *                 | [TypeArguments] SUPER SuperSuffix
   894      *                 | NEW [TypeArguments] Creator
   895      *                 | "(" Arguments ")" "->" ( Expression | Block )
   896      *                 | Ident "->" ( Expression | Block )
   897      *                 | Ident { "." Ident }
   898      *                 | Expression3 MemberReferenceSuffix
   899      *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
   900      *                   | Arguments
   901      *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
   902      *                   ]
   903      *                 | BasicType BracketsOpt "." CLASS
   904      *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
   905      *  PostfixOp      = "++" | "--"
   906      *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
   907      *                 | BasicType
   908      *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
   909      *  Selector       = "." [TypeArguments] Ident [Arguments]
   910      *                 | "." THIS
   911      *                 | "." [TypeArguments] SUPER SuperSuffix
   912      *                 | "." NEW [TypeArguments] InnerCreator
   913      *                 | "[" Expression "]"
   914      *  TypeSelector   = "." Ident [TypeArguments]
   915      *  SuperSuffix    = Arguments | "." Ident [Arguments]
   916      */
   917     protected JCExpression term3() {
   918         int pos = token.pos;
   919         JCExpression t;
   920         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
   921         switch (token.kind) {
   922         case QUES:
   923             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
   924                 mode = TYPE;
   925                 return typeArgument();
   926             } else
   927                 return illegal();
   928         case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
   929             if (typeArgs == null && (mode & EXPR) != 0) {
   930                 TokenKind tk = token.kind;
   931                 nextToken();
   932                 mode = EXPR;
   933                 if (tk == SUB &&
   934                     (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
   935                     token.radix() == 10) {
   936                     mode = EXPR;
   937                     t = literal(names.hyphen, pos);
   938                 } else {
   939                     t = term3();
   940                     return F.at(pos).Unary(unoptag(tk), t);
   941                 }
   942             } else return illegal();
   943             break;
   944         case LPAREN:
   945             if (typeArgs == null && (mode & EXPR) != 0) {
   946                 if (peekToken(FINAL) ||
   947                         peekToken(RPAREN) ||
   948                         peekToken(IDENTIFIER, COMMA) ||
   949                         peekToken(IDENTIFIER, RPAREN, ARROW)) {
   950                     //implicit n-ary lambda
   951                     t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos);
   952                     break;
   953                 } else {
   954                     nextToken();
   955                     mode = EXPR | TYPE | NOPARAMS;
   956                     t = term3();
   957                     if ((mode & TYPE) != 0 && token.kind == LT) {
   958                         // Could be a cast to a parameterized type
   959                         JCTree.Tag op = JCTree.Tag.LT;
   960                         int pos1 = token.pos;
   961                         nextToken();
   962                         mode &= (EXPR | TYPE);
   963                         mode |= TYPEARG;
   964                         JCExpression t1 = term3();
   965                         if ((mode & TYPE) != 0 &&
   966                             (token.kind == COMMA || token.kind == GT)) {
   967                             mode = TYPE;
   968                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
   969                             args.append(t1);
   970                             while (token.kind == COMMA) {
   971                                 nextToken();
   972                                 args.append(typeArgument());
   973                             }
   974                             accept(GT);
   975                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
   976                             checkGenerics();
   977                             mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type
   978                             t = term3Rest(t, typeArgs);
   979                             if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) {
   980                                 //explicit lambda (w/ generic type)
   981                                 mode = EXPR;
   982                                 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
   983                                 if (token.kind == ELLIPSIS) {
   984                                     mods.flags = Flags.VARARGS;
   985                                     t = to(F.at(token.pos).TypeArray(t));
   986                                     nextToken();
   987                                 }
   988                                 t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
   989                                 break;
   990                             }
   991                         } else if ((mode & EXPR) != 0) {
   992                             mode = EXPR;
   993                             JCExpression e = term2Rest(t1, TreeInfo.shiftPrec);
   994                             t = F.at(pos1).Binary(op, t, e);
   995                             t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
   996                         } else {
   997                             accept(GT);
   998                         }
   999                     } else if ((mode & TYPE) != 0 &&
  1000                             (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) {
  1001                         //explicit lambda (w/ non-generic type)
  1002                         mode = EXPR;
  1003                         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  1004                         if (token.kind == ELLIPSIS) {
  1005                             mods.flags = Flags.VARARGS;
  1006                             t = to(F.at(token.pos).TypeArray(t));
  1007                             nextToken();
  1009                         t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos);
  1010                         break;
  1011                     } else {
  1012                         t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
  1016                 accept(RPAREN);
  1017                 lastmode = mode;
  1018                 mode = EXPR;
  1019                 if ((lastmode & EXPR) == 0) {
  1020                     JCExpression t1 = term3();
  1021                     return F.at(pos).TypeCast(t, t1);
  1022                 } else if ((lastmode & TYPE) != 0) {
  1023                     switch (token.kind) {
  1024                     /*case PLUSPLUS: case SUBSUB: */
  1025                     case BANG: case TILDE:
  1026                     case LPAREN: case THIS: case SUPER:
  1027                     case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
  1028                     case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
  1029                     case TRUE: case FALSE: case NULL:
  1030                         case NEW: case IDENTIFIER: case ASSERT: case ENUM:
  1031                     case BYTE: case SHORT: case CHAR: case INT:
  1032                     case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
  1033                         JCExpression t1 = term3();
  1034                         return F.at(pos).TypeCast(t, t1);
  1037             } else {
  1038                 return illegal();
  1040             t = toP(F.at(pos).Parens(t));
  1041             break;
  1042         case THIS:
  1043             if ((mode & EXPR) != 0) {
  1044                 mode = EXPR;
  1045                 t = to(F.at(pos).Ident(names._this));
  1046                 nextToken();
  1047                 if (typeArgs == null)
  1048                     t = argumentsOpt(null, t);
  1049                 else
  1050                     t = arguments(typeArgs, t);
  1051                 typeArgs = null;
  1052             } else return illegal();
  1053             break;
  1054         case SUPER:
  1055             if ((mode & EXPR) != 0) {
  1056                 mode = EXPR;
  1057                 t = to(F.at(pos).Ident(names._super));
  1058                 t = superSuffix(typeArgs, t);
  1059                 typeArgs = null;
  1060             } else return illegal();
  1061             break;
  1062         case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
  1063         case CHARLITERAL: case STRINGLITERAL:
  1064         case TRUE: case FALSE: case NULL:
  1065             if (typeArgs == null && (mode & EXPR) != 0) {
  1066                 mode = EXPR;
  1067                 t = literal(names.empty);
  1068             } else return illegal();
  1069             break;
  1070         case NEW:
  1071             if (typeArgs != null) return illegal();
  1072             if ((mode & EXPR) != 0) {
  1073                 mode = EXPR;
  1074                 nextToken();
  1075                 if (token.kind == LT) typeArgs = typeArguments(false);
  1076                 t = creator(pos, typeArgs);
  1077                 typeArgs = null;
  1078             } else return illegal();
  1079             break;
  1080         case IDENTIFIER: case ASSERT: case ENUM:
  1081             if (typeArgs != null) return illegal();
  1082             if ((mode & EXPR) != 0 && peekToken(ARROW)) {
  1083                 t = lambdaExpressionOrStatement(false, false, pos);
  1084             } else {
  1085                 t = toP(F.at(token.pos).Ident(ident()));
  1086                 loop: while (true) {
  1087                     pos = token.pos;
  1088                     switch (token.kind) {
  1089                     case LBRACKET:
  1090                         nextToken();
  1091                         if (token.kind == RBRACKET) {
  1092                             nextToken();
  1093                             t = bracketsOpt(t);
  1094                             t = toP(F.at(pos).TypeArray(t));
  1095                             t = bracketsSuffix(t);
  1096                         } else {
  1097                             if ((mode & EXPR) != 0) {
  1098                                 mode = EXPR;
  1099                                 JCExpression t1 = term();
  1100                                 t = to(F.at(pos).Indexed(t, t1));
  1102                             accept(RBRACKET);
  1104                         break loop;
  1105                     case LPAREN:
  1106                         if ((mode & EXPR) != 0) {
  1107                             mode = EXPR;
  1108                             t = arguments(typeArgs, t);
  1109                             typeArgs = null;
  1111                         break loop;
  1112                     case DOT:
  1113                         nextToken();
  1114                         int oldmode = mode;
  1115                         mode &= ~NOPARAMS;
  1116                         typeArgs = typeArgumentsOpt(EXPR);
  1117                         mode = oldmode;
  1118                         if ((mode & EXPR) != 0) {
  1119                             switch (token.kind) {
  1120                             case CLASS:
  1121                                 if (typeArgs != null) return illegal();
  1122                                 mode = EXPR;
  1123                                 t = to(F.at(pos).Select(t, names._class));
  1124                                 nextToken();
  1125                                 break loop;
  1126                             case THIS:
  1127                                 if (typeArgs != null) return illegal();
  1128                                 mode = EXPR;
  1129                                 t = to(F.at(pos).Select(t, names._this));
  1130                                 nextToken();
  1131                                 break loop;
  1132                             case SUPER:
  1133                                 mode = EXPR;
  1134                                 t = to(F.at(pos).Select(t, names._super));
  1135                                 t = superSuffix(typeArgs, t);
  1136                                 typeArgs = null;
  1137                                 break loop;
  1138                             case NEW:
  1139                                 if (typeArgs != null) return illegal();
  1140                                 mode = EXPR;
  1141                                 int pos1 = token.pos;
  1142                                 nextToken();
  1143                                 if (token.kind == LT) typeArgs = typeArguments(false);
  1144                                 t = innerCreator(pos1, typeArgs, t);
  1145                                 typeArgs = null;
  1146                                 break loop;
  1149                         // typeArgs saved for next loop iteration.
  1150                         t = toP(F.at(pos).Select(t, ident()));
  1151                         break;
  1152                     case LT:
  1153                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
  1154                             //this is an unbound method reference whose qualifier
  1155                             //is a generic type i.e. A<S>#m
  1156                             int pos1 = token.pos;
  1157                             accept(LT);
  1158                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
  1159                             args.append(typeArgument());
  1160                             while (token.kind == COMMA) {
  1161                                 nextToken();
  1162                                 args.append(typeArgument());
  1164                             accept(GT);
  1165                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
  1166                             checkGenerics();
  1167                             while (token.kind == DOT) {
  1168                                 nextToken();
  1169                                 mode = TYPE;
  1170                                 t = toP(F.at(token.pos).Select(t, ident()));
  1171                                 t = typeArgumentsOpt(t);
  1173                             if (token.kind != HASH) {
  1174                                 //method reference expected here
  1175                                 t = illegal();
  1177                             mode = EXPR;
  1178                             return term3Rest(t, typeArgs);
  1180                         break loop;
  1181                     default:
  1182                         break loop;
  1186             if (typeArgs != null) illegal();
  1187             t = typeArgumentsOpt(t);
  1188             break;
  1189         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1190         case DOUBLE: case BOOLEAN:
  1191             if (typeArgs != null) illegal();
  1192             t = bracketsSuffix(bracketsOpt(basicType()));
  1193             break;
  1194         case VOID:
  1195             if (typeArgs != null) illegal();
  1196             if ((mode & EXPR) != 0) {
  1197                 nextToken();
  1198                 if (token.kind == DOT) {
  1199                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
  1200                     t = bracketsSuffix(ti);
  1201                 } else {
  1202                     return illegal(pos);
  1204             } else {
  1205                 // Support the corner case of myMethodHandle.<void>invoke() by passing
  1206                 // a void type (like other primitive types) to the next phase.
  1207                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
  1208                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
  1209                 nextToken();
  1210                 return ti;
  1211                 //return illegal();
  1213             break;
  1214         default:
  1215             return illegal();
  1217         return term3Rest(t, typeArgs);
  1220     JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
  1221         if (typeArgs != null) illegal();
  1222         while (true) {
  1223             int pos1 = token.pos;
  1224             if (token.kind == LBRACKET) {
  1225                 nextToken();
  1226                 if ((mode & TYPE) != 0) {
  1227                     int oldmode = mode;
  1228                     mode = TYPE;
  1229                     if (token.kind == RBRACKET) {
  1230                         nextToken();
  1231                         t = bracketsOpt(t);
  1232                         t = toP(F.at(pos1).TypeArray(t));
  1233                         return t;
  1235                     mode = oldmode;
  1237                 if ((mode & EXPR) != 0) {
  1238                     mode = EXPR;
  1239                     JCExpression t1 = term();
  1240                     t = to(F.at(pos1).Indexed(t, t1));
  1242                 accept(RBRACKET);
  1243             } else if (token.kind == DOT) {
  1244                 nextToken();
  1245                 typeArgs = typeArgumentsOpt(EXPR);
  1246                 if (token.kind == SUPER && (mode & EXPR) != 0) {
  1247                     mode = EXPR;
  1248                     t = to(F.at(pos1).Select(t, names._super));
  1249                     nextToken();
  1250                     t = arguments(typeArgs, t);
  1251                     typeArgs = null;
  1252                 } else if (token.kind == NEW && (mode & EXPR) != 0) {
  1253                     if (typeArgs != null) return illegal();
  1254                     mode = EXPR;
  1255                     int pos2 = token.pos;
  1256                     nextToken();
  1257                     if (token.kind == LT) typeArgs = typeArguments(false);
  1258                     t = innerCreator(pos2, typeArgs, t);
  1259                     typeArgs = null;
  1260                 } else {
  1261                     t = toP(F.at(pos1).Select(t, ident()));
  1262                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
  1263                     typeArgs = null;
  1265             } else if ((mode & EXPR) != 0 && token.kind == HASH) {
  1266                 mode = EXPR;
  1267                 if (typeArgs != null) return illegal();
  1268                 accept(HASH);
  1269                 t = memberReferenceSuffix(pos1, t);
  1270             } else {
  1271                 break;
  1274         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
  1275             mode = EXPR;
  1276             t = to(F.at(token.pos).Unary(
  1277                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
  1278             nextToken();
  1280         return toP(t);
  1283     /**
  1284      * If we see an identifier followed by a '&lt;' it could be an unbound
  1285      * method reference or a binary expression. To disambiguate, look for a
  1286      * matching '&gt;' and see if the subsequent terminal is either '.' or '#'.
  1287      */
  1288     @SuppressWarnings("fallthrough")
  1289     boolean isUnboundMemberRef() {
  1290         int pos = 0, depth = 0;
  1291         for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
  1292             switch (t.kind) {
  1293                 case IDENTIFIER: case QUES: case EXTENDS: case SUPER:
  1294                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
  1295                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
  1296                 case DOUBLE: case BOOLEAN: case CHAR:
  1297                     break;
  1298                 case LT:
  1299                     depth++; break;
  1300                 case GTGTGT:
  1301                     depth--;
  1302                 case GTGT:
  1303                     depth--;
  1304                 case GT:
  1305                     depth--;
  1306                     if (depth == 0) {
  1307                         return
  1308                             S.token(pos + 1).kind == TokenKind.DOT ||
  1309                             S.token(pos + 1).kind == TokenKind.HASH;
  1311                     break;
  1312                 default:
  1313                     return false;
  1318     JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) {
  1319         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  1320         params.append(firstParam);
  1321         JCVariableDecl lastParam = firstParam;
  1322         while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  1323             nextToken();
  1324             params.append(lastParam = formalParameter());
  1326         accept(RPAREN);
  1327         return lambdaExpressionOrStatementRest(params.toList(), pos);
  1330     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1331         List<JCVariableDecl> params = explicitParams ?
  1332                 formalParameters() :
  1333                 implicitParameters(hasParens);
  1335         return lambdaExpressionOrStatementRest(params, pos);
  1338     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1339         if (token.kind != ARROW) {
  1340             //better error recovery
  1341             return F.at(pos).Erroneous(args);
  1344         checkLambda();
  1345         accept(ARROW);
  1347         return token.kind == LBRACE ?
  1348             lambdaStatement(args, pos, pos) :
  1349             lambdaExpression(args, pos);
  1352     JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
  1353         JCBlock block = block(pos2, 0);
  1354         return toP(F.at(pos).Lambda(args, block));
  1357     JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
  1358         JCTree expr = parseExpression();
  1359         return toP(F.at(pos).Lambda(args, expr));
  1362     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
  1363      */
  1364     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
  1365         nextToken();
  1366         if (token.kind == LPAREN || typeArgs != null) {
  1367             t = arguments(typeArgs, t);
  1368         } else if (token.kind == HASH) {
  1369             if (typeArgs != null) return illegal();
  1370             t = memberReferenceSuffix(t);
  1371         } else {
  1372             int pos = token.pos;
  1373             accept(DOT);
  1374             typeArgs = (token.kind == LT) ? typeArguments(false) : null;
  1375             t = toP(F.at(pos).Select(t, ident()));
  1376             t = argumentsOpt(typeArgs, t);
  1378         return t;
  1381     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
  1382      */
  1383     JCPrimitiveTypeTree basicType() {
  1384         JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
  1385         nextToken();
  1386         return t;
  1389     /** ArgumentsOpt = [ Arguments ]
  1390      */
  1391     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
  1392         if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
  1393             mode = EXPR;
  1394             return arguments(typeArgs, t);
  1395         } else {
  1396             return t;
  1400     /** Arguments = "(" [Expression { COMMA Expression }] ")"
  1401      */
  1402     List<JCExpression> arguments() {
  1403         ListBuffer<JCExpression> args = lb();
  1404         if (token.kind == LPAREN) {
  1405             nextToken();
  1406             if (token.kind != RPAREN) {
  1407                 args.append(parseExpression());
  1408                 while (token.kind == COMMA) {
  1409                     nextToken();
  1410                     args.append(parseExpression());
  1413             accept(RPAREN);
  1414         } else {
  1415             syntaxError(token.pos, "expected", LPAREN);
  1417         return args.toList();
  1420     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
  1421         int pos = token.pos;
  1422         List<JCExpression> args = arguments();
  1423         return toP(F.at(pos).Apply(typeArgs, t, args));
  1426     /**  TypeArgumentsOpt = [ TypeArguments ]
  1427      */
  1428     JCExpression typeArgumentsOpt(JCExpression t) {
  1429         if (token.kind == LT &&
  1430             (mode & TYPE) != 0 &&
  1431             (mode & NOPARAMS) == 0) {
  1432             mode = TYPE;
  1433             checkGenerics();
  1434             return typeArguments(t, false);
  1435         } else {
  1436             return t;
  1439     List<JCExpression> typeArgumentsOpt() {
  1440         return typeArgumentsOpt(TYPE);
  1443     List<JCExpression> typeArgumentsOpt(int useMode) {
  1444         if (token.kind == LT) {
  1445             checkGenerics();
  1446             if ((mode & useMode) == 0 ||
  1447                 (mode & NOPARAMS) != 0) {
  1448                 illegal();
  1450             mode = useMode;
  1451             return typeArguments(false);
  1453         return null;
  1456     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
  1457      */
  1458     List<JCExpression> typeArguments(boolean diamondAllowed) {
  1459         if (token.kind == LT) {
  1460             nextToken();
  1461             if (token.kind == GT && diamondAllowed) {
  1462                 checkDiamond();
  1463                 mode |= DIAMOND;
  1464                 nextToken();
  1465                 return List.nil();
  1466             } else {
  1467                 ListBuffer<JCExpression> args = ListBuffer.lb();
  1468                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1469                 while (token.kind == COMMA) {
  1470                     nextToken();
  1471                     args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
  1473                 switch (token.kind) {
  1475                 case GTGTGTEQ: case GTGTEQ: case GTEQ:
  1476                 case GTGTGT: case GTGT:
  1477                     token = S.split();
  1478                     break;
  1479                 case GT:
  1480                     nextToken();
  1481                     break;
  1482                 default:
  1483                     args.append(syntaxError(token.pos, "expected", GT));
  1484                     break;
  1486                 return args.toList();
  1488         } else {
  1489             return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
  1493     /** TypeArgument = Type
  1494      *               | "?"
  1495      *               | "?" EXTENDS Type {"&" Type}
  1496      *               | "?" SUPER Type
  1497      */
  1498     JCExpression typeArgument() {
  1499         if (token.kind != QUES) return parseType();
  1500         int pos = token.pos;
  1501         nextToken();
  1502         if (token.kind == EXTENDS) {
  1503             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
  1504             nextToken();
  1505             JCExpression bound = parseType();
  1506             return F.at(pos).Wildcard(t, bound);
  1507         } else if (token.kind == SUPER) {
  1508             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
  1509             nextToken();
  1510             JCExpression bound = parseType();
  1511             return F.at(pos).Wildcard(t, bound);
  1512         } else if (token.kind == IDENTIFIER) {
  1513             //error recovery
  1514             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
  1515             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
  1516             JCIdent id = toP(F.at(token.pos).Ident(ident()));
  1517             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
  1518             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
  1519             return err;
  1520         } else {
  1521             TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
  1522             return toP(F.at(pos).Wildcard(t, null));
  1526     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
  1527         int pos = token.pos;
  1528         List<JCExpression> args = typeArguments(diamondAllowed);
  1529         return toP(F.at(pos).TypeApply(t, args));
  1532     /** BracketsOpt = {"[" "]"}
  1533      */
  1534     private JCExpression bracketsOpt(JCExpression t) {
  1535         if (token.kind == LBRACKET) {
  1536             int pos = token.pos;
  1537             nextToken();
  1538             t = bracketsOptCont(t, pos);
  1539             F.at(pos);
  1541         return t;
  1544     private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
  1545         accept(RBRACKET);
  1546         t = bracketsOpt(t);
  1547         return toP(F.at(pos).TypeArray(t));
  1550     /** BracketsSuffixExpr = "." CLASS
  1551      *  BracketsSuffixType =
  1552      */
  1553     JCExpression bracketsSuffix(JCExpression t) {
  1554         if ((mode & EXPR) != 0 && token.kind == DOT) {
  1555             mode = EXPR;
  1556             int pos = token.pos;
  1557             nextToken();
  1558             accept(CLASS);
  1559             if (token.pos == endPosTable.errorEndPos) {
  1560                 // error recovery
  1561                 Name name = null;
  1562                 if (token.kind == IDENTIFIER) {
  1563                     name = token.name();
  1564                     nextToken();
  1565                 } else {
  1566                     name = names.error;
  1568                 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
  1569             } else {
  1570                 t = toP(F.at(pos).Select(t, names._class));
  1572         } else if ((mode & TYPE) != 0) {
  1573             mode = TYPE;
  1574         } else {
  1575             syntaxError(token.pos, "dot.class.expected");
  1577         return t;
  1580     /**
  1581      * MemberReferenceSuffix = "#" [TypeArguments] Ident
  1582      *                       | "#" [TypeArguments] "new"
  1583      */
  1584     JCExpression memberReferenceSuffix(JCExpression t) {
  1585         int pos1 = token.pos;
  1586         accept(HASH);
  1587         return memberReferenceSuffix(pos1, t);
  1590     JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
  1591         checkMethodReferences();
  1592         mode = EXPR;
  1593         List<JCExpression> typeArgs = null;
  1594         if (token.kind == LT) {
  1595             typeArgs = typeArguments(false);
  1597         Name refName = null;
  1598         ReferenceMode refMode = null;
  1599         if (token.kind == NEW) {
  1600             refMode = ReferenceMode.NEW;
  1601             refName = names.init;
  1602             nextToken();
  1603         } else {
  1604             refMode = ReferenceMode.INVOKE;
  1605             refName = ident();
  1607         return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
  1610     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
  1611      */
  1612     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
  1613         switch (token.kind) {
  1614         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
  1615         case DOUBLE: case BOOLEAN:
  1616             if (typeArgs == null)
  1617                 return arrayCreatorRest(newpos, basicType());
  1618             break;
  1619         default:
  1621         JCExpression t = qualident();
  1622         int oldmode = mode;
  1623         mode = TYPE;
  1624         boolean diamondFound = false;
  1625         int lastTypeargsPos = -1;
  1626         if (token.kind == LT) {
  1627             checkGenerics();
  1628             lastTypeargsPos = token.pos;
  1629             t = typeArguments(t, true);
  1630             diamondFound = (mode & DIAMOND) != 0;
  1632         while (token.kind == DOT) {
  1633             if (diamondFound) {
  1634                 //cannot select after a diamond
  1635                 illegal();
  1637             int pos = token.pos;
  1638             nextToken();
  1639             t = toP(F.at(pos).Select(t, ident()));
  1640             if (token.kind == LT) {
  1641                 lastTypeargsPos = token.pos;
  1642                 checkGenerics();
  1643                 t = typeArguments(t, true);
  1644                 diamondFound = (mode & DIAMOND) != 0;
  1647         mode = oldmode;
  1648         if (token.kind == LBRACKET) {
  1649             JCExpression e = arrayCreatorRest(newpos, t);
  1650             if (diamondFound) {
  1651                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
  1652                 return toP(F.at(newpos).Erroneous(List.of(e)));
  1654             else if (typeArgs != null) {
  1655                 int pos = newpos;
  1656                 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
  1657                     // note: this should always happen but we should
  1658                     // not rely on this as the parser is continuously
  1659                     // modified to improve error recovery.
  1660                     pos = typeArgs.head.pos;
  1662                 setErrorEndPos(S.prevToken().endPos);
  1663                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
  1664                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
  1665                 return toP(err);
  1667             return e;
  1668         } else if (token.kind == LPAREN) {
  1669             return classCreatorRest(newpos, null, typeArgs, t);
  1670         } else {
  1671             setErrorEndPos(token.pos);
  1672             reportSyntaxError(token.pos, "expected2", LPAREN, LBRACKET);
  1673             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
  1674             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
  1678     /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
  1679      */
  1680     JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
  1681         JCExpression t = toP(F.at(token.pos).Ident(ident()));
  1682         if (token.kind == LT) {
  1683             int oldmode = mode;
  1684             checkGenerics();
  1685             t = typeArguments(t, true);
  1686             mode = oldmode;
  1688         return classCreatorRest(newpos, encl, typeArgs, t);
  1691     /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
  1692      *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
  1693      */
  1694     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
  1695         accept(LBRACKET);
  1696         if (token.kind == RBRACKET) {
  1697             accept(RBRACKET);
  1698             elemtype = bracketsOpt(elemtype);
  1699             if (token.kind == LBRACE) {
  1700                 return arrayInitializer(newpos, elemtype);
  1701             } else {
  1702                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
  1703                 return syntaxError(token.pos, List.<JCTree>of(t), "array.dimension.missing");
  1705         } else {
  1706             ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
  1707             dims.append(parseExpression());
  1708             accept(RBRACKET);
  1709             while (token.kind == LBRACKET) {
  1710                 int pos = token.pos;
  1711                 nextToken();
  1712                 if (token.kind == RBRACKET) {
  1713                     elemtype = bracketsOptCont(elemtype, pos);
  1714                 } else {
  1715                     dims.append(parseExpression());
  1716                     accept(RBRACKET);
  1719             return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
  1723     /** ClassCreatorRest = Arguments [ClassBody]
  1724      */
  1725     JCNewClass classCreatorRest(int newpos,
  1726                                   JCExpression encl,
  1727                                   List<JCExpression> typeArgs,
  1728                                   JCExpression t)
  1730         List<JCExpression> args = arguments();
  1731         JCClassDecl body = null;
  1732         if (token.kind == LBRACE) {
  1733             int pos = token.pos;
  1734             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  1735             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1736             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
  1738         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
  1741     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
  1742      */
  1743     JCExpression arrayInitializer(int newpos, JCExpression t) {
  1744         accept(LBRACE);
  1745         ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
  1746         if (token.kind == COMMA) {
  1747             nextToken();
  1748         } else if (token.kind != RBRACE) {
  1749             elems.append(variableInitializer());
  1750             while (token.kind == COMMA) {
  1751                 nextToken();
  1752                 if (token.kind == RBRACE) break;
  1753                 elems.append(variableInitializer());
  1756         accept(RBRACE);
  1757         return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
  1760     /** VariableInitializer = ArrayInitializer | Expression
  1761      */
  1762     public JCExpression variableInitializer() {
  1763         return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
  1766     /** ParExpression = "(" Expression ")"
  1767      */
  1768     JCExpression parExpression() {
  1769         int pos = token.pos;
  1770         accept(LPAREN);
  1771         JCExpression t = parseExpression();
  1772         accept(RPAREN);
  1773         return toP(F.at(pos).Parens(t));
  1776     /** Block = "{" BlockStatements "}"
  1777      */
  1778     JCBlock block(int pos, long flags) {
  1779         accept(LBRACE);
  1780         List<JCStatement> stats = blockStatements();
  1781         JCBlock t = F.at(pos).Block(flags, stats);
  1782         while (token.kind == CASE || token.kind == DEFAULT) {
  1783             syntaxError("orphaned", token.kind);
  1784             switchBlockStatementGroups();
  1786         // the Block node has a field "endpos" for first char of last token, which is
  1787         // usually but not necessarily the last char of the last token.
  1788         t.endpos = token.pos;
  1789         accept(RBRACE);
  1790         return toP(t);
  1793     public JCBlock block() {
  1794         return block(token.pos, 0);
  1797     /** BlockStatements = { BlockStatement }
  1798      *  BlockStatement  = LocalVariableDeclarationStatement
  1799      *                  | ClassOrInterfaceOrEnumDeclaration
  1800      *                  | [Ident ":"] Statement
  1801      *  LocalVariableDeclarationStatement
  1802      *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
  1803      */
  1804     @SuppressWarnings("fallthrough")
  1805     List<JCStatement> blockStatements() {
  1806         //todo: skip to anchor on error(?)
  1807         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
  1808         while (true) {
  1809             List<JCStatement> stat = blockStatement();
  1810             if (stat.isEmpty()) {
  1811                 return stats.toList();
  1812             } else {
  1813                 if (token.pos <= endPosTable.errorEndPos) {
  1814                     skip(false, true, true, true);
  1816                 stats.addAll(stat);
  1821     /*
  1822      * This method parses a statement treating it as a block, relaxing the
  1823      * JLS restrictions, allows us to parse more faulty code, doing so
  1824      * enables us to provide better and accurate diagnostics to the user.
  1825      */
  1826     JCStatement parseStatementAsBlock() {
  1827         int pos = token.pos;
  1828         List<JCStatement> stats = blockStatement();
  1829         if (stats.isEmpty()) {
  1830             JCErroneous e = F.at(pos).Erroneous();
  1831             error(e, "illegal.start.of.stmt");
  1832             return F.at(pos).Exec(e);
  1833         } else {
  1834             JCStatement first = stats.head;
  1835             String error = null;
  1836             switch (first.getTag()) {
  1837             case CLASSDEF:
  1838                 error = "class.not.allowed";
  1839                 break;
  1840             case VARDEF:
  1841                 error = "variable.not.allowed";
  1842                 break;
  1844             if (error != null) {
  1845                 error(first, error);
  1846                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
  1847                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
  1849             return first;
  1853     @SuppressWarnings("fallthrough")
  1854     List<JCStatement> blockStatement() {
  1855         //todo: skip to anchor on error(?)
  1856         int pos = token.pos;
  1857         switch (token.kind) {
  1858         case RBRACE: case CASE: case DEFAULT: case EOF:
  1859             return List.nil();
  1860         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
  1861         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
  1862         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
  1863             return List.of(parseStatement());
  1864         case MONKEYS_AT:
  1865         case FINAL: {
  1866             Comment dc = token.comment(CommentStyle.JAVADOC);
  1867             JCModifiers mods = modifiersOpt();
  1868             if (token.kind == INTERFACE ||
  1869                 token.kind == CLASS ||
  1870                 allowEnums && token.kind == ENUM) {
  1871                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1872             } else {
  1873                 JCExpression t = parseType();
  1874                 ListBuffer<JCStatement> stats =
  1875                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1876                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1877                 storeEnd(stats.elems.last(), token.endPos);
  1878                 accept(SEMI);
  1879                 return stats.toList();
  1882         case ABSTRACT: case STRICTFP: {
  1883             Comment dc = token.comment(CommentStyle.JAVADOC);
  1884             JCModifiers mods = modifiersOpt();
  1885             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
  1887         case INTERFACE:
  1888         case CLASS:
  1889             Comment dc = token.comment(CommentStyle.JAVADOC);
  1890             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1891         case ENUM:
  1892         case ASSERT:
  1893             if (allowEnums && token.kind == ENUM) {
  1894                 error(token.pos, "local.enum");
  1895                 dc = token.comment(CommentStyle.JAVADOC);
  1896                 return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
  1897             } else if (allowAsserts && token.kind == ASSERT) {
  1898                 return List.of(parseStatement());
  1900             /* fall through to default */
  1901         default:
  1902             Token prevToken = token;
  1903             JCExpression t = term(EXPR | TYPE);
  1904             if (token.kind == COLON && t.hasTag(IDENT)) {
  1905                 nextToken();
  1906                 JCStatement stat = parseStatement();
  1907                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
  1908             } else if ((lastmode & TYPE) != 0 &&
  1909                        (token.kind == IDENTIFIER ||
  1910                         token.kind == ASSERT ||
  1911                         token.kind == ENUM)) {
  1912                 pos = token.pos;
  1913                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
  1914                 F.at(pos);
  1915                 ListBuffer<JCStatement> stats =
  1916                         variableDeclarators(mods, t, new ListBuffer<JCStatement>());
  1917                 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
  1918                 storeEnd(stats.elems.last(), token.endPos);
  1919                 accept(SEMI);
  1920                 return stats.toList();
  1921             } else {
  1922                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  1923                 JCExpressionStatement expr = to(F.at(pos).Exec(checkExprStat(t)));
  1924                 accept(SEMI);
  1925                 return List.<JCStatement>of(expr);
  1930     /** Statement =
  1931      *       Block
  1932      *     | IF ParExpression Statement [ELSE Statement]
  1933      *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
  1934      *     | FOR "(" FormalParameter : Expression ")" Statement
  1935      *     | WHILE ParExpression Statement
  1936      *     | DO Statement WHILE ParExpression ";"
  1937      *     | TRY Block ( Catches | [Catches] FinallyPart )
  1938      *     | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
  1939      *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
  1940      *     | SYNCHRONIZED ParExpression Block
  1941      *     | RETURN [Expression] ";"
  1942      *     | THROW Expression ";"
  1943      *     | BREAK [Ident] ";"
  1944      *     | CONTINUE [Ident] ";"
  1945      *     | ASSERT Expression [ ":" Expression ] ";"
  1946      *     | ";"
  1947      *     | ExpressionStatement
  1948      *     | Ident ":" Statement
  1949      */
  1950     @SuppressWarnings("fallthrough")
  1951     public JCStatement parseStatement() {
  1952         int pos = token.pos;
  1953         switch (token.kind) {
  1954         case LBRACE:
  1955             return block();
  1956         case IF: {
  1957             nextToken();
  1958             JCExpression cond = parExpression();
  1959             JCStatement thenpart = parseStatementAsBlock();
  1960             JCStatement elsepart = null;
  1961             if (token.kind == ELSE) {
  1962                 nextToken();
  1963                 elsepart = parseStatementAsBlock();
  1965             return F.at(pos).If(cond, thenpart, elsepart);
  1967         case FOR: {
  1968             nextToken();
  1969             accept(LPAREN);
  1970             List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
  1971             if (inits.length() == 1 &&
  1972                 inits.head.hasTag(VARDEF) &&
  1973                 ((JCVariableDecl) inits.head).init == null &&
  1974                 token.kind == COLON) {
  1975                 checkForeach();
  1976                 JCVariableDecl var = (JCVariableDecl)inits.head;
  1977                 accept(COLON);
  1978                 JCExpression expr = parseExpression();
  1979                 accept(RPAREN);
  1980                 JCStatement body = parseStatementAsBlock();
  1981                 return F.at(pos).ForeachLoop(var, expr, body);
  1982             } else {
  1983                 accept(SEMI);
  1984                 JCExpression cond = token.kind == SEMI ? null : parseExpression();
  1985                 accept(SEMI);
  1986                 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
  1987                 accept(RPAREN);
  1988                 JCStatement body = parseStatementAsBlock();
  1989                 return F.at(pos).ForLoop(inits, cond, steps, body);
  1992         case WHILE: {
  1993             nextToken();
  1994             JCExpression cond = parExpression();
  1995             JCStatement body = parseStatementAsBlock();
  1996             return F.at(pos).WhileLoop(cond, body);
  1998         case DO: {
  1999             nextToken();
  2000             JCStatement body = parseStatementAsBlock();
  2001             accept(WHILE);
  2002             JCExpression cond = parExpression();
  2003             JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
  2004             accept(SEMI);
  2005             return t;
  2007         case TRY: {
  2008             nextToken();
  2009             List<JCTree> resources = List.<JCTree>nil();
  2010             if (token.kind == LPAREN) {
  2011                 checkTryWithResources();
  2012                 nextToken();
  2013                 resources = resources();
  2014                 accept(RPAREN);
  2016             JCBlock body = block();
  2017             ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
  2018             JCBlock finalizer = null;
  2019             if (token.kind == CATCH || token.kind == FINALLY) {
  2020                 while (token.kind == CATCH) catchers.append(catchClause());
  2021                 if (token.kind == FINALLY) {
  2022                     nextToken();
  2023                     finalizer = block();
  2025             } else {
  2026                 if (allowTWR) {
  2027                     if (resources.isEmpty())
  2028                         error(pos, "try.without.catch.finally.or.resource.decls");
  2029                 } else
  2030                     error(pos, "try.without.catch.or.finally");
  2032             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
  2034         case SWITCH: {
  2035             nextToken();
  2036             JCExpression selector = parExpression();
  2037             accept(LBRACE);
  2038             List<JCCase> cases = switchBlockStatementGroups();
  2039             JCSwitch t = to(F.at(pos).Switch(selector, cases));
  2040             accept(RBRACE);
  2041             return t;
  2043         case SYNCHRONIZED: {
  2044             nextToken();
  2045             JCExpression lock = parExpression();
  2046             JCBlock body = block();
  2047             return F.at(pos).Synchronized(lock, body);
  2049         case RETURN: {
  2050             nextToken();
  2051             JCExpression result = token.kind == SEMI ? null : parseExpression();
  2052             JCReturn t = to(F.at(pos).Return(result));
  2053             accept(SEMI);
  2054             return t;
  2056         case THROW: {
  2057             nextToken();
  2058             JCExpression exc = parseExpression();
  2059             JCThrow t = to(F.at(pos).Throw(exc));
  2060             accept(SEMI);
  2061             return t;
  2063         case BREAK: {
  2064             nextToken();
  2065             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2066             JCBreak t = to(F.at(pos).Break(label));
  2067             accept(SEMI);
  2068             return t;
  2070         case CONTINUE: {
  2071             nextToken();
  2072             Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
  2073             JCContinue t =  to(F.at(pos).Continue(label));
  2074             accept(SEMI);
  2075             return t;
  2077         case SEMI:
  2078             nextToken();
  2079             return toP(F.at(pos).Skip());
  2080         case ELSE:
  2081             return toP(F.Exec(syntaxError("else.without.if")));
  2082         case FINALLY:
  2083             return toP(F.Exec(syntaxError("finally.without.try")));
  2084         case CATCH:
  2085             return toP(F.Exec(syntaxError("catch.without.try")));
  2086         case ASSERT: {
  2087             if (allowAsserts && token.kind == ASSERT) {
  2088                 nextToken();
  2089                 JCExpression assertion = parseExpression();
  2090                 JCExpression message = null;
  2091                 if (token.kind == COLON) {
  2092                     nextToken();
  2093                     message = parseExpression();
  2095                 JCAssert t = to(F.at(pos).Assert(assertion, message));
  2096                 accept(SEMI);
  2097                 return t;
  2099             /* else fall through to default case */
  2101         case ENUM:
  2102         default:
  2103             Token prevToken = token;
  2104             JCExpression expr = parseExpression();
  2105             if (token.kind == COLON && expr.hasTag(IDENT)) {
  2106                 nextToken();
  2107                 JCStatement stat = parseStatement();
  2108                 return F.at(pos).Labelled(prevToken.name(), stat);
  2109             } else {
  2110                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
  2111                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
  2112                 accept(SEMI);
  2113                 return stat;
  2118     /** CatchClause     = CATCH "(" FormalParameter ")" Block
  2119      */
  2120     protected JCCatch catchClause() {
  2121         int pos = token.pos;
  2122         accept(CATCH);
  2123         accept(LPAREN);
  2124         JCModifiers mods = optFinal(Flags.PARAMETER);
  2125         List<JCExpression> catchTypes = catchTypes();
  2126         JCExpression paramType = catchTypes.size() > 1 ?
  2127                 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
  2128                 catchTypes.head;
  2129         JCVariableDecl formal = variableDeclaratorId(mods, paramType);
  2130         accept(RPAREN);
  2131         JCBlock body = block();
  2132         return F.at(pos).Catch(formal, body);
  2135     List<JCExpression> catchTypes() {
  2136         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
  2137         catchTypes.add(parseType());
  2138         while (token.kind == BAR) {
  2139             checkMulticatch();
  2140             nextToken();
  2141             catchTypes.add(qualident());
  2143         return catchTypes.toList();
  2146     /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
  2147      *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
  2148      *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
  2149      */
  2150     List<JCCase> switchBlockStatementGroups() {
  2151         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
  2152         while (true) {
  2153             int pos = token.pos;
  2154             switch (token.kind) {
  2155             case CASE: {
  2156                 nextToken();
  2157                 JCExpression pat = parseExpression();
  2158                 accept(COLON);
  2159                 List<JCStatement> stats = blockStatements();
  2160                 JCCase c = F.at(pos).Case(pat, stats);
  2161                 if (stats.isEmpty())
  2162                     storeEnd(c, S.prevToken().endPos);
  2163                 cases.append(c);
  2164                 break;
  2166             case DEFAULT: {
  2167                 nextToken();
  2168                 accept(COLON);
  2169                 List<JCStatement> stats = blockStatements();
  2170                 JCCase c = F.at(pos).Case(null, stats);
  2171                 if (stats.isEmpty())
  2172                     storeEnd(c, S.prevToken().endPos);
  2173                 cases.append(c);
  2174                 break;
  2176             case RBRACE: case EOF:
  2177                 return cases.toList();
  2178             default:
  2179                 nextToken(); // to ensure progress
  2180                 syntaxError(pos, "expected3",
  2181                     CASE, DEFAULT, RBRACE);
  2186     /** MoreStatementExpressions = { COMMA StatementExpression }
  2187      */
  2188     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
  2189                                                                     JCExpression first,
  2190                                                                     T stats) {
  2191         // This Exec is a "StatementExpression"; it subsumes no terminating token
  2192         stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
  2193         while (token.kind == COMMA) {
  2194             nextToken();
  2195             pos = token.pos;
  2196             JCExpression t = parseExpression();
  2197             // This Exec is a "StatementExpression"; it subsumes no terminating token
  2198             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
  2200         return stats;
  2203     /** ForInit = StatementExpression MoreStatementExpressions
  2204      *           |  { FINAL | '@' Annotation } Type VariableDeclarators
  2205      */
  2206     List<JCStatement> forInit() {
  2207         ListBuffer<JCStatement> stats = lb();
  2208         int pos = token.pos;
  2209         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
  2210             return variableDeclarators(optFinal(0), parseType(), stats).toList();
  2211         } else {
  2212             JCExpression t = term(EXPR | TYPE);
  2213             if ((lastmode & TYPE) != 0 &&
  2214                 (token.kind == IDENTIFIER || token.kind == ASSERT ||
  2215                  token.kind == ENUM)) {
  2216                 return variableDeclarators(modifiersOpt(), t, stats).toList();
  2217             } else if ((lastmode & TYPE) != 0 && token.kind == COLON) {
  2218                 error(pos, "bad.initializer", "for-loop");
  2219                 return List.of((JCStatement)F.at(pos).VarDef(null, null, t, null));
  2220             } else {
  2221                 return moreStatementExpressions(pos, t, stats).toList();
  2226     /** ForUpdate = StatementExpression MoreStatementExpressions
  2227      */
  2228     List<JCExpressionStatement> forUpdate() {
  2229         return moreStatementExpressions(token.pos,
  2230                                         parseExpression(),
  2231                                         new ListBuffer<JCExpressionStatement>()).toList();
  2234     /** AnnotationsOpt = { '@' Annotation }
  2235      */
  2236     List<JCAnnotation> annotationsOpt() {
  2237         if (token.kind != MONKEYS_AT) return List.nil(); // optimization
  2238         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
  2239         while (token.kind == MONKEYS_AT) {
  2240             int pos = token.pos;
  2241             nextToken();
  2242             buf.append(annotation(pos));
  2244         return buf.toList();
  2247     /** ModifiersOpt = { Modifier }
  2248      *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
  2249      *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
  2250      *           | "@" Annotation
  2251      */
  2252     JCModifiers modifiersOpt() {
  2253         return modifiersOpt(null);
  2255     protected JCModifiers modifiersOpt(JCModifiers partial) {
  2256         long flags;
  2257         ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
  2258         int pos;
  2259         if (partial == null) {
  2260             flags = 0;
  2261             pos = token.pos;
  2262         } else {
  2263             flags = partial.flags;
  2264             annotations.appendList(partial.annotations);
  2265             pos = partial.pos;
  2267         if (token.deprecatedFlag()) {
  2268             flags |= Flags.DEPRECATED;
  2270         int lastPos = Position.NOPOS;
  2271     loop:
  2272         while (true) {
  2273             long flag;
  2274             switch (token.kind) {
  2275             case PRIVATE     : flag = Flags.PRIVATE; break;
  2276             case PROTECTED   : flag = Flags.PROTECTED; break;
  2277             case PUBLIC      : flag = Flags.PUBLIC; break;
  2278             case STATIC      : flag = Flags.STATIC; break;
  2279             case TRANSIENT   : flag = Flags.TRANSIENT; break;
  2280             case FINAL       : flag = Flags.FINAL; break;
  2281             case ABSTRACT    : flag = Flags.ABSTRACT; break;
  2282             case NATIVE      : flag = Flags.NATIVE; break;
  2283             case VOLATILE    : flag = Flags.VOLATILE; break;
  2284             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
  2285             case STRICTFP    : flag = Flags.STRICTFP; break;
  2286             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
  2287             case ERROR       : flag = 0; nextToken(); break;
  2288             default: break loop;
  2290             if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
  2291             lastPos = token.pos;
  2292             nextToken();
  2293             if (flag == Flags.ANNOTATION) {
  2294                 checkAnnotations();
  2295                 if (token.kind != INTERFACE) {
  2296                     JCAnnotation ann = annotation(lastPos);
  2297                     // if first modifier is an annotation, set pos to annotation's.
  2298                     if (flags == 0 && annotations.isEmpty())
  2299                         pos = ann.pos;
  2300                     annotations.append(ann);
  2301                     lastPos = ann.pos;
  2302                     flag = 0;
  2305             flags |= flag;
  2307         switch (token.kind) {
  2308         case ENUM: flags |= Flags.ENUM; break;
  2309         case INTERFACE: flags |= Flags.INTERFACE; break;
  2310         default: break;
  2313         /* A modifiers tree with no modifier tokens or annotations
  2314          * has no text position. */
  2315         if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
  2316             pos = Position.NOPOS;
  2318         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
  2319         if (pos != Position.NOPOS)
  2320             storeEnd(mods, S.prevToken().endPos);
  2321         return mods;
  2324     /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
  2325      * @param pos position of "@" token
  2326      */
  2327     JCAnnotation annotation(int pos) {
  2328         // accept(AT); // AT consumed by caller
  2329         checkAnnotations();
  2330         JCTree ident = qualident();
  2331         List<JCExpression> fieldValues = annotationFieldValuesOpt();
  2332         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
  2333         storeEnd(ann, S.prevToken().endPos);
  2334         return ann;
  2337     List<JCExpression> annotationFieldValuesOpt() {
  2338         return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
  2341     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
  2342     List<JCExpression> annotationFieldValues() {
  2343         accept(LPAREN);
  2344         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2345         if (token.kind != RPAREN) {
  2346             buf.append(annotationFieldValue());
  2347             while (token.kind == COMMA) {
  2348                 nextToken();
  2349                 buf.append(annotationFieldValue());
  2352         accept(RPAREN);
  2353         return buf.toList();
  2356     /** AnnotationFieldValue    = AnnotationValue
  2357      *                          | Identifier "=" AnnotationValue
  2358      */
  2359     JCExpression annotationFieldValue() {
  2360         if (token.kind == IDENTIFIER) {
  2361             mode = EXPR;
  2362             JCExpression t1 = term1();
  2363             if (t1.hasTag(IDENT) && token.kind == EQ) {
  2364                 int pos = token.pos;
  2365                 accept(EQ);
  2366                 JCExpression v = annotationValue();
  2367                 return toP(F.at(pos).Assign(t1, v));
  2368             } else {
  2369                 return t1;
  2372         return annotationValue();
  2375     /* AnnotationValue          = ConditionalExpression
  2376      *                          | Annotation
  2377      *                          | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
  2378      */
  2379     JCExpression annotationValue() {
  2380         int pos;
  2381         switch (token.kind) {
  2382         case MONKEYS_AT:
  2383             pos = token.pos;
  2384             nextToken();
  2385             return annotation(pos);
  2386         case LBRACE:
  2387             pos = token.pos;
  2388             accept(LBRACE);
  2389             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
  2390             if (token.kind != RBRACE) {
  2391                 buf.append(annotationValue());
  2392                 while (token.kind == COMMA) {
  2393                     nextToken();
  2394                     if (token.kind == RBRACE) break;
  2395                     buf.append(annotationValue());
  2398             accept(RBRACE);
  2399             return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
  2400         default:
  2401             mode = EXPR;
  2402             return term1();
  2406     /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
  2407      */
  2408     public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
  2409                                                                          JCExpression type,
  2410                                                                          T vdefs)
  2412         return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
  2415     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
  2416      *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
  2418      *  @param reqInit  Is an initializer always required?
  2419      *  @param dc       The documentation comment for the variable declarations, or null.
  2420      */
  2421     <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
  2422                                                                      JCModifiers mods,
  2423                                                                      JCExpression type,
  2424                                                                      Name name,
  2425                                                                      boolean reqInit,
  2426                                                                      Comment dc,
  2427                                                                      T vdefs)
  2429         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
  2430         while (token.kind == COMMA) {
  2431             // All but last of multiple declarators subsume a comma
  2432             storeEnd((JCTree)vdefs.elems.last(), token.endPos);
  2433             nextToken();
  2434             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
  2436         return vdefs;
  2439     /** VariableDeclarator = Ident VariableDeclaratorRest
  2440      *  ConstantDeclarator = Ident ConstantDeclaratorRest
  2441      */
  2442     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc) {
  2443         return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
  2446     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
  2447      *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
  2449      *  @param reqInit  Is an initializer always required?
  2450      *  @param dc       The documentation comment for the variable declarations, or null.
  2451      */
  2452     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
  2453                                   boolean reqInit, Comment dc) {
  2454         type = bracketsOpt(type);
  2455         JCExpression init = null;
  2456         if (token.kind == EQ) {
  2457             nextToken();
  2458             init = variableInitializer();
  2460         else if (reqInit) syntaxError(token.pos, "expected", EQ);
  2461         JCVariableDecl result =
  2462             toP(F.at(pos).VarDef(mods, name, type, init));
  2463         attach(result, dc);
  2464         return result;
  2467     /** VariableDeclaratorId = Ident BracketsOpt
  2468      */
  2469     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
  2470         int pos = token.pos;
  2471         Name name = ident();
  2472         if ((mods.flags & Flags.VARARGS) != 0 &&
  2473                 token.kind == LBRACKET) {
  2474             log.error(token.pos, "varargs.and.old.array.syntax");
  2476         type = bracketsOpt(type);
  2477         return toP(F.at(pos).VarDef(mods, name, type, null));
  2480     /** Resources = Resource { ";" Resources }
  2481      */
  2482     List<JCTree> resources() {
  2483         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2484         defs.append(resource());
  2485         while (token.kind == SEMI) {
  2486             // All but last of multiple declarators must subsume a semicolon
  2487             storeEnd(defs.elems.last(), token.endPos);
  2488             int semiColonPos = token.pos;
  2489             nextToken();
  2490             if (token.kind == RPAREN) { // Optional trailing semicolon
  2491                                        // after last resource
  2492                 break;
  2494             defs.append(resource());
  2496         return defs.toList();
  2499     /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
  2500      */
  2501     protected JCTree resource() {
  2502         JCModifiers optFinal = optFinal(Flags.FINAL);
  2503         JCExpression type = parseType();
  2504         int pos = token.pos;
  2505         Name ident = ident();
  2506         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
  2509     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
  2510      */
  2511     public JCTree.JCCompilationUnit parseCompilationUnit() {
  2512         Token firstToken = token;
  2513         JCExpression pid = null;
  2514         JCModifiers mods = null;
  2515         boolean consumedToplevelDoc = false;
  2516         boolean seenImport = false;
  2517         boolean seenPackage = false;
  2518         List<JCAnnotation> packageAnnotations = List.nil();
  2519         if (token.kind == MONKEYS_AT)
  2520             mods = modifiersOpt();
  2522         if (token.kind == PACKAGE) {
  2523             seenPackage = true;
  2524             if (mods != null) {
  2525                 checkNoMods(mods.flags);
  2526                 packageAnnotations = mods.annotations;
  2527                 mods = null;
  2529             nextToken();
  2530             pid = qualident();
  2531             accept(SEMI);
  2533         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2534         boolean checkForImports = true;
  2535         boolean firstTypeDecl = true;
  2536         while (token.kind != EOF) {
  2537             if (token.pos <= endPosTable.errorEndPos) {
  2538                 // error recovery
  2539                 skip(checkForImports, false, false, false);
  2540                 if (token.kind == EOF)
  2541                     break;
  2543             if (checkForImports && mods == null && token.kind == IMPORT) {
  2544                 seenImport = true;
  2545                 defs.append(importDeclaration());
  2546             } else {
  2547                 Comment docComment = token.comment(CommentStyle.JAVADOC);
  2548                 if (firstTypeDecl && !seenImport && !seenPackage) {
  2549                     docComment = firstToken.comment(CommentStyle.JAVADOC);
  2550                     consumedToplevelDoc = true;
  2552                 JCTree def = typeDeclaration(mods, docComment);
  2553                 if (def instanceof JCExpressionStatement)
  2554                     def = ((JCExpressionStatement)def).expr;
  2555                 defs.append(def);
  2556                 if (def instanceof JCClassDecl)
  2557                     checkForImports = false;
  2558                 mods = null;
  2559                 firstTypeDecl = false;
  2562         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
  2563         if (!consumedToplevelDoc)
  2564             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
  2565         if (defs.elems.isEmpty())
  2566             storeEnd(toplevel, S.prevToken().endPos);
  2567         if (keepDocComments)
  2568             toplevel.docComments = docComments;
  2569         if (keepLineMap)
  2570             toplevel.lineMap = S.getLineMap();
  2571         toplevel.endPositions = this.endPosTable;
  2572         return toplevel;
  2575     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
  2576      */
  2577     JCTree importDeclaration() {
  2578         int pos = token.pos;
  2579         nextToken();
  2580         boolean importStatic = false;
  2581         if (token.kind == STATIC) {
  2582             checkStaticImports();
  2583             importStatic = true;
  2584             nextToken();
  2586         JCExpression pid = toP(F.at(token.pos).Ident(ident()));
  2587         do {
  2588             int pos1 = token.pos;
  2589             accept(DOT);
  2590             if (token.kind == STAR) {
  2591                 pid = to(F.at(pos1).Select(pid, names.asterisk));
  2592                 nextToken();
  2593                 break;
  2594             } else {
  2595                 pid = toP(F.at(pos1).Select(pid, ident()));
  2597         } while (token.kind == DOT);
  2598         accept(SEMI);
  2599         return toP(F.at(pos).Import(pid, importStatic));
  2602     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
  2603      *                  | ";"
  2604      */
  2605     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
  2606         int pos = token.pos;
  2607         if (mods == null && token.kind == SEMI) {
  2608             nextToken();
  2609             return toP(F.at(pos).Skip());
  2610         } else {
  2611             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
  2615     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
  2616      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
  2617      *  @param mods     Any modifiers starting the class or interface declaration
  2618      *  @param dc       The documentation comment for the class, or null.
  2619      */
  2620     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
  2621         if (token.kind == CLASS) {
  2622             return classDeclaration(mods, dc);
  2623         } else if (token.kind == INTERFACE) {
  2624             return interfaceDeclaration(mods, dc);
  2625         } else if (allowEnums) {
  2626             if (token.kind == ENUM) {
  2627                 return enumDeclaration(mods, dc);
  2628             } else {
  2629                 int pos = token.pos;
  2630                 List<JCTree> errs;
  2631                 if (token.kind == IDENTIFIER) {
  2632                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2633                     setErrorEndPos(token.pos);
  2634                 } else {
  2635                     errs = List.<JCTree>of(mods);
  2637                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
  2638                                               CLASS, INTERFACE, ENUM)));
  2640         } else {
  2641             if (token.kind == ENUM) {
  2642                 error(token.pos, "enums.not.supported.in.source", source.name);
  2643                 allowEnums = true;
  2644                 return enumDeclaration(mods, dc);
  2646             int pos = token.pos;
  2647             List<JCTree> errs;
  2648             if (token.kind == IDENTIFIER) {
  2649                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
  2650                 setErrorEndPos(token.pos);
  2651             } else {
  2652                 errs = List.<JCTree>of(mods);
  2654             return toP(F.Exec(syntaxError(pos, errs, "expected2",
  2655                                           CLASS, INTERFACE)));
  2659     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
  2660      *                     [IMPLEMENTS TypeList] ClassBody
  2661      *  @param mods    The modifiers starting the class declaration
  2662      *  @param dc       The documentation comment for the class, or null.
  2663      */
  2664     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
  2665         int pos = token.pos;
  2666         accept(CLASS);
  2667         Name name = ident();
  2669         List<JCTypeParameter> typarams = typeParametersOpt();
  2671         JCExpression extending = null;
  2672         if (token.kind == EXTENDS) {
  2673             nextToken();
  2674             extending = parseType();
  2676         List<JCExpression> implementing = List.nil();
  2677         if (token.kind == IMPLEMENTS) {
  2678             nextToken();
  2679             implementing = typeList();
  2681         List<JCTree> defs = classOrInterfaceBody(name, false);
  2682         JCClassDecl result = toP(F.at(pos).ClassDef(
  2683             mods, name, typarams, extending, implementing, defs));
  2684         attach(result, dc);
  2685         return result;
  2688     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
  2689      *                         [EXTENDS TypeList] InterfaceBody
  2690      *  @param mods    The modifiers starting the interface declaration
  2691      *  @param dc       The documentation comment for the interface, or null.
  2692      */
  2693     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
  2694         int pos = token.pos;
  2695         accept(INTERFACE);
  2696         Name name = ident();
  2698         List<JCTypeParameter> typarams = typeParametersOpt();
  2700         List<JCExpression> extending = List.nil();
  2701         if (token.kind == EXTENDS) {
  2702             nextToken();
  2703             extending = typeList();
  2705         List<JCTree> defs = classOrInterfaceBody(name, true);
  2706         JCClassDecl result = toP(F.at(pos).ClassDef(
  2707             mods, name, typarams, null, extending, defs));
  2708         attach(result, dc);
  2709         return result;
  2712     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
  2713      *  @param mods    The modifiers starting the enum declaration
  2714      *  @param dc       The documentation comment for the enum, or null.
  2715      */
  2716     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
  2717         int pos = token.pos;
  2718         accept(ENUM);
  2719         Name name = ident();
  2721         List<JCExpression> implementing = List.nil();
  2722         if (token.kind == IMPLEMENTS) {
  2723             nextToken();
  2724             implementing = typeList();
  2727         List<JCTree> defs = enumBody(name);
  2728         mods.flags |= Flags.ENUM;
  2729         JCClassDecl result = toP(F.at(pos).
  2730             ClassDef(mods, name, List.<JCTypeParameter>nil(),
  2731                 null, implementing, defs));
  2732         attach(result, dc);
  2733         return result;
  2736     /** EnumBody = "{" { EnumeratorDeclarationList } [","]
  2737      *                  [ ";" {ClassBodyDeclaration} ] "}"
  2738      */
  2739     List<JCTree> enumBody(Name enumName) {
  2740         accept(LBRACE);
  2741         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2742         if (token.kind == COMMA) {
  2743             nextToken();
  2744         } else if (token.kind != RBRACE && token.kind != SEMI) {
  2745             defs.append(enumeratorDeclaration(enumName));
  2746             while (token.kind == COMMA) {
  2747                 nextToken();
  2748                 if (token.kind == RBRACE || token.kind == SEMI) break;
  2749                 defs.append(enumeratorDeclaration(enumName));
  2751             if (token.kind != SEMI && token.kind != RBRACE) {
  2752                 defs.append(syntaxError(token.pos, "expected3",
  2753                                 COMMA, RBRACE, SEMI));
  2754                 nextToken();
  2757         if (token.kind == SEMI) {
  2758             nextToken();
  2759             while (token.kind != RBRACE && token.kind != EOF) {
  2760                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
  2761                                                                 false));
  2762                 if (token.pos <= endPosTable.errorEndPos) {
  2763                     // error recovery
  2764                    skip(false, true, true, false);
  2768         accept(RBRACE);
  2769         return defs.toList();
  2772     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
  2773      */
  2774     JCTree enumeratorDeclaration(Name enumName) {
  2775         Comment dc = token.comment(CommentStyle.JAVADOC);
  2776         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
  2777         if (token.deprecatedFlag()) {
  2778             flags |= Flags.DEPRECATED;
  2780         int pos = token.pos;
  2781         List<JCAnnotation> annotations = annotationsOpt();
  2782         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
  2783         List<JCExpression> typeArgs = typeArgumentsOpt();
  2784         int identPos = token.pos;
  2785         Name name = ident();
  2786         int createPos = token.pos;
  2787         List<JCExpression> args = (token.kind == LPAREN)
  2788             ? arguments() : List.<JCExpression>nil();
  2789         JCClassDecl body = null;
  2790         if (token.kind == LBRACE) {
  2791             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
  2792             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
  2793             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
  2795         if (args.isEmpty() && body == null)
  2796             createPos = identPos;
  2797         JCIdent ident = F.at(identPos).Ident(enumName);
  2798         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
  2799         if (createPos != identPos)
  2800             storeEnd(create, S.prevToken().endPos);
  2801         ident = F.at(identPos).Ident(enumName);
  2802         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
  2803         attach(result, dc);
  2804         return result;
  2807     /** TypeList = Type {"," Type}
  2808      */
  2809     List<JCExpression> typeList() {
  2810         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2811         ts.append(parseType());
  2812         while (token.kind == COMMA) {
  2813             nextToken();
  2814             ts.append(parseType());
  2816         return ts.toList();
  2819     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
  2820      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
  2821      */
  2822     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
  2823         accept(LBRACE);
  2824         if (token.pos <= endPosTable.errorEndPos) {
  2825             // error recovery
  2826             skip(false, true, false, false);
  2827             if (token.kind == LBRACE)
  2828                 nextToken();
  2830         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
  2831         while (token.kind != RBRACE && token.kind != EOF) {
  2832             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
  2833             if (token.pos <= endPosTable.errorEndPos) {
  2834                // error recovery
  2835                skip(false, true, true, false);
  2838         accept(RBRACE);
  2839         return defs.toList();
  2842     /** ClassBodyDeclaration =
  2843      *      ";"
  2844      *    | [STATIC] Block
  2845      *    | ModifiersOpt
  2846      *      ( Type Ident
  2847      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
  2848      *      | VOID Ident MethodDeclaratorRest
  2849      *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
  2850      *      | Ident ConstructorDeclaratorRest
  2851      *      | TypeParameters Ident ConstructorDeclaratorRest
  2852      *      | ClassOrInterfaceOrEnumDeclaration
  2853      *      )
  2854      *  InterfaceBodyDeclaration =
  2855      *      ";"
  2856      *    | ModifiersOpt Type Ident
  2857      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
  2858      */
  2859     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
  2860         if (token.kind == SEMI) {
  2861             nextToken();
  2862             return List.<JCTree>nil();
  2863         } else {
  2864             Comment dc = token.comment(CommentStyle.JAVADOC);
  2865             int pos = token.pos;
  2866             JCModifiers mods = modifiersOpt();
  2867             if (token.kind == CLASS ||
  2868                 token.kind == INTERFACE ||
  2869                 allowEnums && token.kind == ENUM) {
  2870                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
  2871             } else if (token.kind == LBRACE && !isInterface &&
  2872                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
  2873                        mods.annotations.isEmpty()) {
  2874                 return List.<JCTree>of(block(pos, mods.flags));
  2875             } else {
  2876                 pos = token.pos;
  2877                 List<JCTypeParameter> typarams = typeParametersOpt();
  2878                 // if there are type parameters but no modifiers, save the start
  2879                 // position of the method in the modifiers.
  2880                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
  2881                     mods.pos = pos;
  2882                     storeEnd(mods, pos);
  2884                 Token tk = token;
  2885                 pos = token.pos;
  2886                 JCExpression type;
  2887                 boolean isVoid = token.kind == VOID;
  2888                 if (isVoid) {
  2889                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
  2890                     nextToken();
  2891                 } else {
  2892                     type = parseType();
  2894                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {
  2895                     if (isInterface || tk.name() != className)
  2896                         error(pos, "invalid.meth.decl.ret.type.req");
  2897                     return List.of(methodDeclaratorRest(
  2898                         pos, mods, null, names.init, typarams,
  2899                         isInterface, true, dc));
  2900                 } else {
  2901                     pos = token.pos;
  2902                     Name name = ident();
  2903                     if (token.kind == LPAREN) {
  2904                         return List.of(methodDeclaratorRest(
  2905                             pos, mods, type, name, typarams,
  2906                             isInterface, isVoid, dc));
  2907                     } else if (!isVoid && typarams.isEmpty()) {
  2908                         List<JCTree> defs =
  2909                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
  2910                                                     new ListBuffer<JCTree>()).toList();
  2911                         storeEnd(defs.last(), token.endPos);
  2912                         accept(SEMI);
  2913                         return defs;
  2914                     } else {
  2915                         pos = token.pos;
  2916                         List<JCTree> err = isVoid
  2917                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2918                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
  2919                             : null;
  2920                         return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
  2927     /** MethodDeclaratorRest =
  2928      *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
  2929      *  VoidMethodDeclaratorRest =
  2930      *      FormalParameters [Throws TypeList] ( MethodBody | ";")
  2931      *  InterfaceMethodDeclaratorRest =
  2932      *      FormalParameters BracketsOpt [THROWS TypeList] ";"
  2933      *  VoidInterfaceMethodDeclaratorRest =
  2934      *      FormalParameters [THROWS TypeList] ";"
  2935      *  ConstructorDeclaratorRest =
  2936      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
  2937      */
  2938     protected JCTree methodDeclaratorRest(int pos,
  2939                               JCModifiers mods,
  2940                               JCExpression type,
  2941                               Name name,
  2942                               List<JCTypeParameter> typarams,
  2943                               boolean isInterface, boolean isVoid,
  2944                               Comment dc) {
  2945         List<JCVariableDecl> params = formalParameters();
  2946         if (!isVoid) type = bracketsOpt(type);
  2947         List<JCExpression> thrown = List.nil();
  2948         if (token.kind == THROWS) {
  2949             nextToken();
  2950             thrown = qualidentList();
  2952         JCBlock body = null;
  2953         JCExpression defaultValue;
  2954         if (token.kind == LBRACE) {
  2955             body = block();
  2956             defaultValue = null;
  2957         } else {
  2958             if (token.kind == DEFAULT) {
  2959                 accept(DEFAULT);
  2960                 defaultValue = annotationValue();
  2961             } else {
  2962                 defaultValue = null;
  2964             accept(SEMI);
  2965             if (token.pos <= endPosTable.errorEndPos) {
  2966                 // error recovery
  2967                 skip(false, true, false, false);
  2968                 if (token.kind == LBRACE) {
  2969                     body = block();
  2974         JCMethodDecl result =
  2975             toP(F.at(pos).MethodDef(mods, name, type, typarams,
  2976                                     params, thrown,
  2977                                     body, defaultValue));
  2978         attach(result, dc);
  2979         return result;
  2982     /** QualidentList = Qualident {"," Qualident}
  2983      */
  2984     List<JCExpression> qualidentList() {
  2985         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
  2986         ts.append(qualident());
  2987         while (token.kind == COMMA) {
  2988             nextToken();
  2989             ts.append(qualident());
  2991         return ts.toList();
  2994     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
  2995      */
  2996     List<JCTypeParameter> typeParametersOpt() {
  2997         if (token.kind == LT) {
  2998             checkGenerics();
  2999             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
  3000             nextToken();
  3001             typarams.append(typeParameter());
  3002             while (token.kind == COMMA) {
  3003                 nextToken();
  3004                 typarams.append(typeParameter());
  3006             accept(GT);
  3007             return typarams.toList();
  3008         } else {
  3009             return List.nil();
  3013     /** TypeParameter = TypeVariable [TypeParameterBound]
  3014      *  TypeParameterBound = EXTENDS Type {"&" Type}
  3015      *  TypeVariable = Ident
  3016      */
  3017     JCTypeParameter typeParameter() {
  3018         int pos = token.pos;
  3019         Name name = ident();
  3020         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
  3021         if (token.kind == EXTENDS) {
  3022             nextToken();
  3023             bounds.append(parseType());
  3024             while (token.kind == AMP) {
  3025                 nextToken();
  3026                 bounds.append(parseType());
  3029         return toP(F.at(pos).TypeParameter(name, bounds.toList()));
  3032     /** FormalParameters = "(" [ FormalParameterList ] ")"
  3033      *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
  3034      *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
  3035      */
  3036     List<JCVariableDecl> formalParameters() {
  3037         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3038         JCVariableDecl lastParam = null;
  3039         accept(LPAREN);
  3040         if (token.kind != RPAREN) {
  3041             params.append(lastParam = formalParameter());
  3042             while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
  3043                 nextToken();
  3044                 params.append(lastParam = formalParameter());
  3047         accept(RPAREN);
  3048         return params.toList();
  3051     List<JCVariableDecl> implicitParameters(boolean hasParens) {
  3052         if (hasParens) {
  3053             accept(LPAREN);
  3055         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
  3056         if (token.kind != RPAREN && token.kind != ARROW) {
  3057             params.append(implicitParameter());
  3058             while (token.kind == COMMA) {
  3059                 nextToken();
  3060                 params.append(implicitParameter());
  3063         if (hasParens) {
  3064             accept(RPAREN);
  3066         return params.toList();
  3069     JCModifiers optFinal(long flags) {
  3070         JCModifiers mods = modifiersOpt();
  3071         checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
  3072         mods.flags |= flags;
  3073         return mods;
  3076     /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
  3077      *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
  3078      */
  3079     protected JCVariableDecl formalParameter() {
  3080         JCModifiers mods = optFinal(Flags.PARAMETER);
  3081         JCExpression type = parseType();
  3082         if (token.kind == ELLIPSIS) {
  3083             checkVarargs();
  3084             mods.flags |= Flags.VARARGS;
  3085             type = to(F.at(token.pos).TypeArray(type));
  3086             nextToken();
  3088         return variableDeclaratorId(mods, type);
  3091     protected JCVariableDecl implicitParameter() {
  3092         JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
  3093         return variableDeclaratorId(mods, null);
  3096 /* ---------- auxiliary methods -------------- */
  3098     void error(int pos, String key, Object ... args) {
  3099         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3102     void error(DiagnosticPosition pos, String key, Object ... args) {
  3103         log.error(DiagnosticFlag.SYNTAX, pos, key, args);
  3106     void warning(int pos, String key, Object ... args) {
  3107         log.warning(pos, key, args);
  3110     /** Check that given tree is a legal expression statement.
  3111      */
  3112     protected JCExpression checkExprStat(JCExpression t) {
  3113         switch(t.getTag()) {
  3114         case PREINC: case PREDEC:
  3115         case POSTINC: case POSTDEC:
  3116         case ASSIGN:
  3117         case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG:
  3118         case SL_ASG: case SR_ASG: case USR_ASG:
  3119         case PLUS_ASG: case MINUS_ASG:
  3120         case MUL_ASG: case DIV_ASG: case MOD_ASG:
  3121         case APPLY: case NEWCLASS:
  3122         case ERRONEOUS:
  3123             return t;
  3124         default:
  3125             JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
  3126             error(ret, "not.stmt");
  3127             return ret;
  3131     /** Return precedence of operator represented by token,
  3132      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
  3133      */
  3134     static int prec(TokenKind token) {
  3135         JCTree.Tag oc = optag(token);
  3136         return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
  3139     /**
  3140      * Return the lesser of two positions, making allowance for either one
  3141      * being unset.
  3142      */
  3143     static int earlier(int pos1, int pos2) {
  3144         if (pos1 == Position.NOPOS)
  3145             return pos2;
  3146         if (pos2 == Position.NOPOS)
  3147             return pos1;
  3148         return (pos1 < pos2 ? pos1 : pos2);
  3151     /** Return operation tag of binary operator represented by token,
  3152      *  No_TAG if token is not a binary operator.
  3153      */
  3154     static JCTree.Tag optag(TokenKind token) {
  3155         switch (token) {
  3156         case BARBAR:
  3157             return OR;
  3158         case AMPAMP:
  3159             return AND;
  3160         case BAR:
  3161             return BITOR;
  3162         case BAREQ:
  3163             return BITOR_ASG;
  3164         case CARET:
  3165             return BITXOR;
  3166         case CARETEQ:
  3167             return BITXOR_ASG;
  3168         case AMP:
  3169             return BITAND;
  3170         case AMPEQ:
  3171             return BITAND_ASG;
  3172         case EQEQ:
  3173             return JCTree.Tag.EQ;
  3174         case BANGEQ:
  3175             return NE;
  3176         case LT:
  3177             return JCTree.Tag.LT;
  3178         case GT:
  3179             return JCTree.Tag.GT;
  3180         case LTEQ:
  3181             return LE;
  3182         case GTEQ:
  3183             return GE;
  3184         case LTLT:
  3185             return SL;
  3186         case LTLTEQ:
  3187             return SL_ASG;
  3188         case GTGT:
  3189             return SR;
  3190         case GTGTEQ:
  3191             return SR_ASG;
  3192         case GTGTGT:
  3193             return USR;
  3194         case GTGTGTEQ:
  3195             return USR_ASG;
  3196         case PLUS:
  3197             return JCTree.Tag.PLUS;
  3198         case PLUSEQ:
  3199             return PLUS_ASG;
  3200         case SUB:
  3201             return MINUS;
  3202         case SUBEQ:
  3203             return MINUS_ASG;
  3204         case STAR:
  3205             return MUL;
  3206         case STAREQ:
  3207             return MUL_ASG;
  3208         case SLASH:
  3209             return DIV;
  3210         case SLASHEQ:
  3211             return DIV_ASG;
  3212         case PERCENT:
  3213             return MOD;
  3214         case PERCENTEQ:
  3215             return MOD_ASG;
  3216         case INSTANCEOF:
  3217             return TYPETEST;
  3218         default:
  3219             return NO_TAG;
  3223     /** Return operation tag of unary operator represented by token,
  3224      *  No_TAG if token is not a binary operator.
  3225      */
  3226     static JCTree.Tag unoptag(TokenKind token) {
  3227         switch (token) {
  3228         case PLUS:
  3229             return POS;
  3230         case SUB:
  3231             return NEG;
  3232         case BANG:
  3233             return NOT;
  3234         case TILDE:
  3235             return COMPL;
  3236         case PLUSPLUS:
  3237             return PREINC;
  3238         case SUBSUB:
  3239             return PREDEC;
  3240         default:
  3241             return NO_TAG;
  3245     /** Return type tag of basic type represented by token,
  3246      *  -1 if token is not a basic type identifier.
  3247      */
  3248     static int typetag(TokenKind token) {
  3249         switch (token) {
  3250         case BYTE:
  3251             return TypeTags.BYTE;
  3252         case CHAR:
  3253             return TypeTags.CHAR;
  3254         case SHORT:
  3255             return TypeTags.SHORT;
  3256         case INT:
  3257             return TypeTags.INT;
  3258         case LONG:
  3259             return TypeTags.LONG;
  3260         case FLOAT:
  3261             return TypeTags.FLOAT;
  3262         case DOUBLE:
  3263             return TypeTags.DOUBLE;
  3264         case BOOLEAN:
  3265             return TypeTags.BOOLEAN;
  3266         default:
  3267             return -1;
  3271     void checkGenerics() {
  3272         if (!allowGenerics) {
  3273             error(token.pos, "generics.not.supported.in.source", source.name);
  3274             allowGenerics = true;
  3277     void checkVarargs() {
  3278         if (!allowVarargs) {
  3279             error(token.pos, "varargs.not.supported.in.source", source.name);
  3280             allowVarargs = true;
  3283     void checkForeach() {
  3284         if (!allowForeach) {
  3285             error(token.pos, "foreach.not.supported.in.source", source.name);
  3286             allowForeach = true;
  3289     void checkStaticImports() {
  3290         if (!allowStaticImport) {
  3291             error(token.pos, "static.import.not.supported.in.source", source.name);
  3292             allowStaticImport = true;
  3295     void checkAnnotations() {
  3296         if (!allowAnnotations) {
  3297             error(token.pos, "annotations.not.supported.in.source", source.name);
  3298             allowAnnotations = true;
  3301     void checkDiamond() {
  3302         if (!allowDiamond) {
  3303             error(token.pos, "diamond.not.supported.in.source", source.name);
  3304             allowDiamond = true;
  3307     void checkMulticatch() {
  3308         if (!allowMulticatch) {
  3309             error(token.pos, "multicatch.not.supported.in.source", source.name);
  3310             allowMulticatch = true;
  3313     void checkTryWithResources() {
  3314         if (!allowTWR) {
  3315             error(token.pos, "try.with.resources.not.supported.in.source", source.name);
  3316             allowTWR = true;
  3319     void checkLambda() {
  3320         if (!allowLambda) {
  3321             log.error(token.pos, "lambda.not.supported.in.source", source.name);
  3322             allowLambda = true;
  3325     void checkMethodReferences() {
  3326         if (!allowMethodReferences) {
  3327             log.error(token.pos, "method.references.not.supported.in.source", source.name);
  3328             allowMethodReferences = true;
  3332     /*
  3333      * a functional source tree and end position mappings
  3334      */
  3335     protected class SimpleEndPosTable extends AbstractEndPosTable {
  3337         private final Map<JCTree, Integer> endPosMap;
  3339         SimpleEndPosTable() {
  3340             endPosMap = new HashMap<JCTree, Integer>();
  3343         protected void storeEnd(JCTree tree, int endpos) {
  3344             endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos);
  3347         protected <T extends JCTree> T to(T t) {
  3348             storeEnd(t, token.endPos);
  3349             return t;
  3352         protected <T extends JCTree> T toP(T t) {
  3353             storeEnd(t, S.prevToken().endPos);
  3354             return t;
  3357         public int getEndPos(JCTree tree) {
  3358             Integer value = endPosMap.get(tree);
  3359             return (value == null) ? Position.NOPOS : value;
  3362         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3363             Integer pos = endPosMap.remove(oldTree);
  3364             if (pos != null) {
  3365                 endPosMap.put(newTree, pos);
  3366                 return pos;
  3368             return Position.NOPOS;
  3372     /*
  3373      * a default skeletal implementation without any mapping overhead.
  3374      */
  3375     protected class EmptyEndPosTable extends AbstractEndPosTable {
  3377         protected void storeEnd(JCTree tree, int endpos) { /* empty */ }
  3379         protected <T extends JCTree> T to(T t) {
  3380             return t;
  3383         protected <T extends JCTree> T toP(T t) {
  3384             return t;
  3387         public int getEndPos(JCTree tree) {
  3388             return Position.NOPOS;
  3391         public int replaceTree(JCTree oldTree, JCTree newTree) {
  3392             return Position.NOPOS;
  3397     protected abstract class AbstractEndPosTable implements EndPosTable {
  3399         /**
  3400          * Store the last error position.
  3401          */
  3402         protected int errorEndPos;
  3404         /**
  3405          * Store ending position for a tree, the value of which is the greater
  3406          * of last error position and the given ending position.
  3407          * @param tree   The tree.
  3408          * @param endpos The ending position to associate with the tree.
  3409          */
  3410         protected abstract void storeEnd(JCTree tree, int endpos);
  3412         /**
  3413          * Store current token's ending position for a tree, the value of which
  3414          * will be the greater of last error position and the ending position of
  3415          * the current token.
  3416          * @param t The tree.
  3417          */
  3418         protected abstract <T extends JCTree> T to(T t);
  3420         /**
  3421          * Store current token's ending position for a tree, the value of which
  3422          * will be the greater of last error position and the ending position of
  3423          * the previous token.
  3424          * @param t The tree.
  3425          */
  3426         protected abstract <T extends JCTree> T toP(T t);
  3428         /**
  3429          * Set the error position during the parsing phases, the value of which
  3430          * will be set only if it is greater than the last stored error position.
  3431          * @param errPos The error position
  3432          */
  3433         protected void setErrorEndPos(int errPos) {
  3434             if (errPos > errorEndPos) {
  3435                 errorEndPos = errPos;

mercurial