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