1 /*
2 * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.parser;
27
28 import java.util.*;
29 import java.util.function.Function;
30 import java.util.function.Predicate;
31 import java.util.stream.Collectors;
32
33 import javax.lang.model.SourceVersion;
34
35 import com.sun.source.tree.CaseTree;
36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
37 import com.sun.source.tree.ModuleTree.ModuleKind;
38
39 import com.sun.tools.javac.code.*;
40 import com.sun.tools.javac.code.Source.Feature;
41 import com.sun.tools.javac.file.PathFileObject;
42 import com.sun.tools.javac.parser.Tokens.*;
43 import com.sun.tools.javac.resources.CompilerProperties.Errors;
44 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
45 import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
46 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
47 import com.sun.tools.javac.tree.*;
48 import com.sun.tools.javac.tree.JCTree.*;
49 import com.sun.tools.javac.util.*;
50 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
51 import com.sun.tools.javac.util.JCDiagnostic.Error;
52 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
53 import com.sun.tools.javac.util.List;
54
55 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
56 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
62 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
63 import com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
64 import static com.sun.tools.javac.tree.JCTree.Tag.*;
65 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
66 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
67 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
68 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
69
70 /**
71 * The parser maps a token sequence into an abstract syntax tree.
72 * The parser is a hand-written recursive-descent parser that
73 * implements the grammar described in the Java Language Specification.
74 * For efficiency reasons, an operator precedence scheme is used
75 * for parsing binary operation expressions.
76 *
77 * <p><b>This is NOT part of any supported API.
78 * If you write code that depends on this, you do so at your own risk.
79 * This code and its internal interfaces are subject to change or
80 * deletion without notice.</b>
81 */
82 public class JavacParser implements Parser {
83
84 /** The number of precedence levels of infix operators.
85 */
86 private static final int infixPrecedenceLevels = 10;
87
88 /** Is the parser instantiated to parse a module-info file ?
89 */
90 private final boolean parseModuleInfo;
91
92 /** The scanner used for lexical analysis.
93 */
94 protected Lexer S;
95
96 /** The factory to be used for abstract syntax tree construction.
97 */
98 protected TreeMaker F;
99
100 /** The log to be used for error diagnostics.
101 */
102 private Log log;
103
104 /** The Source language setting. */
105 private Source source;
106
107 /** The Preview language setting. */
108 private Preview preview;
109
110 /** The name table. */
111 private Names names;
112
113 protected int errorEndPos = Position.NOPOS;
114
115 /** A map associating "other nearby documentation comments"
116 * with the preferred documentation comment for a declaration. */
117 protected Map<Comment, List<Comment>> danglingComments = new HashMap<>();
118
119 // Because of javac's limited lookahead, some contexts are ambiguous in
120 // the presence of type annotations even though they are not ambiguous
121 // in the absence of type annotations. Consider this code:
122 // void m(String [] m) { }
123 // void m(String ... m) { }
124 // After parsing "String", javac calls bracketsOpt which immediately
125 // returns if the next character is not '['. Similarly, javac can see
126 // if the next token is ... and in that case parse an ellipsis. But in
127 // the presence of type annotations:
128 // void m(String @A [] m) { }
129 // void m(String @A ... m) { }
130 // no finite lookahead is enough to determine whether to read array
131 // levels or an ellipsis. Furthermore, if you call bracketsOpt, then
132 // bracketsOpt first reads all the leading annotations and only then
133 // discovers that it needs to fail. bracketsOpt needs a way to push
134 // back the extra annotations that it read. (But, bracketsOpt should
135 // not *always* be allowed to push back extra annotations that it finds
136 // -- in most contexts, any such extra annotation is an error.
137 //
138 // The following two variables permit type annotations that have
139 // already been read to be stored for later use. Alternate
140 // implementations are possible but would cause much larger changes to
141 // the parser.
142
143 /** Type annotations that have already been read but have not yet been used. **/
144 private List<JCAnnotation> typeAnnotationsPushedBack = List.nil();
145
146 /**
147 * If the parser notices extra annotations, then it either immediately
148 * issues an error (if this variable is false) or places the extra
149 * annotations in variable typeAnnotationsPushedBack (if this variable
150 * is true).
151 */
152 private boolean permitTypeAnnotationsPushBack = false;
153 private JCDiagnostic.Error unexpectedTopLevelDefinitionStartError;
154
155 interface ErrorRecoveryAction {
156 JCTree doRecover(JavacParser parser);
157 }
158
159 enum BasicErrorRecoveryAction implements ErrorRecoveryAction {
160 BLOCK_STMT {public JCTree doRecover(JavacParser parser) { return parser.parseStatementAsBlock(); }},
161 CATCH_CLAUSE {public JCTree doRecover(JavacParser parser) { return parser.catchClause(); }}
162 }
163
164 /** Construct a parser from a given scanner, tree factory and log.
165 */
166 protected JavacParser(ParserFactory fac,
167 Lexer S,
168 boolean keepDocComments,
169 boolean keepLineMap) {
170 this(fac, S, keepDocComments, keepLineMap, false);
171
172 }
173 /** Construct a parser from a given scanner, tree factory and log.
174 */
175 @SuppressWarnings("this-escape")
176 protected JavacParser(ParserFactory fac,
177 Lexer S,
178 boolean keepDocComments,
179 boolean keepLineMap,
180 boolean parseModuleInfo) {
181 this.S = S;
182 nextToken(); // prime the pump
183 this.F = fac.F;
184 this.log = fac.log;
185 this.names = fac.names;
186 this.source = fac.source;
187 this.preview = fac.preview;
188 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
189 this.keepDocComments = keepDocComments;
190 this.parseModuleInfo = parseModuleInfo;
191 this.docComments = newDocCommentTable(keepDocComments, fac);
192 this.keepLineMap = keepLineMap;
193 this.errorTree = F.Erroneous();
194 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
195 this.allowRecords = Feature.RECORDS.allowedInSource(source);
196 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
197 updateUnexpectedTopLevelDefinitionStartError(false);
198 }
199
200 /** Construct a parser from an existing parser, with minimal overhead.
201 */
202 @SuppressWarnings("this-escape")
203 protected JavacParser(JavacParser parser,
204 Lexer S) {
205 this.S = S;
206 this.token = parser.token;
207 this.F = parser.F;
208 this.log = parser.log;
209 this.names = parser.names;
210 this.source = parser.source;
211 this.preview = parser.preview;
212 this.allowStringFolding = parser.allowStringFolding;
213 this.keepDocComments = parser.keepDocComments;
214 this.parseModuleInfo = false;
215 this.docComments = parser.docComments;
216 this.errorTree = F.Erroneous();
217 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
218 this.allowRecords = Feature.RECORDS.allowedInSource(source);
219 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
220 updateUnexpectedTopLevelDefinitionStartError(false);
221 }
222
223 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
224 return keepDocComments ? new LazyDocCommentTable(fac) : null;
225 }
226
227 /** Switch: should we fold strings?
228 */
229 boolean allowStringFolding;
230
231 /** Switch: should we keep docComments?
232 */
233 boolean keepDocComments;
234
235 /** Switch: should we keep line table?
236 */
237 boolean keepLineMap;
238
239 /** Switch: is "this" allowed as an identifier?
240 * This is needed to parse receiver types.
241 */
242 boolean allowThisIdent;
243
244 /** Switch: is yield statement allowed in this source level?
245 */
246 boolean allowYieldStatement;
247
248 /** Switch: are records allowed in this source level?
249 */
250 boolean allowRecords;
251
252 /** Switch: are sealed types allowed in this source level?
253 */
254 boolean allowSealedTypes;
255
256 /** The type of the method receiver, as specified by a first "this" parameter.
257 */
258 JCVariableDecl receiverParam;
259
260 /** When terms are parsed, the mode determines which is expected:
261 * mode = EXPR : an expression
262 * mode = TYPE : a type
263 * mode = NOLAMBDA : lambdas are not allowed
264 */
265 protected static final int EXPR = 1 << 0;
266 protected static final int TYPE = 1 << 1;
267 protected static final int NOLAMBDA = 1 << 2;
268
269 protected void setMode(int mode) {
270 this.mode = mode;
271 }
272
273 protected void setLastMode(int mode) {
274 lastmode = mode;
275 }
276
277 protected boolean isMode(int mode) {
278 return (this.mode & mode) != 0;
279 }
280
281 protected boolean wasTypeMode() {
282 return (lastmode & TYPE) != 0;
283 }
284
285 protected void selectExprMode() {
286 setMode((mode & NOLAMBDA) | EXPR);
287 }
288
289 protected void selectTypeMode() {
290 setMode((mode & NOLAMBDA) | TYPE);
291 }
292
293 /** The current mode.
294 */
295 protected int mode = 0;
296
297 /** The mode of the term that was parsed last.
298 */
299 protected int lastmode = 0;
300
301 /* ---------- token management -------------- */
302
303 protected Token token;
304
305 public Token token() {
306 return token;
307 }
308
309 public void nextToken() {
310 S.nextToken();
311 token = S.token();
312 }
313
314 protected boolean peekToken(Predicate<TokenKind> tk) {
315 return peekToken(0, tk);
316 }
317
318 protected boolean peekToken(int lookahead, Predicate<TokenKind> tk) {
319 return tk.test(S.token(lookahead + 1).kind);
320 }
321
322 protected boolean peekToken(Predicate<TokenKind> tk1, Predicate<TokenKind> tk2) {
323 return peekToken(0, tk1, tk2);
324 }
325
326 protected boolean peekToken(int lookahead, Predicate<TokenKind> tk1, Predicate<TokenKind> tk2) {
327 return tk1.test(S.token(lookahead + 1).kind) &&
328 tk2.test(S.token(lookahead + 2).kind);
329 }
330
331 protected boolean peekToken(Predicate<TokenKind> tk1, Predicate<TokenKind> tk2, Predicate<TokenKind> tk3) {
332 return peekToken(0, tk1, tk2, tk3);
333 }
334
335 protected boolean peekToken(int lookahead, Predicate<TokenKind> tk1, Predicate<TokenKind> tk2, Predicate<TokenKind> tk3) {
336 return tk1.test(S.token(lookahead + 1).kind) &&
337 tk2.test(S.token(lookahead + 2).kind) &&
338 tk3.test(S.token(lookahead + 3).kind);
339 }
340
341 @SuppressWarnings("unchecked")
342 protected boolean peekToken(Predicate<TokenKind>... kinds) {
343 return peekToken(0, kinds);
344 }
345
346 @SuppressWarnings("unchecked")
347 protected boolean peekToken(int lookahead, Predicate<TokenKind>... kinds) {
348 for (Predicate<TokenKind> kind : kinds) {
349 if (!kind.test(S.token(++lookahead).kind)) {
350 return false;
351 }
352 }
353 return true;
354 }
355
356 /* ---------- error recovery -------------- */
357
358 private JCErroneous errorTree;
359
360 /** Skip forward until a suitable stop token is found.
361 */
362 protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
363 while (true) {
364 switch (token.kind) {
365 case SEMI:
366 nextToken();
367 return;
368 case PUBLIC:
369 case FINAL:
370 case ABSTRACT:
371 case MONKEYS_AT:
372 case EOF:
373 case CLASS:
374 case INTERFACE:
375 case ENUM:
376 return;
377 case IMPORT:
378 if (stopAtImport)
379 return;
380 break;
381 case LBRACE:
382 case RBRACE:
383 case PRIVATE:
384 case PROTECTED:
385 case STATIC:
386 case TRANSIENT:
387 case NATIVE:
388 case VOLATILE:
389 case SYNCHRONIZED:
390 case STRICTFP:
391 case LT:
392 case BYTE:
393 case SHORT:
394 case CHAR:
395 case INT:
396 case LONG:
397 case FLOAT:
398 case DOUBLE:
399 case BOOLEAN:
400 case VOID:
401 if (stopAtMemberDecl)
402 return;
403 break;
404 case UNDERSCORE:
405 case IDENTIFIER:
406 if (stopAtIdentifier)
407 return;
408 break;
409 case CASE:
410 case DEFAULT:
411 case IF:
412 case FOR:
413 case WHILE:
414 case DO:
415 case TRY:
416 case SWITCH:
417 case RETURN:
418 case THROW:
419 case BREAK:
420 case CONTINUE:
421 case ELSE:
422 case FINALLY:
423 case CATCH:
424 case THIS:
425 case SUPER:
426 case NEW:
427 if (stopAtStatement)
428 return;
429 break;
430 case ASSERT:
431 if (stopAtStatement)
432 return;
433 break;
434 }
435 nextToken();
436 }
437 }
438
439 protected JCErroneous syntaxError(int pos, Error errorKey) {
440 return syntaxError(pos, List.nil(), errorKey);
441 }
442
443 protected JCErroneous syntaxError(int pos, List<? extends JCTree> errs, Error errorKey) {
444 return syntaxError(pos, errs, errorKey, false);
445 }
446
447 private JCErroneous syntaxError(int pos, List<? extends JCTree> errs, Error errorKey, boolean noEofError) {
448 setErrorEndPos(pos);
449 JCErroneous err = F.at(pos).Erroneous(errs);
450 reportSyntaxError(err, errorKey, noEofError);
451 if (errs != null) {
452 JCTree last = errs.last();
453 if (last != null)
454 storeEnd(last, pos);
455 }
456 return toP(err);
457 }
458
459 private static final int RECOVERY_THRESHOLD = 50;
460 private int errorPos = Position.NOPOS;
461 private int count = 0;
462
463 /**
464 * Report a syntax using the given the position parameter and arguments,
465 * unless one was already reported at the same position.
466 */
467 protected void reportSyntaxError(int pos, Error errorKey) {
468 JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos);
469 reportSyntaxError(diag, errorKey);
470 }
471
472 /**
473 * Report a syntax error using the given DiagnosticPosition object and
474 * arguments, unless one was already reported at the same position.
475 */
476 protected void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, Error errorKey) {
477 reportSyntaxError(diagPos, errorKey, false);
478 }
479
480 private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, Error errorKey, boolean noEofError) {
481 int pos = diagPos.getPreferredPosition();
482 if (pos > S.errPos() || pos == Position.NOPOS) {
483 if (token.kind == EOF && !noEofError) {
484 log.error(DiagnosticFlag.SYNTAX, diagPos, Errors.PrematureEof);
485 } else {
486 log.error(DiagnosticFlag.SYNTAX, diagPos, errorKey);
487 }
488 }
489 S.errPos(pos);
490 if (token.pos == errorPos && token.kind != EOF) {
491 //check for a possible infinite loop in parsing:
492 Assert.check(count++ < RECOVERY_THRESHOLD);
493 } else {
494 count = 0;
495 errorPos = token.pos;
496 }
497 }
498
499 /** If next input token matches given token, skip it, otherwise report
500 * an error.
501 */
502 public void accept(TokenKind tk) {
503 accept(tk, Errors::Expected);
504 }
505
506 /** If next input token matches given token, skip it, otherwise report
507 * an error.
508 */
509 public void accept(TokenKind tk, Function<TokenKind, Error> errorProvider) {
510 if (token.kind == tk) {
511 nextToken();
512 } else {
513 setErrorEndPos(token.pos);
514 reportSyntaxError(S.prevToken().endPos, errorProvider.apply(tk));
515 }
516 }
517
518 /** Report an illegal start of expression/type error at given position.
519 */
520 JCExpression illegal(int pos) {
521 setErrorEndPos(pos);
522 if (isMode(EXPR))
523 return syntaxError(pos, Errors.IllegalStartOfExpr);
524 else
525 return syntaxError(pos, Errors.IllegalStartOfType);
526
527 }
528
529 /** Report an illegal start of expression/type error at current position.
530 */
531 JCExpression illegal() {
532 return illegal(token.pos);
533 }
534
535 /** Diagnose a modifier flag from the set, if any. */
536 protected void checkNoMods(long mods) {
537 checkNoMods(token.pos, mods);
538 }
539
540 protected void checkNoMods(int pos, long mods) {
541 if (mods != 0) {
542 long lowestMod = mods & -mods;
543 log.error(DiagnosticFlag.SYNTAX, pos, Errors.ModNotAllowedHere(Flags.asFlagSet(lowestMod)));
544 }
545 }
546
547 /* ---------- doc comments --------- */
548
549 /** A table to store all documentation comments
550 * indexed by the tree nodes they refer to.
551 * defined only if option flag keepDocComment is set.
552 */
553 private final DocCommentTable docComments;
554
555 /** Record nearby documentation comments against the
556 * primary documentation comment for a declaration.
557 *
558 * Dangling documentation comments are handled as follows.
559 * 1. {@code Scanner} adds all doc comments to a queue of
560 * recent doc comments. The queue is flushed whenever
561 * it is known that the recent doc comments should be
562 * ignored and should not cause any warnings.
563 * 2. The primary documentation comment is the one obtained
564 * from the first token of any declaration.
565 * (using {@code token.getDocComment()}.
566 * 3. At the end of the "signature" of the declaration
567 * (that is, before any initialization or body for the
568 * declaration) any other "recent" comments are saved
569 * in a map using the primary comment as a key,
570 * using this method, {@code saveDanglingComments}.
571 * 4. When the tree node for the declaration is finally
572 * available, and the primary comment, if any,
573 * is "attached", (in {@link #attach}) any related
574 * dangling comments are reported to the log as warnings.
575 * 5. (Later) Warnings may be generated for the dangling
576 * comments, subject to the {@code -Xlint} and
577 * {@code @SuppressWarnings}.
578 *
579 * @param dc the primary documentation comment
580 */
581 private void saveDanglingDocComments(Comment dc) {
582 var recentComments = S.getDocComments();
583
584 switch (recentComments.size()) {
585 case 0:
586 // no recent comments
587 return;
588
589 case 1:
590 if (recentComments.peek() == dc) {
591 // no other recent comments
592 recentComments.remove();
593 return;
594 }
595 }
596
597 var lb = new ListBuffer<Comment>();
598 while (!recentComments.isEmpty()) {
599 var c = recentComments.remove();
600 if (c != dc) {
601 lb.add(c);
602 }
603 }
604 danglingComments.put(dc, lb.toList());
605 }
606
607 /** Make an entry into docComments hashtable,
608 * provided flag keepDocComments is set and given doc comment is non-null.
609 * If there are any related "dangling comments", register
610 * diagnostics to be handled later, when @SuppressWarnings
611 * can be taken into account.
612 *
613 * @param tree The tree to be used as index in the hashtable
614 * @param dc The doc comment to associate with the tree, or null.
615 * @return {@code tree}
616 */
617 protected <T extends JCTree> T attach(T tree, Comment dc) {
618 if (keepDocComments && dc != null) {
619 docComments.putComment(tree, dc);
620 }
621 reportDanglingComments(tree, dc);
622 return tree;
623 }
624
625 /** Reports all dangling comments associated with the
626 * primary comment for a declaration against the position
627 * of the tree node for a declaration.
628 *
629 * @param tree the tree node for the declaration
630 * @param dc the primary comment for the declaration
631 */
632 void reportDanglingComments(JCTree tree, Comment dc) {
633 var list = danglingComments.remove(dc);
634 if (list != null) {
635 list.forEach(c -> reportDanglingDocComment(tree, c));
636 }
637 }
638
639 /**
640 * Reports an individual dangling comment as a warning to the log.
641 * The comment may or not may generate an actual diagnostic, depending on
642 * the settings for {@code -Xlint} and/or {@code @SuppressWarnings}.
643 *
644 * @param c the comment
645 */
646 void reportDanglingDocComment(JCTree tree, Comment c) {
647 var pos = c.getPos();
648 if (pos != null && !shebang(c, pos)) {
649 pos = pos.withLintPosition(tree.getStartPosition());
650 S.lintWarning(pos, LintWarnings.DanglingDocComment);
651 }
652 }
653
654 /** Returns true for a comment that acts similarly to shebang in UNIX */
655 private boolean shebang(Comment c, JCDiagnostic.DiagnosticPosition pos) {
656 var src = log.currentSource();
657 return c.getStyle() == Comment.CommentStyle.JAVADOC_LINE &&
658 c.getPos().getStartPosition() == 0 &&
659 src.getLineNumber(pos.getEndPosition()) == 1;
660 }
661
662 /**
663 * Ignores any recent documentation comments found by the scanner,
664 * such as those that cannot be associated with a nearby declaration.
665 */
666 private void ignoreDanglingComments() {
667 S.getDocComments().clear();
668 }
669
670 /* -------- source positions ------- */
671
672 protected void setErrorEndPos(int errPos) {
673 if (errPos > errorEndPos) {
674 errorEndPos = errPos;
675 }
676 }
677
678 /**
679 * Store ending position for a tree, the value of which is the greater of
680 * {@link #errorEndPos} and the given ending position.
681 * @param tree tree node
682 * @param endpos the ending position to associate with {@code tree}
683 * @return {@code tree}
684 */
685 protected <T extends JCTree> T storeEnd(T tree, int endpos) {
686 tree.endpos = Math.max(endpos, errorEndPos);
687 return tree;
688 }
689
690 /**
691 * Store current token's ending position for a tree, the value of which
692 * will be the greater of {@link #errorEndPos}
693 * and the ending position of the current token.
694 * @param tree tree node
695 */
696 protected <T extends JCTree> T to(T tree) {
697 return storeEnd(tree, token.endPos);
698 }
699
700 /**
701 * Store current token's ending position for a tree, the value of which
702 * will be the greater of {@link #errorEndPos}
703 * and the ending position of the previous token.
704 * @param tree tree node
705 */
706 protected <T extends JCTree> T toP(T tree) {
707 return storeEnd(tree, S.prevToken().endPos);
708 }
709
710 /** Get the start position for a tree node. The start position is
711 * defined to be the position of the first character of the first
712 * token of the node's source text.
713 * @param tree The tree node
714 */
715 public int getStartPos(JCTree tree) {
716 return TreeInfo.getStartPos(tree);
717 }
718
719 /**
720 * Get the end position for a tree node. The end position is
721 * defined to be the position of the last character of the last
722 * token of the node's source text. Returns Position.NOPOS if end
723 * positions are not generated or the position is otherwise not
724 * found.
725 * @param tree The tree node
726 */
727 public int getEndPos(JCTree tree) {
728 return tree.endpos;
729 }
730
731
732
733 /* ---------- parsing -------------- */
734
735 /**
736 * Ident = IDENTIFIER
737 */
738 public Name ident() {
739 return ident(false);
740 }
741
742 protected Name ident(boolean allowClass) {
743 return ident(allowClass, false);
744 }
745
746 public Name identOrUnderscore() {
747 return ident(false, true);
748 }
749
750 protected Name ident(boolean allowClass, boolean asVariable) {
751 if (token.kind == IDENTIFIER) {
752 Name name = token.name();
753 nextToken();
754 return name;
755 } else if (token.kind == ASSERT) {
756 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.AssertAsIdentifier);
757 nextToken();
758 return names.error;
759 } else if (token.kind == ENUM) {
760 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.EnumAsIdentifier);
761 nextToken();
762 return names.error;
763 } else if (token.kind == THIS) {
764 if (allowThisIdent) {
765 Name name = token.name();
766 nextToken();
767 return name;
768 } else {
769 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ThisAsIdentifier);
770 nextToken();
771 return names.error;
772 }
773 } else if (token.kind == UNDERSCORE) {
774 if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) {
775 log.warning(token.pos, Warnings.UnderscoreAsIdentifier);
776 } else if (asVariable) {
777 checkSourceLevel(Feature.UNNAMED_VARIABLES);
778 if (peekToken(LBRACKET)) {
779 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UseOfUnderscoreNotAllowedWithBrackets);
780 }
781 } else {
782 if (Feature.UNNAMED_VARIABLES.allowedInSource(source)) {
783 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UseOfUnderscoreNotAllowedNonVariable);
784 } else {
785 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.UnderscoreAsIdentifier);
786 }
787 }
788 Name name = token.name();
789 nextToken();
790 return name;
791 } else {
792 accept(IDENTIFIER);
793 if (allowClass && token.kind == CLASS) {
794 nextToken();
795 return names._class;
796 }
797 return names.error;
798 }
799 }
800
801 /**
802 * Qualident = Ident { DOT [Annotations] Ident }
803 */
804 public JCExpression qualident(boolean allowAnnos) {
805 JCExpression t = toP(F.at(token.pos).Ident(ident()));
806 while (token.kind == DOT) {
807 int pos = token.pos;
808 nextToken();
809 List<JCAnnotation> tyannos = null;
810 if (allowAnnos) {
811 tyannos = typeAnnotationsOpt();
812 }
813 t = toP(F.at(pos).Select(t, ident()));
814 if (tyannos != null && tyannos.nonEmpty()) {
815 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
816 }
817 }
818 return t;
819 }
820
821 JCExpression literal(Name prefix) {
822 return literal(prefix, token.pos);
823 }
824
825 /**
826 * Literal =
827 * INTLITERAL
828 * | LONGLITERAL
829 * | FLOATLITERAL
830 * | DOUBLELITERAL
831 * | CHARLITERAL
832 * | STRINGLITERAL
833 * | TRUE
834 * | FALSE
835 * | NULL
836 */
837 JCExpression literal(Name prefix, int pos) {
838 JCExpression t = errorTree;
839 switch (token.kind) {
840 case INTLITERAL:
841 try {
842 t = F.at(pos).Literal(
843 TypeTag.INT,
844 Convert.string2int(strval(prefix), token.radix()));
845 } catch (NumberFormatException ex) {
846 reportIntegralLiteralError(prefix, pos);
847 }
848 break;
849 case LONGLITERAL:
850 try {
851 t = F.at(pos).Literal(
852 TypeTag.LONG,
853 Long.valueOf(Convert.string2long(strval(prefix), token.radix())));
854 } catch (NumberFormatException ex) {
855 reportIntegralLiteralError(prefix, pos);
856 }
857 break;
858 case FLOATLITERAL: {
859 String proper = token.radix() == 16 ?
860 ("0x"+ token.stringVal()) :
861 token.stringVal();
862 Float n;
863 try {
864 n = Float.valueOf(proper);
865 } catch (NumberFormatException ex) {
866 // error already reported in scanner
867 n = Float.NaN;
868 }
869 if (n.floatValue() == 0.0f && !isZero(proper))
870 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooSmall);
871 else if (n.floatValue() == Float.POSITIVE_INFINITY)
872 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooLarge);
873 else
874 t = F.at(pos).Literal(TypeTag.FLOAT, n);
875 break;
876 }
877 case DOUBLELITERAL: {
878 String proper = token.radix() == 16 ?
879 ("0x"+ token.stringVal()) :
880 token.stringVal();
881 Double n;
882 try {
883 n = Double.valueOf(proper);
884 } catch (NumberFormatException ex) {
885 // error already reported in scanner
886 n = Double.NaN;
887 }
888 if (n.doubleValue() == 0.0d && !isZero(proper))
889 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooSmall);
890 else if (n.doubleValue() == Double.POSITIVE_INFINITY)
891 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.FpNumberTooLarge);
892 else
893 t = F.at(pos).Literal(TypeTag.DOUBLE, n);
894 break;
895 }
896 case CHARLITERAL:
897 t = F.at(pos).Literal(
898 TypeTag.CHAR,
899 token.stringVal().charAt(0) + 0);
900 break;
901 case STRINGLITERAL:
902 t = F.at(pos).Literal(
903 TypeTag.CLASS,
904 token.stringVal());
905 break;
906 case TRUE: case FALSE:
907 t = F.at(pos).Literal(
908 TypeTag.BOOLEAN,
909 (token.kind == TRUE ? 1 : 0));
910 break;
911 case NULL:
912 t = F.at(pos).Literal(
913 TypeTag.BOT,
914 null);
915 break;
916 default:
917 Assert.error();
918 }
919 if (t == errorTree)
920 t = F.at(pos).Erroneous();
921 storeEnd(t, token.endPos);
922 nextToken();
923 return t;
924 }
925 //where
926 boolean isZero(String s) {
927 char[] cs = s.toCharArray();
928 int base = ((cs.length > 1 && Character.toLowerCase(cs[1]) == 'x') ? 16 : 10);
929 int i = ((base==16) ? 2 : 0);
930 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
931 return !(i < cs.length && (Character.digit(cs[i], base) > 0));
932 }
933
934 String strval(Name prefix) {
935 String s = token.stringVal();
936 return prefix.isEmpty() ? s : prefix + s;
937 }
938 void reportIntegralLiteralError(Name prefix, int pos) {
939 int radix = token.radix();
940 if (radix == 2 || radix == 8) {
941 //attempt to produce more user-friendly error message for
942 //binary and octal literals with wrong digits:
943 String value = strval(prefix);
944 char[] cs = value.toCharArray();
945 for (int i = 0; i < cs.length; i++) {
946 char c = cs[i];
947 int d = Character.digit(c, radix);
948 if (d == (-1)) {
949 Error err = radix == 2 ? Errors.IllegalDigitInBinaryLiteral
950 : Errors.IllegalDigitInOctalLiteral;
951 log.error(DiagnosticFlag.SYNTAX,
952 token.pos + i,
953 err);
954 return ;
955 }
956 }
957 }
958 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.IntNumberTooLarge(strval(prefix)));
959 }
960
961 /** terms can be either expressions or types.
962 */
963 public JCExpression parseExpression() {
964 return term(EXPR);
965 }
966
967 /** parses patterns.
968 */
969 public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType,
970 boolean allowVar, boolean checkGuard) {
971 JCPattern pattern;
972 mods = mods != null ? mods : optFinal(0);
973 JCExpression e;
974 if (token.kind == UNDERSCORE && parsedType == null) {
975 nextToken();
976 checkSourceLevel(Feature.UNNAMED_VARIABLES);
977 pattern = toP(F.at(token.pos).AnyPattern());
978 }
979 else {
980 int varTypePos = Position.NOPOS;
981 if (parsedType == null) {
982 boolean var = token.kind == IDENTIFIER && token.name() == names.var;
983 e = unannotatedType(allowVar, TYPE | NOLAMBDA);
984 if (var) {
985 varTypePos = e.pos;
986 e = null;
987 }
988 } else {
989 e = parsedType;
990 }
991 if (token.kind == LPAREN) {
992 //deconstruction pattern:
993 checkSourceLevel(Feature.RECORD_PATTERNS);
994 ListBuffer<JCPattern> nested = new ListBuffer<>();
995 if (!peekToken(RPAREN)) {
996 do {
997 nextToken();
998 JCPattern nestedPattern = parsePattern(token.pos, null, null, true, false);
999 nested.append(nestedPattern);
1000 } while (token.kind == COMMA);
1001 } else {
1002 nextToken();
1003 }
1004 accept(RPAREN);
1005 pattern = toP(F.at(pos).RecordPattern(e, nested.toList()));
1006 if (mods.annotations.nonEmpty()) {
1007 log.error(mods.annotations.head.pos(), Errors.RecordPatternsAnnotationsNotAllowed);
1008 }
1009 checkNoMods(pos, mods.flags & Flags.FINAL);
1010 new TreeScanner() {
1011 @Override
1012 public void visitAnnotatedType(JCAnnotatedType tree) {
1013 log.error(tree.pos(), Errors.RecordPatternsAnnotationsNotAllowed);
1014 }
1015 }.scan(e);
1016 } else {
1017 //type test pattern:
1018 int varPos = token.pos;
1019 Name name = identOrUnderscore();
1020 if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
1021 name = names.empty;
1022 }
1023 JCVariableDecl var = toP(F.at(varPos).VarDef(mods, name, e, null,
1024 varTypePos != Position.NOPOS ? JCVariableDecl.DeclKind.VAR : JCVariableDecl.DeclKind.EXPLICIT,
1025 varTypePos));
1026 if (e == null) {
1027 if (var.name == names.underscore && !allowVar) {
1028 log.error(DiagnosticFlag.SYNTAX, varPos, Errors.UseOfUnderscoreNotAllowed);
1029 }
1030 }
1031 pattern = toP(F.at(pos).BindingPattern(var));
1032 }
1033 }
1034 return pattern;
1035 }
1036
1037 /**
1038 * parses (optional) type annotations followed by a type. If the
1039 * annotations are present before the type and are not consumed during array
1040 * parsing, this method returns a {@link JCAnnotatedType} consisting of
1041 * these annotations and the underlying type. Otherwise, it returns the
1042 * underlying type.
1043 *
1044 * <p>
1045 *
1046 * Note that this method sets {@code mode} to {@code TYPE} first, before
1047 * parsing annotations.
1048 */
1049 public JCExpression parseType() {
1050 return parseType(false);
1051 }
1052
1053 public JCExpression parseType(boolean allowVar) {
1054 List<JCAnnotation> annotations = typeAnnotationsOpt();
1055 return parseType(allowVar, annotations);
1056 }
1057
1058 public JCExpression parseType(boolean allowVar, List<JCAnnotation> annotations) {
1059 JCExpression result = unannotatedType(allowVar);
1060
1061 if (annotations.nonEmpty()) {
1062 result = insertAnnotationsToMostInner(result, annotations, false);
1063 }
1064
1065 return result;
1066 }
1067
1068 protected JCExpression parseIntersectionType(int pos, JCExpression firstType) {
1069 JCExpression t = firstType;
1070 int pos1 = pos;
1071 List<JCExpression> targets = List.of(t);
1072 while (token.kind == AMP) {
1073 accept(AMP);
1074 targets = targets.prepend(parseType());
1075 }
1076 if (targets.length() > 1) {
1077 t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
1078 }
1079 return t;
1080 }
1081
1082 public JCExpression unannotatedType(boolean allowVar) {
1083 return unannotatedType(allowVar, TYPE);
1084 }
1085
1086 public JCExpression unannotatedType(boolean allowVar, int newmode) {
1087 JCExpression result = term(newmode);
1088 Name restrictedTypeName = restrictedTypeName(result, !allowVar);
1089
1090 if (restrictedTypeName != null && (!allowVar || restrictedTypeName != names.var)) {
1091 syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
1092 }
1093
1094 if ((lastmode & TYPE) == 0) {
1095 //if the mode was switched to expression while expecting type, wrap with Erroneous:
1096 result = F.Erroneous(List.of(result));
1097 }
1098
1099 return result;
1100 }
1101
1102
1103
1104 protected JCExpression term(int newmode) {
1105 int prevmode = mode;
1106 setMode(newmode);
1107 JCExpression t = term();
1108 setLastMode(mode);
1109 setMode(prevmode);
1110 return t;
1111 }
1112
1113 /**
1114 * {@literal
1115 * Expression = Expression1 [ExpressionRest]
1116 * ExpressionRest = [AssignmentOperator Expression1]
1117 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
1118 * "&=" | "|=" | "^=" |
1119 * "%=" | "<<=" | ">>=" | ">>>="
1120 * Type = Type1
1121 * TypeNoParams = TypeNoParams1
1122 * StatementExpression = Expression
1123 * ConstantExpression = Expression
1124 * }
1125 */
1126 JCExpression term() {
1127 JCExpression t = term1();
1128 if (isMode(EXPR) &&
1129 (token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0))
1130 return termRest(t);
1131 else
1132 return t;
1133 }
1134
1135 JCExpression termRest(JCExpression t) {
1136 switch (token.kind) {
1137 case EQ: {
1138 int pos = token.pos;
1139 nextToken();
1140 selectExprMode();
1141 JCExpression t1 = term();
1142 return toP(F.at(pos).Assign(t, t1));
1143 }
1144 case PLUSEQ:
1145 case SUBEQ:
1146 case STAREQ:
1147 case SLASHEQ:
1148 case PERCENTEQ:
1149 case AMPEQ:
1150 case BAREQ:
1151 case CARETEQ:
1152 case LTLTEQ:
1153 case GTGTEQ:
1154 case GTGTGTEQ:
1155 int pos = token.pos;
1156 TokenKind tk = token.kind;
1157 nextToken();
1158 selectExprMode();
1159 JCExpression t1 = term();
1160 return F.at(pos).Assignop(optag(tk), t, t1);
1161 default:
1162 return t;
1163 }
1164 }
1165
1166 /** Expression1 = Expression2 [Expression1Rest]
1167 * Type1 = Type2
1168 * TypeNoParams1 = TypeNoParams2
1169 */
1170 JCExpression term1() {
1171 JCExpression t = term2();
1172 if (isMode(EXPR) && token.kind == QUES) {
1173 selectExprMode();
1174 return term1Rest(t);
1175 } else {
1176 return t;
1177 }
1178 }
1179
1180 /** Expression1Rest = ["?" Expression ":" Expression1]
1181 */
1182 JCExpression term1Rest(JCExpression t) {
1183 if (token.kind == QUES) {
1184 int pos = token.pos;
1185 nextToken();
1186 JCExpression t1 = term();
1187 accept(COLON);
1188 JCExpression t2 = term1();
1189 return F.at(pos).Conditional(t, t1, t2);
1190 } else {
1191 return t;
1192 }
1193 }
1194
1195 /** Expression2 = Expression3 [Expression2Rest]
1196 * Type2 = Type3
1197 * TypeNoParams2 = TypeNoParams3
1198 */
1199 JCExpression term2() {
1200 JCExpression t = term3();
1201 if (isMode(EXPR) && prec(token.kind) >= TreeInfo.orPrec) {
1202 selectExprMode();
1203 return term2Rest(t, TreeInfo.orPrec);
1204 } else {
1205 return t;
1206 }
1207 }
1208
1209 /* Expression2Rest = {infixop Expression3}
1210 * | Expression3 instanceof Type
1211 * | Expression3 instanceof Pattern
1212 * infixop = "||"
1213 * | "&&"
1214 * | "|"
1215 * | "^"
1216 * | "&"
1217 * | "==" | "!="
1218 * | "<" | ">" | "<=" | ">="
1219 * | "<<" | ">>" | ">>>"
1220 * | "+" | "-"
1221 * | "*" | "/" | "%"
1222 */
1223 JCExpression term2Rest(JCExpression t, int minprec) {
1224 JCExpression[] odStack = newOdStack();
1225 Token[] opStack = newOpStack();
1226
1227 // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
1228 int top = 0;
1229 odStack[0] = t;
1230 int startPos = token.pos;
1231 Token topOp = Tokens.DUMMY;
1232 while (prec(token.kind) >= minprec) {
1233 opStack[top] = topOp;
1234
1235 if (token.kind == INSTANCEOF) {
1236 int pos = token.pos;
1237 nextToken();
1238 JCTree pattern;
1239 if (token.kind == LPAREN) {
1240 checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
1241 pattern = parsePattern(token.pos, null, null, false, false);
1242 } else {
1243 int patternPos = token.pos;
1244 JCModifiers mods = optFinal(0);
1245 int typePos = token.pos;
1246 JCExpression type = unannotatedType(false);
1247 if (token.kind == IDENTIFIER) {
1248 checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF);
1249 pattern = parsePattern(patternPos, mods, type, false, false);
1250 } else if (token.kind == LPAREN) {
1251 pattern = parsePattern(patternPos, mods, type, false, false);
1252 } else if (token.kind == UNDERSCORE) {
1253 checkSourceLevel(token.pos, Feature.UNNAMED_VARIABLES);
1254 pattern = parsePattern(patternPos, mods, type, false, false);
1255 } else {
1256 checkNoMods(typePos, mods.flags & ~Flags.DEPRECATED);
1257 if (mods.annotations.nonEmpty()) {
1258 List<JCAnnotation> typeAnnos =
1259 mods.annotations
1260 .map(decl -> {
1261 JCAnnotation typeAnno = F.at(decl.pos)
1262 .TypeAnnotation(decl.annotationType,
1263 decl.args);
1264 typeAnno.endpos = decl.endpos;
1265 return typeAnno;
1266 });
1267 type = insertAnnotationsToMostInner(type, typeAnnos, false);
1268 }
1269 pattern = type;
1270 }
1271 }
1272 odStack[top] = F.at(pos).TypeTest(odStack[top], pattern);
1273 } else {
1274 topOp = token;
1275 nextToken();
1276 top++;
1277 odStack[top] = term3();
1278 }
1279 while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
1280 odStack[top - 1] = F.at(topOp.pos).Binary(optag(topOp.kind), odStack[top - 1], odStack[top]);
1281 top--;
1282 topOp = opStack[top];
1283 }
1284 }
1285 Assert.check(top == 0);
1286 t = odStack[0];
1287
1288 if (t.hasTag(JCTree.Tag.PLUS)) {
1289 t = foldStrings(t);
1290 }
1291
1292 odStackSupply.add(odStack);
1293 opStackSupply.add(opStack);
1294 return t;
1295 }
1296 //where
1297 /** If tree is a concatenation of string literals, replace it
1298 * by a single literal representing the concatenated string.
1299 */
1300 protected JCExpression foldStrings(JCExpression tree) {
1301 if (!allowStringFolding)
1302 return tree;
1303 ListBuffer<JCExpression> opStack = new ListBuffer<>();
1304 ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
1305 boolean needsFolding = false;
1306 JCExpression curr = tree;
1307 while (true) {
1308 if (curr.hasTag(JCTree.Tag.PLUS)) {
1309 JCBinary op = (JCBinary)curr;
1310 needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
1311 curr = op.lhs;
1312 } else {
1313 needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
1314 break; //last one!
1315 }
1316 }
1317 if (needsFolding) {
1318 List<JCExpression> ops = opStack.toList();
1319 JCExpression res = ops.head;
1320 for (JCExpression op : ops.tail) {
1321 res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op);
1322 storeEnd(res, getEndPos(op));
1323 }
1324 return res;
1325 } else {
1326 return tree;
1327 }
1328 }
1329
1330 private boolean foldIfNeeded(JCExpression tree, ListBuffer<JCLiteral> litBuf,
1331 ListBuffer<JCExpression> opStack, boolean last) {
1332 JCLiteral str = stringLiteral(tree);
1333 if (str != null) {
1334 litBuf.prepend(str);
1335 return last && merge(litBuf, opStack);
1336 } else {
1337 boolean res = merge(litBuf, opStack);
1338 litBuf.clear();
1339 opStack.prepend(tree);
1340 return res;
1341 }
1342 }
1343
1344 boolean merge(ListBuffer<JCLiteral> litBuf, ListBuffer<JCExpression> opStack) {
1345 if (litBuf.isEmpty()) {
1346 return false;
1347 } else if (litBuf.size() == 1) {
1348 opStack.prepend(litBuf.first());
1349 return false;
1350 } else {
1351 JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS,
1352 litBuf.stream().map(lit -> (String)lit.getValue()).collect(Collectors.joining()));
1353 storeEnd(t, litBuf.last().getEndPosition());
1354 opStack.prepend(t);
1355 return true;
1356 }
1357 }
1358
1359 private JCLiteral stringLiteral(JCTree tree) {
1360 if (tree.hasTag(LITERAL)) {
1361 JCLiteral lit = (JCLiteral)tree;
1362 if (lit.typetag == TypeTag.CLASS) {
1363 return lit;
1364 }
1365 }
1366 return null;
1367 }
1368
1369
1370 /** optimization: To save allocating a new operand/operator stack
1371 * for every binary operation, we use supplys.
1372 */
1373 ArrayList<JCExpression[]> odStackSupply = new ArrayList<>();
1374 ArrayList<Token[]> opStackSupply = new ArrayList<>();
1375
1376 private JCExpression[] newOdStack() {
1377 if (odStackSupply.isEmpty())
1378 return new JCExpression[infixPrecedenceLevels + 1];
1379 return odStackSupply.remove(odStackSupply.size() - 1);
1380 }
1381
1382 private Token[] newOpStack() {
1383 if (opStackSupply.isEmpty())
1384 return new Token[infixPrecedenceLevels + 1];
1385 return opStackSupply.remove(opStackSupply.size() - 1);
1386 }
1387
1388 /**
1389 * Expression3 = PrefixOp Expression3
1390 * | "(" Expr | TypeNoParams ")" Expression3
1391 * | Primary {Selector} {PostfixOp}
1392 *
1393 * {@literal
1394 * Primary = "(" Expression ")"
1395 * | Literal
1396 * | [TypeArguments] THIS [Arguments]
1397 * | [TypeArguments] SUPER SuperSuffix
1398 * | NEW [TypeArguments] Creator
1399 * | "(" Arguments ")" "->" ( Expression | Block )
1400 * | Ident "->" ( Expression | Block )
1401 * | [Annotations] Ident { "." [Annotations] Ident }
1402 * | Expression3 MemberReferenceSuffix
1403 * [ [Annotations] "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
1404 * | Arguments
1405 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
1406 * ]
1407 * | BasicType BracketsOpt "." CLASS
1408 * }
1409 *
1410 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
1411 * PostfixOp = "++" | "--"
1412 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
1413 * | BasicType
1414 * TypeNoParams3 = Ident { "." Ident } BracketsOpt
1415 * Selector = "." [TypeArguments] Ident [Arguments]
1416 * | "." THIS
1417 * | "." [TypeArguments] SUPER SuperSuffix
1418 * | "." NEW [TypeArguments] InnerCreator
1419 * | "[" Expression "]"
1420 * TypeSelector = "." Ident [TypeArguments]
1421 * SuperSuffix = Arguments | "." Ident [Arguments]
1422 */
1423 protected JCExpression term3() {
1424 int pos = token.pos;
1425 JCExpression t;
1426 int startMode = mode;
1427 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
1428 switch (token.kind) {
1429 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
1430 if (typeArgs == null && isMode(EXPR)) {
1431 TokenKind tk = token.kind;
1432 nextToken();
1433 selectExprMode();
1434 if (tk == SUB &&
1435 (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
1436 token.radix() == 10) {
1437 selectExprMode();
1438 t = literal(names.hyphen, pos);
1439 } else {
1440 t = term3();
1441 return F.at(pos).Unary(unoptag(tk), t);
1442 }
1443 } else return illegal();
1444 break;
1445 case LPAREN:
1446 if (typeArgs == null && isMode(EXPR)) {
1447 ParensResult pres = analyzeParens();
1448 switch (pres) {
1449 case CAST:
1450 accept(LPAREN);
1451 selectTypeMode();
1452 t = parseIntersectionType(pos, parseType());
1453 accept(RPAREN);
1454 selectExprMode();
1455 JCExpression t1 = term3();
1456 return F.at(pos).TypeCast(t, t1);
1457 case IMPLICIT_LAMBDA:
1458 case EXPLICIT_LAMBDA:
1459 t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
1460 break;
1461 default: //PARENS
1462 accept(LPAREN);
1463 selectExprMode();
1464 t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec)));
1465 accept(RPAREN);
1466 t = toP(F.at(pos).Parens(t));
1467 break;
1468 }
1469 } else {
1470 return illegal();
1471 }
1472 break;
1473 case THIS:
1474 if (isMode(EXPR)) {
1475 selectExprMode();
1476 t = to(F.at(pos).Ident(names._this));
1477 nextToken();
1478 if (typeArgs == null)
1479 t = argumentsOpt(null, t);
1480 else
1481 t = arguments(typeArgs, t);
1482 typeArgs = null;
1483 } else return illegal();
1484 break;
1485 case SUPER:
1486 if (isMode(EXPR)) {
1487 selectExprMode();
1488 t = to(F.at(pos).Ident(names._super));
1489 t = superSuffix(typeArgs, t);
1490 typeArgs = null;
1491 } else return illegal();
1492 break;
1493 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
1494 case CHARLITERAL: case STRINGLITERAL:
1495 case TRUE: case FALSE: case NULL:
1496 if (typeArgs == null && isMode(EXPR)) {
1497 selectExprMode();
1498 t = literal(names.empty);
1499 } else return illegal();
1500 break;
1501 case NEW:
1502 if (typeArgs != null) return illegal();
1503 if (isMode(EXPR)) {
1504 selectExprMode();
1505 nextToken();
1506 if (token.kind == LT) typeArgs = typeArguments();
1507 t = creator(pos, typeArgs);
1508 typeArgs = null;
1509 } else return illegal();
1510 break;
1511 case MONKEYS_AT:
1512 // Only annotated cast types and method references are valid
1513 List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
1514 if (typeAnnos.isEmpty()) {
1515 // else there would be no '@'
1516 throw new AssertionError("Expected type annotations, but found none!");
1517 }
1518
1519 JCExpression expr = term3();
1520
1521 if (!isMode(TYPE)) {
1522 // Type annotations on class literals no longer legal
1523 switch (expr.getTag()) {
1524 case REFERENCE: {
1525 JCMemberReference mref = (JCMemberReference) expr;
1526 if (TreeInfo.isType(mref.expr, names)) {
1527 mref.expr = insertAnnotationsToMostInner(mref.expr, typeAnnos, false);
1528 } else {
1529 //the selector is not a type, error recovery:
1530 JCAnnotatedType annotatedType =
1531 toP(F.at(pos).AnnotatedType(typeAnnos, mref.expr));
1532 int termStart = getStartPos(mref.expr);
1533 mref.expr = syntaxError(termStart, List.of(annotatedType),
1534 Errors.IllegalStartOfType);
1535 }
1536 mref.pos = getStartPos(mref.expr);
1537 t = mref;
1538 break;
1539 }
1540 case SELECT: {
1541 JCFieldAccess sel = (JCFieldAccess) expr;
1542
1543 if (sel.name != names._class) {
1544 return illegal();
1545 } else {
1546 log.error(token.pos, Errors.NoAnnotationsOnDotClass);
1547 return expr;
1548 }
1549 }
1550 default:
1551 return illegal(typeAnnos.head.pos);
1552 }
1553
1554 } else {
1555 // Type annotations targeting a cast
1556 t = insertAnnotationsToMostInner(expr, typeAnnos, false);
1557 }
1558 break;
1559 case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM:
1560 if (typeArgs != null) return illegal();
1561 if (isMode(EXPR) && !isMode(NOLAMBDA) && peekToken(ARROW)) {
1562 t = lambdaExpressionOrStatement(false, false, pos);
1563 } else {
1564 t = toP(F.at(token.pos).Ident(ident()));
1565 loop: while (true) {
1566 pos = token.pos;
1567 final List<JCAnnotation> annos = typeAnnotationsOpt();
1568
1569 // need to report an error later if LBRACKET is for array
1570 // index access rather than array creation level
1571 if (!annos.isEmpty() && token.kind != LBRACKET && token.kind != ELLIPSIS)
1572 return illegal(annos.head.pos);
1573
1574 switch (token.kind) {
1575 case LBRACKET:
1576 nextToken();
1577 if (token.kind == RBRACKET) {
1578 nextToken();
1579 t = bracketsOpt(t);
1580 t = toP(F.at(pos).TypeArray(t));
1581 if (annos.nonEmpty()) {
1582 t = toP(F.at(pos).AnnotatedType(annos, t));
1583 }
1584 t = bracketsSuffix(t);
1585 } else {
1586 if (isMode(EXPR)) {
1587 selectExprMode();
1588 JCExpression t1 = term();
1589 if (!annos.isEmpty()) t = illegal(annos.head.pos);
1590 t = to(F.at(pos).Indexed(t, t1));
1591 }
1592 accept(RBRACKET);
1593 }
1594 break loop;
1595 case LPAREN:
1596 if (isMode(EXPR)) {
1597 selectExprMode();
1598 t = arguments(typeArgs, t);
1599 if (!annos.isEmpty()) t = illegal(annos.head.pos);
1600 typeArgs = null;
1601 }
1602 break loop;
1603 case DOT:
1604 nextToken();
1605 if (token.kind == TokenKind.IDENTIFIER && typeArgs != null) {
1606 return illegal();
1607 }
1608 int prevmode = mode;
1609 typeArgs = typeArgumentsOpt(EXPR);
1610 setMode(prevmode);
1611 if (isMode(EXPR)) {
1612 switch (token.kind) {
1613 case CLASS:
1614 if (typeArgs != null) return illegal();
1615 selectExprMode();
1616 t = to(F.at(pos).Select(t, names._class));
1617 nextToken();
1618 break loop;
1619 case THIS:
1620 if (typeArgs != null) return illegal();
1621 selectExprMode();
1622 t = to(F.at(pos).Select(t, names._this));
1623 nextToken();
1624 break loop;
1625 case SUPER:
1626 selectExprMode();
1627 t = to(F.at(pos).Select(t, names._super));
1628 t = superSuffix(typeArgs, t);
1629 typeArgs = null;
1630 break loop;
1631 case NEW:
1632 if (typeArgs != null) return illegal();
1633 selectExprMode();
1634 int pos1 = token.pos;
1635 nextToken();
1636 if (token.kind == LT) typeArgs = typeArguments();
1637 t = innerCreator(pos1, typeArgs, t);
1638 typeArgs = null;
1639 break loop;
1640 }
1641 }
1642
1643 List<JCAnnotation> tyannos = null;
1644 if (isMode(TYPE) && token.kind == MONKEYS_AT) {
1645 tyannos = typeAnnotationsOpt();
1646 }
1647 // typeArgs saved for next loop iteration.
1648 t = toP(F.at(pos).Select(t, ident()));
1649 if (token.pos <= errorEndPos &&
1650 token.kind == MONKEYS_AT) {
1651 //error recovery, case like:
1652 //int i = expr.<missing-ident>
1653 //@Deprecated
1654 if (typeArgs != null) illegal();
1655 return toP(t);
1656 }
1657 if (tyannos != null && tyannos.nonEmpty()) {
1658 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1659 }
1660 break;
1661 case ELLIPSIS:
1662 if (this.permitTypeAnnotationsPushBack) {
1663 this.typeAnnotationsPushedBack = annos;
1664 } else if (annos.nonEmpty()) {
1665 // Don't return here -- error recovery attempt
1666 illegal(annos.head.pos);
1667 }
1668 break loop;
1669 case LT:
1670 if (!isMode(TYPE) && isUnboundMemberRef()) {
1671 //this is an unbound method reference whose qualifier
1672 //is a generic type i.e. A<S>::m
1673 int pos1 = token.pos;
1674 accept(LT);
1675 ListBuffer<JCExpression> args = new ListBuffer<>();
1676 args.append(typeArgument());
1677 while (token.kind == COMMA) {
1678 nextToken();
1679 args.append(typeArgument());
1680 }
1681 accept(GT);
1682 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1683 while (token.kind == DOT) {
1684 nextToken();
1685 selectTypeMode();
1686 t = toP(F.at(token.pos).Select(t, ident()));
1687 t = typeApplyOpt(t);
1688 }
1689 t = bracketsOpt(t);
1690 if (token.kind != COLCOL) {
1691 //method reference expected here
1692 t = illegal();
1693 }
1694 selectExprMode();
1695 return term3Rest(t, typeArgs);
1696 }
1697 break loop;
1698 default:
1699 break loop;
1700 }
1701 }
1702 }
1703 if (typeArgs != null) illegal();
1704 t = typeApplyOpt(t);
1705 break;
1706 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1707 case DOUBLE: case BOOLEAN:
1708 if (typeArgs != null) illegal();
1709 t = bracketsSuffix(bracketsOpt(basicType()));
1710 break;
1711 case VOID:
1712 if (typeArgs != null) illegal();
1713 if (isMode(EXPR)) {
1714 nextToken();
1715 if (token.kind == DOT) {
1716 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTag.VOID));
1717 t = bracketsSuffix(ti);
1718 } else {
1719 return illegal(pos);
1720 }
1721 } else {
1722 // Support the corner case of myMethodHandle.<void>invoke() by passing
1723 // a void type (like other primitive types) to the next phase.
1724 // The error will be reported in Attr.attribTypes or Attr.visitApply.
1725 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTag.VOID));
1726 nextToken();
1727 return ti;
1728 //return illegal();
1729 }
1730 break;
1731 case SWITCH:
1732 checkSourceLevel(Feature.SWITCH_EXPRESSION);
1733 allowYieldStatement = true;
1734 int switchPos = token.pos;
1735 nextToken();
1736 JCExpression selector = parExpression();
1737 accept(LBRACE);
1738 ListBuffer<JCCase> cases = new ListBuffer<>();
1739 while (true) {
1740 pos = token.pos;
1741 switch (token.kind) {
1742 case CASE:
1743 case DEFAULT:
1744 cases.appendList(switchExpressionStatementGroup());
1745 break;
1746 case RBRACE: case EOF:
1747 JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
1748 cases.toList()));
1749 e.bracePos = token.pos;
1750 accept(RBRACE);
1751 return e;
1752 default:
1753 nextToken(); // to ensure progress
1754 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
1755 }
1756 }
1757 // Not reachable.
1758 default:
1759 if (typeArgs != null && (startMode & TYPE) != 0) {
1760 return F.at(pos).TypeApply(F.Erroneous(), typeArgs);
1761 }
1762 return illegal();
1763 }
1764 return term3Rest(t, typeArgs);
1765 }
1766
1767 private List<JCCase> switchExpressionStatementGroup() {
1768 ListBuffer<JCCase> caseExprs = new ListBuffer<>();
1769 int casePos = token.pos;
1770 ListBuffer<JCCaseLabel> pats = new ListBuffer<>();
1771
1772 if (token.kind == DEFAULT) {
1773 nextToken();
1774 pats.append(toP(F.at(casePos).DefaultCaseLabel()));
1775 } else {
1776 accept(CASE);
1777 boolean allowDefault = false;
1778 while (true) {
1779 JCCaseLabel label = parseCaseLabel(allowDefault);
1780 pats.append(label);
1781 if (token.kind != COMMA) break;
1782 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
1783 nextToken();
1784 allowDefault = TreeInfo.isNullCaseLabel(label);
1785 };
1786 }
1787 JCExpression guard = parseGuard(pats.last());
1788 List<JCStatement> stats = null;
1789 JCTree body = null;
1790 CaseTree.CaseKind kind;
1791 switch (token.kind) {
1792 case ARROW:
1793 checkSourceLevel(Feature.SWITCH_RULE);
1794 nextToken();
1795 if (token.kind == TokenKind.THROW || token.kind == TokenKind.LBRACE) {
1796 stats = List.of(parseStatement());
1797 body = stats.head;
1798 kind = JCCase.RULE;
1799 } else {
1800 JCExpression value = parseExpression();
1801 stats = List.of(to(F.at(value).Yield(value)));
1802 body = value;
1803 kind = JCCase.RULE;
1804 accept(SEMI);
1805 }
1806 break;
1807 default:
1808 accept(COLON, tk -> Errors.Expected2(COLON, ARROW));
1809 stats = blockStatements();
1810 kind = JCCase.STATEMENT;
1811 break;
1812 }
1813 caseExprs.append(toP(F.at(casePos).Case(kind, pats.toList(), guard, stats, body)));
1814 return caseExprs.toList();
1815 }
1816
1817 JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) {
1818 if (typeArgs != null) illegal();
1819 while (true) {
1820 int pos1 = token.pos;
1821 final List<JCAnnotation> annos = typeAnnotationsOpt();
1822
1823 if (token.kind == LBRACKET) {
1824 nextToken();
1825 if (isMode(TYPE)) {
1826 int prevmode = mode;
1827 selectTypeMode();
1828 if (token.kind == RBRACKET) {
1829 nextToken();
1830 t = bracketsOpt(t);
1831 t = toP(F.at(pos1).TypeArray(t));
1832 if (token.kind == COLCOL) {
1833 selectExprMode();
1834 continue;
1835 }
1836 if (annos.nonEmpty()) {
1837 t = toP(F.at(pos1).AnnotatedType(annos, t));
1838 }
1839 return t;
1840 }
1841 setMode(prevmode);
1842 }
1843 if (isMode(EXPR)) {
1844 selectExprMode();
1845 JCExpression t1 = term();
1846 t = to(F.at(pos1).Indexed(t, t1));
1847 }
1848 accept(RBRACKET);
1849 } else if (token.kind == DOT) {
1850 nextToken();
1851 typeArgs = typeArgumentsOpt(EXPR);
1852 if (token.kind == SUPER && isMode(EXPR)) {
1853 selectExprMode();
1854 t = to(F.at(pos1).Select(t, names._super));
1855 nextToken();
1856 t = arguments(typeArgs, t);
1857 typeArgs = null;
1858 } else if (token.kind == NEW && isMode(EXPR)) {
1859 if (typeArgs != null) return illegal();
1860 selectExprMode();
1861 int pos2 = token.pos;
1862 nextToken();
1863 if (token.kind == LT) typeArgs = typeArguments();
1864 t = innerCreator(pos2, typeArgs, t);
1865 typeArgs = null;
1866 } else {
1867 List<JCAnnotation> tyannos = null;
1868 if (isMode(TYPE) && token.kind == MONKEYS_AT) {
1869 // is the mode check needed?
1870 tyannos = typeAnnotationsOpt();
1871 }
1872 t = toP(F.at(pos1).Select(t, ident(true)));
1873 if (token.pos <= errorEndPos &&
1874 token.kind == MONKEYS_AT) {
1875 //error recovery, case like:
1876 //int i = expr.<missing-ident>
1877 //@Deprecated
1878 break;
1879 }
1880 if (tyannos != null && tyannos.nonEmpty()) {
1881 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1882 }
1883 t = argumentsOpt(typeArgs, typeApplyOpt(t));
1884 typeArgs = null;
1885 }
1886 } else if (isMode(EXPR) && token.kind == COLCOL) {
1887 selectExprMode();
1888 if (typeArgs != null) return illegal();
1889 accept(COLCOL);
1890 t = memberReferenceSuffix(pos1, t);
1891 } else {
1892 if (!annos.isEmpty()) {
1893 if (permitTypeAnnotationsPushBack)
1894 typeAnnotationsPushedBack = annos;
1895 else
1896 return illegal(annos.head.pos);
1897 }
1898 break;
1899 }
1900 }
1901 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1902 selectExprMode();
1903 t = to(F.at(token.pos).Unary(
1904 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1905 nextToken();
1906 }
1907 return toP(t);
1908 }
1909
1910 /**
1911 * If we see an identifier followed by a '<' it could be an unbound
1912 * method reference or a binary expression. To disambiguate, look for a
1913 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1914 */
1915 @SuppressWarnings("fallthrough")
1916 boolean isUnboundMemberRef() {
1917 int pos = 0, depth = 0;
1918 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1919 switch (t.kind) {
1920 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1921 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1922 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1923 case DOUBLE: case BOOLEAN: case CHAR:
1924 case MONKEYS_AT:
1925 break;
1926
1927 case LPAREN:
1928 // skip annotation values
1929 int nesting = 0;
1930 for (; ; pos++) {
1931 TokenKind tk2 = S.token(pos).kind;
1932 switch (tk2) {
1933 case EOF:
1934 return false;
1935 case LPAREN:
1936 nesting++;
1937 break;
1938 case RPAREN:
1939 nesting--;
1940 if (nesting == 0) {
1941 continue outer;
1942 }
1943 break;
1944 }
1945 }
1946
1947 case LT:
1948 depth++; break;
1949 case GTGTGT:
1950 depth--;
1951 case GTGT:
1952 depth--;
1953 case GT:
1954 depth--;
1955 if (depth == 0) {
1956 TokenKind nextKind = S.token(pos + 1).kind;
1957 return
1958 nextKind == TokenKind.DOT ||
1959 nextKind == TokenKind.LBRACKET ||
1960 nextKind == TokenKind.COLCOL;
1961 }
1962 break;
1963 default:
1964 return false;
1965 }
1966 }
1967 }
1968
1969 /**
1970 * If we see an identifier followed by a '<' it could be an unbound
1971 * method reference or a binary expression. To disambiguate, look for a
1972 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1973 */
1974 @SuppressWarnings("fallthrough")
1975 ParensResult analyzeParens() {
1976 int depth = 0;
1977 boolean type = false;
1978 ParensResult defaultResult = ParensResult.PARENS;
1979 outer: for (int lookahead = 0; ; lookahead++) {
1980 TokenKind tk = S.token(lookahead).kind;
1981 switch (tk) {
1982 case COMMA:
1983 type = true;
1984 case EXTENDS: case SUPER: case DOT: case AMP:
1985 //skip
1986 break;
1987 case QUES:
1988 if (peekToken(lookahead, EXTENDS) ||
1989 peekToken(lookahead, SUPER)) {
1990 //wildcards
1991 type = true;
1992 }
1993 break;
1994 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1995 case DOUBLE: case BOOLEAN: case CHAR: case VOID:
1996 if (peekToken(lookahead, RPAREN)) {
1997 //Type, ')' -> cast
1998 return ParensResult.CAST;
1999 } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
2000 //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
2001 return ParensResult.EXPLICIT_LAMBDA;
2002 }
2003 break;
2004 case LPAREN:
2005 if (lookahead != 0) {
2006 // '(' in a non-starting position -> parens
2007 return ParensResult.PARENS;
2008 } else if (peekToken(lookahead, RPAREN)) {
2009 // '(', ')' -> explicit lambda
2010 return ParensResult.EXPLICIT_LAMBDA;
2011 }
2012 break;
2013 case RPAREN:
2014 // if we have seen something that looks like a type,
2015 // then it's a cast expression
2016 if (type) return ParensResult.CAST;
2017 // otherwise, disambiguate cast vs. parenthesized expression
2018 // based on subsequent token.
2019 switch (S.token(lookahead + 1).kind) {
2020 /*case PLUSPLUS: case SUBSUB: */
2021 case BANG: case TILDE:
2022 case LPAREN: case THIS: case SUPER:
2023 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
2024 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
2025 case STRINGFRAGMENT:
2026 case TRUE: case FALSE: case NULL:
2027 case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
2028 case SWITCH:
2029 case BYTE: case SHORT: case CHAR: case INT:
2030 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
2031 return ParensResult.CAST;
2032 default:
2033 return defaultResult;
2034 }
2035 case UNDERSCORE:
2036 case ASSERT:
2037 case ENUM:
2038 case IDENTIFIER:
2039 if (peekToken(lookahead, LAX_IDENTIFIER)) {
2040 // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
2041 return ParensResult.EXPLICIT_LAMBDA;
2042 } else if (peekToken(lookahead, RPAREN, ARROW)) {
2043 // Identifier, ')' '->' -> implicit lambda
2044 return !isMode(NOLAMBDA) ? ParensResult.IMPLICIT_LAMBDA
2045 : ParensResult.PARENS;
2046 } else if (depth == 0 && peekToken(lookahead, COMMA)) {
2047 defaultResult = ParensResult.IMPLICIT_LAMBDA;
2048 }
2049 type = false;
2050 break;
2051 case FINAL:
2052 case ELLIPSIS:
2053 //those can only appear in explicit lambdas
2054 return ParensResult.EXPLICIT_LAMBDA;
2055 case MONKEYS_AT:
2056 type = true;
2057 lookahead = skipAnnotation(lookahead);
2058 break;
2059 case LBRACKET:
2060 if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
2061 // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
2062 return ParensResult.EXPLICIT_LAMBDA;
2063 } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
2064 peekToken(lookahead, RBRACKET, AMP)) {
2065 // '[', ']', ')' -> cast
2066 // '[', ']', '&' -> cast (intersection type)
2067 return ParensResult.CAST;
2068 } else if (peekToken(lookahead, RBRACKET)) {
2069 //consume the ']' and skip
2070 type = true;
2071 lookahead++;
2072 break;
2073 } else {
2074 return ParensResult.PARENS;
2075 }
2076 case LT:
2077 depth++; break;
2078 case GTGTGT:
2079 depth--;
2080 case GTGT:
2081 depth--;
2082 case GT:
2083 depth--;
2084 if (depth == 0) {
2085 if (peekToken(lookahead, RPAREN) ||
2086 peekToken(lookahead, AMP)) {
2087 // '>', ')' -> cast
2088 // '>', '&' -> cast
2089 return ParensResult.CAST;
2090 } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
2091 peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
2092 peekToken(lookahead, ELLIPSIS)) {
2093 // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
2094 // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
2095 // '>', '...' -> explicit lambda
2096 return ParensResult.EXPLICIT_LAMBDA;
2097 }
2098 //it looks a type, but could still be (i) a cast to generic type,
2099 //(ii) an unbound method reference or (iii) an explicit lambda
2100 type = true;
2101 break;
2102 } else if (depth < 0) {
2103 //unbalanced '<', '>' - not a generic type
2104 return ParensResult.PARENS;
2105 }
2106 break;
2107 default:
2108 //this includes EOF
2109 return defaultResult;
2110 }
2111 }
2112 }
2113
2114 private int skipAnnotation(int lookahead) {
2115 lookahead += 1; //skip '@'
2116 while (peekToken(lookahead, DOT)) {
2117 lookahead += 2;
2118 }
2119 if (peekToken(lookahead, LPAREN)) {
2120 lookahead++;
2121 //skip annotation values
2122 int nesting = 0;
2123 for (; ; lookahead++) {
2124 TokenKind tk2 = S.token(lookahead).kind;
2125 switch (tk2) {
2126 case EOF:
2127 return lookahead;
2128 case LPAREN:
2129 nesting++;
2130 break;
2131 case RPAREN:
2132 nesting--;
2133 if (nesting == 0) {
2134 return lookahead;
2135 }
2136 break;
2137 }
2138 }
2139 }
2140 return lookahead;
2141 }
2142
2143 /** Accepts all identifier-like tokens */
2144 protected Predicate<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
2145
2146 enum ParensResult {
2147 CAST,
2148 EXPLICIT_LAMBDA,
2149 IMPLICIT_LAMBDA,
2150 PARENS
2151 }
2152
2153 JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
2154 List<JCVariableDecl> params = explicitParams ?
2155 formalParameters(true, false) :
2156 implicitParameters(hasParens);
2157 if (explicitParams) {
2158 LambdaClassifier lambdaClassifier = new LambdaClassifier();
2159 for (JCVariableDecl param: params) {
2160 Name restrictedTypeName;
2161 if (param.vartype != null &&
2162 (restrictedTypeName = restrictedTypeName(param.vartype, false)) != null &&
2163 param.vartype.hasTag(TYPEARRAY)) {
2164 log.error(DiagnosticFlag.SYNTAX, param.pos,
2165 Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source)
2166 ? Errors.RestrictedTypeNotAllowedArray(restrictedTypeName) : Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
2167 }
2168 lambdaClassifier.addParameter(param);
2169 if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
2170 break;
2171 }
2172 }
2173 if (lambdaClassifier.diagFragment != null) {
2174 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidLambdaParameterDeclaration(lambdaClassifier.diagFragment));
2175 }
2176 for (JCVariableDecl param: params) {
2177 if (param.vartype != null
2178 && restrictedTypeName(param.vartype, true) != null) {
2179 checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
2180 param.declKind = JCVariableDecl.DeclKind.VAR;
2181 param.typePos = TreeInfo.getStartPos(param.vartype);
2182 param.vartype = null;
2183 }
2184 }
2185 }
2186 return lambdaExpressionOrStatementRest(params, pos);
2187 }
2188
2189 enum LambdaParameterKind {
2190 VAR(0),
2191 EXPLICIT(1),
2192 IMPLICIT(2),
2193 ERROR(-1);
2194
2195 private final int index;
2196
2197 LambdaParameterKind(int index) {
2198 this.index = index;
2199 }
2200 }
2201
2202 private static final Fragment[][] decisionTable = new Fragment[][] {
2203 /* VAR EXPLICIT IMPLICIT */
2204 /* VAR */ {null, VarAndExplicitNotAllowed, VarAndImplicitNotAllowed},
2205 /* EXPLICIT */ {VarAndExplicitNotAllowed, null, ImplicitAndExplicitNotAllowed},
2206 /* IMPLICIT */ {VarAndImplicitNotAllowed, ImplicitAndExplicitNotAllowed, null},
2207 };
2208
2209 class LambdaClassifier {
2210 LambdaParameterKind kind;
2211 Fragment diagFragment;
2212
2213 /**
2214 * analyzeParens() has already classified the lambda as EXPLICIT_LAMBDA, due to
2215 * two consecutive identifiers. Because of that {@code (<explicit lambda>)}, the
2216 * parser will always attempt to parse a type, followed by a name. If the lambda
2217 * contains an illegal mix of implicit and explicit parameters, it is possible
2218 * for the parser to see a {@code ,} when expecting a name, in which case the
2219 * variable is created with an erroneous name. The logic below makes sure that
2220 * the lambda parameters are all declared with either an explicit type (e.g.
2221 * {@code String x}), or with an inferred type (using {@code var x}). Any other
2222 * combination is rejected.
2223 * */
2224 void addParameter(JCVariableDecl param) {
2225 Assert.check(param.vartype != null);
2226
2227 if (param.name == names.error) {
2228 reduce(LambdaParameterKind.IMPLICIT);
2229 }
2230 else if (restrictedTypeName(param.vartype, false) != null) {
2231 reduce(LambdaParameterKind.VAR);
2232 } else {
2233 reduce(LambdaParameterKind.EXPLICIT);
2234 }
2235 }
2236
2237 private void reduce(LambdaParameterKind newKind) {
2238 if (kind == null) {
2239 kind = newKind;
2240 } else if (kind != newKind && kind != LambdaParameterKind.ERROR) {
2241 LambdaParameterKind currentKind = kind;
2242 kind = LambdaParameterKind.ERROR;
2243 boolean varIndex = currentKind.index == LambdaParameterKind.VAR.index ||
2244 newKind.index == LambdaParameterKind.VAR.index;
2245 diagFragment = Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source) || !varIndex ?
2246 decisionTable[currentKind.index][newKind.index] : null;
2247 }
2248 }
2249
2250 LambdaParameterKind result() {
2251 return kind;
2252 }
2253 }
2254
2255 JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
2256 accept(ARROW);
2257
2258 return token.kind == LBRACE ?
2259 lambdaStatement(args, pos, token.pos) :
2260 lambdaExpression(args, pos);
2261 }
2262
2263 JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) {
2264 JCBlock block = block(pos2, 0);
2265 return toP(F.at(pos).Lambda(args, block));
2266 }
2267
2268 JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) {
2269 JCTree expr = parseExpression();
2270 return toP(F.at(pos).Lambda(args, expr));
2271 }
2272
2273 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
2274 */
2275 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
2276 nextToken();
2277 if (token.kind == LPAREN || typeArgs != null) {
2278 t = arguments(typeArgs, t);
2279 } else if (token.kind == COLCOL) {
2280 if (typeArgs != null) return illegal();
2281 t = memberReferenceSuffix(t);
2282 } else {
2283 int pos = token.pos;
2284 accept(DOT);
2285 typeArgs = (token.kind == LT) ? typeArguments() : null;
2286 t = toP(F.at(pos).Select(t, ident()));
2287 t = argumentsOpt(typeArgs, t);
2288 }
2289 return t;
2290 }
2291
2292 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
2293 */
2294 JCPrimitiveTypeTree basicType() {
2295 JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
2296 nextToken();
2297 return t;
2298 }
2299
2300 /** ArgumentsOpt = [ Arguments ]
2301 */
2302 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
2303 if (isMode(EXPR) && token.kind == LPAREN || typeArgs != null) {
2304 selectExprMode();
2305 return arguments(typeArgs, t);
2306 } else {
2307 return t;
2308 }
2309 }
2310
2311 /** Arguments = "(" [Expression { COMMA Expression }] ")"
2312 */
2313 List<JCExpression> arguments() {
2314 ListBuffer<JCExpression> args = new ListBuffer<>();
2315 if (token.kind == LPAREN) {
2316 nextToken();
2317 if (token.kind != RPAREN) {
2318 args.append(parseExpression());
2319 while (token.kind == COMMA) {
2320 nextToken();
2321 args.append(parseExpression());
2322 }
2323 }
2324 accept(RPAREN, tk -> Errors.Expected2(RPAREN, COMMA));
2325 } else {
2326 syntaxError(token.pos, Errors.Expected(LPAREN));
2327 }
2328 return args.toList();
2329 }
2330
2331 JCExpression arguments(List<JCExpression> typeArgs, JCExpression t) {
2332 int pos = token.pos;
2333 List<JCExpression> args = arguments();
2334 JCExpression mi = F.at(pos).Apply(typeArgs, t, args);
2335 if (t.hasTag(IDENT) && isInvalidUnqualifiedMethodIdentifier(((JCIdent) t).pos,
2336 ((JCIdent) t).name)) {
2337 log.error(DiagnosticFlag.SYNTAX, t, Errors.InvalidYield);
2338 mi = F.Erroneous(List.of(mi));
2339 }
2340 return toP(mi);
2341 }
2342
2343 boolean isInvalidUnqualifiedMethodIdentifier(int pos, Name name) {
2344 if (name == names.yield) {
2345 if (allowYieldStatement) {
2346 return true;
2347 } else {
2348 log.warning(pos, Warnings.InvalidYield);
2349 }
2350 }
2351 return false;
2352 }
2353
2354 /** TypeArgumentsOpt = [ TypeArguments ]
2355 */
2356 JCExpression typeApplyOpt(JCExpression t) {
2357 if (token.kind == LT &&
2358 isMode(TYPE)) {
2359 selectTypeMode();
2360 return typeApply(t);
2361 } else {
2362 return t;
2363 }
2364 }
2365 List<JCExpression> typeArgumentsOpt() {
2366 return typeArgumentsOpt(TYPE);
2367 }
2368
2369 List<JCExpression> typeArgumentsOpt(int useMode) {
2370 if (token.kind == LT) {
2371 if (!isMode(useMode)) {
2372 illegal();
2373 }
2374 setMode(useMode);
2375 return typeArguments();
2376 }
2377 return null;
2378 }
2379
2380 /**
2381 * {@literal
2382 * TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
2383 * }
2384 */
2385 List<JCExpression> typeArguments() {
2386 if (token.kind == LT) {
2387 nextToken();
2388 ListBuffer<JCExpression> args = new ListBuffer<>();
2389 args.append(!isMode(EXPR) ? typeArgument() : parseType());
2390 while (token.kind == COMMA) {
2391 nextToken();
2392 args.append(!isMode(EXPR) ? typeArgument() : parseType());
2393 }
2394 switch (token.kind) {
2395
2396 case GTGTGTEQ: case GTGTEQ: case GTEQ:
2397 case GTGTGT: case GTGT:
2398 token = S.split();
2399 break;
2400 case GT:
2401 nextToken();
2402 break;
2403 default:
2404 args.append(syntaxError(token.pos, Errors.Expected2(GT, COMMA)));
2405 break;
2406 }
2407 return args.toList();
2408 } else {
2409 return List.of(syntaxError(token.pos, Errors.Expected(LT)));
2410 }
2411 }
2412
2413 /**
2414 * {@literal
2415 * TypeArgument = Type
2416 * | [Annotations] "?"
2417 * | [Annotations] "?" EXTENDS Type {"&" Type}
2418 * | [Annotations] "?" SUPER Type
2419 * }
2420 */
2421 JCExpression typeArgument() {
2422 List<JCAnnotation> annotations = typeAnnotationsOpt();
2423 if (token.kind != QUES) return parseType(false, annotations);
2424 int pos = token.pos;
2425 nextToken();
2426 JCExpression result;
2427 if (token.kind == EXTENDS) {
2428 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
2429 nextToken();
2430 JCExpression bound = parseType();
2431 result = F.at(pos).Wildcard(t, bound);
2432 } else if (token.kind == SUPER) {
2433 TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
2434 nextToken();
2435 JCExpression bound = parseType();
2436 result = F.at(pos).Wildcard(t, bound);
2437 } else if (LAX_IDENTIFIER.test(token.kind)) {
2438 //error recovery
2439 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
2440 JCExpression wc = toP(F.at(pos).Wildcard(t, null));
2441 JCIdent id = toP(F.at(token.pos).Ident(ident()));
2442 JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
2443 reportSyntaxError(err, Errors.Expected3(GT, EXTENDS, SUPER));
2444 result = err;
2445 } else {
2446 TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND));
2447 result = toP(F.at(pos).Wildcard(t, null));
2448 }
2449 if (!annotations.isEmpty()) {
2450 result = toP(F.at(annotations.head.pos).AnnotatedType(annotations,result));
2451 }
2452 return result;
2453 }
2454
2455 JCTypeApply typeApply(JCExpression t) {
2456 int pos = token.pos;
2457 List<JCExpression> args = typeArguments();
2458 return toP(F.at(pos).TypeApply(t, args));
2459 }
2460
2461 JCTypeApply typeApplyOrDiamond(JCExpression t) {
2462 if (peekToken(GT)) {
2463 int pos = token.pos;
2464 accept(LT);
2465 accept(GT);
2466 return toP(F.at(pos).TypeApply(t, List.nil()));
2467 } else {
2468 return typeApply(t);
2469 }
2470 }
2471
2472 /**
2473 * BracketsOpt = { [Annotations] "[" "]" }*
2474 *
2475 * <p>
2476 *
2477 * <code>annotations</code> is the list of annotations targeting
2478 * the expression <code>t</code>.
2479 */
2480 private JCExpression bracketsOpt(JCExpression t,
2481 List<JCAnnotation> annotations) {
2482 List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
2483
2484 if (token.kind == LBRACKET) {
2485 int pos = token.pos;
2486 nextToken();
2487 t = bracketsOptCont(t, pos, nextLevelAnnotations);
2488 } else if (!nextLevelAnnotations.isEmpty()) {
2489 if (permitTypeAnnotationsPushBack) {
2490 this.typeAnnotationsPushedBack = nextLevelAnnotations;
2491 } else {
2492 return illegal(nextLevelAnnotations.head.pos);
2493 }
2494 }
2495
2496 if (!annotations.isEmpty()) {
2497 t = toP(F.at(token.pos).AnnotatedType(annotations, t));
2498 }
2499 return t;
2500 }
2501
2502 /** BracketsOpt = [ "[" "]" { [Annotations] "[" "]"} ]
2503 */
2504 private JCExpression bracketsOpt(JCExpression t) {
2505 return bracketsOpt(t, List.nil());
2506 }
2507
2508 private JCExpression bracketsOptCont(JCExpression t, int pos,
2509 List<JCAnnotation> annotations) {
2510 accept(RBRACKET);
2511 t = bracketsOpt(t);
2512 t = toP(F.at(pos).TypeArray(t));
2513 if (annotations.nonEmpty()) {
2514 t = toP(F.at(pos).AnnotatedType(annotations, t));
2515 }
2516 return t;
2517 }
2518
2519 /** BracketsSuffixExpr = "." CLASS
2520 * BracketsSuffixType =
2521 */
2522 JCExpression bracketsSuffix(JCExpression t) {
2523 if (isMode(EXPR) && token.kind == DOT) {
2524 selectExprMode();
2525 int pos = token.pos;
2526 nextToken();
2527 accept(CLASS);
2528 if (token.pos == errorEndPos) {
2529 // error recovery
2530 Name name;
2531 if (LAX_IDENTIFIER.test(token.kind)) {
2532 name = token.name();
2533 nextToken();
2534 } else {
2535 name = names.error;
2536 }
2537 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
2538 } else {
2539 Tag tag = t.getTag();
2540 // Type annotations are illegal on class literals. Annotated non array class literals
2541 // are complained about directly in term3(), Here check for type annotations on dimensions
2542 // taking care to handle some interior dimension(s) being annotated.
2543 if ((tag == TYPEARRAY && TreeInfo.containsTypeAnnotation(t)) || tag == ANNOTATED_TYPE)
2544 syntaxError(token.pos, Errors.NoAnnotationsOnDotClass);
2545 t = toP(F.at(pos).Select(t, names._class));
2546 }
2547 } else if (isMode(TYPE)) {
2548 if (token.kind != COLCOL) {
2549 selectTypeMode();
2550 }
2551 } else if (token.kind != COLCOL) {
2552 syntaxError(token.pos, Errors.DotClassExpected);
2553 }
2554 return t;
2555 }
2556
2557 /**
2558 * MemberReferenceSuffix = "::" [TypeArguments] Ident
2559 * | "::" [TypeArguments] "new"
2560 */
2561 JCExpression memberReferenceSuffix(JCExpression t) {
2562 int pos1 = token.pos;
2563 accept(COLCOL);
2564 return memberReferenceSuffix(pos1, t);
2565 }
2566
2567 JCExpression memberReferenceSuffix(int pos1, JCExpression t) {
2568 selectExprMode();
2569 List<JCExpression> typeArgs = null;
2570 if (token.kind == LT) {
2571 typeArgs = typeArguments();
2572 }
2573 Name refName;
2574 ReferenceMode refMode;
2575 if (token.kind == NEW) {
2576 refMode = ReferenceMode.NEW;
2577 refName = names.init;
2578 nextToken();
2579 } else {
2580 refMode = ReferenceMode.INVOKE;
2581 refName = ident();
2582 }
2583 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2584 }
2585
2586 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2587 */
2588 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2589 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2590
2591 switch (token.kind) {
2592 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2593 case DOUBLE: case BOOLEAN:
2594 if (typeArgs == null) {
2595 if (newAnnotations.isEmpty()) {
2596 return arrayCreatorRest(newpos, basicType());
2597 } else {
2598 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2599 }
2600 }
2601 break;
2602 default:
2603 }
2604 JCExpression t = qualident(true);
2605
2606 int prevmode = mode;
2607 selectTypeMode();
2608 int lastTypeargsPos = -1;
2609 if (token.kind == LT) {
2610 lastTypeargsPos = token.pos;
2611 t = typeApplyOrDiamond(t);
2612 }
2613 while (token.kind == DOT) {
2614 if (TreeInfo.isDiamond(t)) {
2615 //cannot select after a diamond
2616 illegal();
2617 }
2618 int pos = token.pos;
2619 nextToken();
2620 List<JCAnnotation> tyannos = typeAnnotationsOpt();
2621 t = toP(F.at(pos).Select(t, ident()));
2622
2623 if (tyannos != null && tyannos.nonEmpty()) {
2624 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
2625 }
2626
2627 if (token.kind == LT) {
2628 lastTypeargsPos = token.pos;
2629 t = typeApplyOrDiamond(t);
2630 }
2631 }
2632 setMode(prevmode);
2633 if (token.kind == LBRACKET || token.kind == MONKEYS_AT) {
2634 // handle type annotations for non primitive arrays
2635 if (newAnnotations.nonEmpty()) {
2636 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2637 }
2638
2639 JCExpression e = arrayCreatorRest(newpos, t);
2640 if (TreeInfo.isDiamond(t)) {
2641 reportSyntaxError(lastTypeargsPos, Errors.CannotCreateArrayWithDiamond);
2642 return toP(F.at(newpos).Erroneous(List.of(e)));
2643 }
2644 else if (typeArgs != null) {
2645 int pos = newpos;
2646 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2647 // note: this should always happen but we should
2648 // not rely on this as the parser is continuously
2649 // modified to improve error recovery.
2650 pos = typeArgs.head.pos;
2651 }
2652 setErrorEndPos(S.prevToken().endPos);
2653 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2654 reportSyntaxError(err, Errors.CannotCreateArrayWithTypeArguments);
2655 return toP(err);
2656 }
2657 return e;
2658 } else if (token.kind == LPAREN) {
2659 // handle type annotations for instantiations and anonymous classes
2660 if (newAnnotations.nonEmpty()) {
2661 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2662 }
2663 return classCreatorRest(newpos, null, typeArgs, t);
2664 } else {
2665 setErrorEndPos(token.pos);
2666 reportSyntaxError(token.pos, Errors.Expected2(LPAREN, LBRACKET));
2667 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null));
2668 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2669 }
2670 }
2671
2672 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2673 */
2674 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2675 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2676
2677 JCExpression t = toP(F.at(token.pos).Ident(ident()));
2678
2679 if (newAnnotations.nonEmpty()) {
2680 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2681 }
2682
2683 if (token.kind == LT) {
2684 int prevmode = mode;
2685 t = typeApplyOrDiamond(t);
2686 setMode(prevmode);
2687 }
2688 return classCreatorRest(newpos, encl, typeArgs, t);
2689 }
2690
2691 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2692 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
2693 */
2694 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2695 List<JCAnnotation> annos = typeAnnotationsOpt();
2696
2697 accept(LBRACKET);
2698 if (token.kind == RBRACKET) {
2699 accept(RBRACKET);
2700 elemtype = bracketsOpt(elemtype, annos);
2701 if (token.kind == LBRACE) {
2702 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2703 if (annos.nonEmpty()) {
2704 // when an array initializer is present then
2705 // the parsed annotations should target the
2706 // new array tree
2707 // bracketsOpt inserts the annotation in
2708 // elemtype, and it needs to be corrected
2709 //
2710 JCAnnotatedType annotated = (JCAnnotatedType)elemtype;
2711 assert annotated.annotations == annos;
2712 na.annotations = annotated.annotations;
2713 na.elemtype = annotated.underlyingType;
2714 }
2715 return na;
2716 } else {
2717 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.nil(), null));
2718 return syntaxError(token.pos, List.of(t), Errors.ArrayDimensionMissing);
2719 }
2720 } else {
2721 ListBuffer<JCExpression> dims = new ListBuffer<>();
2722
2723 // maintain array dimension type annotations
2724 ListBuffer<List<JCAnnotation>> dimAnnotations = new ListBuffer<>();
2725 dimAnnotations.append(annos);
2726
2727 dims.append(parseExpression());
2728 accept(RBRACKET);
2729 while (token.kind == LBRACKET
2730 || token.kind == MONKEYS_AT) {
2731 List<JCAnnotation> maybeDimAnnos = typeAnnotationsOpt();
2732 int pos = token.pos;
2733 nextToken();
2734 if (token.kind == RBRACKET) { // no dimension
2735 elemtype = bracketsOptCont(elemtype, pos, maybeDimAnnos);
2736 } else {
2737 dimAnnotations.append(maybeDimAnnos);
2738 dims.append(parseExpression());
2739 accept(RBRACKET);
2740 }
2741 }
2742
2743 List<JCExpression> elems = null;
2744 int errpos = token.pos;
2745
2746 if (token.kind == LBRACE) {
2747 elems = arrayInitializerElements(newpos, elemtype);
2748 }
2749
2750 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), elems));
2751 na.dimAnnotations = dimAnnotations.toList();
2752
2753 if (elems != null) {
2754 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2755 }
2756
2757 return na;
2758 }
2759 }
2760
2761 /** ClassCreatorRest = Arguments [ClassBody]
2762 */
2763 JCNewClass classCreatorRest(int newpos,
2764 JCExpression encl,
2765 List<JCExpression> typeArgs,
2766 JCExpression t)
2767 {
2768 List<JCExpression> args = arguments();
2769 JCClassDecl body = null;
2770 if (token.kind == LBRACE) {
2771 ignoreDanglingComments(); // ignore any comments from before the '{'
2772 int pos = token.pos;
2773 List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2774 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2775 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2776 }
2777 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2778 }
2779
2780 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2781 */
2782 JCExpression arrayInitializer(int newpos, JCExpression t) {
2783 List<JCExpression> elems = arrayInitializerElements(newpos, t);
2784 return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2785 }
2786
2787 List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2788 accept(LBRACE);
2789 ListBuffer<JCExpression> elems = new ListBuffer<>();
2790 if (token.kind == COMMA) {
2791 nextToken();
2792 } else if (token.kind != RBRACE) {
2793 elems.append(variableInitializer());
2794 while (token.kind == COMMA) {
2795 nextToken();
2796 if (token.kind == RBRACE) break;
2797 elems.append(variableInitializer());
2798 }
2799 }
2800 accept(RBRACE);
2801 return elems.toList();
2802 }
2803
2804 /** VariableInitializer = ArrayInitializer | Expression
2805 */
2806 public JCExpression variableInitializer() {
2807 return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
2808 }
2809
2810 /** ParExpression = "(" Expression ")"
2811 */
2812 JCExpression parExpression() {
2813 int pos = token.pos;
2814 accept(LPAREN);
2815 JCExpression t = parseExpression();
2816 accept(RPAREN);
2817 return toP(F.at(pos).Parens(t));
2818 }
2819
2820 /** Block = "{" BlockStatements "}"
2821 */
2822 JCBlock block(int pos, long flags) {
2823 accept(LBRACE);
2824 ignoreDanglingComments(); // ignore any comments from before the '{'
2825 List<JCStatement> stats = blockStatements();
2826 JCBlock t = F.at(pos).Block(flags, stats);
2827 while (token.kind == CASE || token.kind == DEFAULT) {
2828 syntaxError(token.pos, Errors.Orphaned(token.kind));
2829 switchBlockStatementGroups();
2830 }
2831 // the Block node has a field "bracePos" for first char of last token, which is
2832 // usually but not necessarily the last char of the last token.
2833 t.bracePos = token.pos;
2834 accept(RBRACE);
2835 return toP(t);
2836 }
2837
2838 public JCBlock block() {
2839 return block(token.pos, 0);
2840 }
2841
2842 /** BlockStatements = { BlockStatement }
2843 * BlockStatement = LocalVariableDeclarationStatement
2844 * | ClassOrInterfaceOrEnumDeclaration
2845 * | [Ident ":"] Statement
2846 * LocalVariableDeclarationStatement
2847 * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
2848 */
2849 List<JCStatement> blockStatements() {
2850 //todo: skip to anchor on error(?)
2851 int lastErrPos = -1;
2852 ListBuffer<JCStatement> stats = new ListBuffer<>();
2853 while (true) {
2854 List<JCStatement> stat = blockStatement();
2855 ignoreDanglingComments(); // ignore comments not consumed by the statement
2856 if (stat.isEmpty()) {
2857 return stats.toList();
2858 } else {
2859 // error recovery
2860 if (token.pos == lastErrPos)
2861 return stats.toList();
2862 if (token.pos <= errorEndPos) {
2863 skip(false, true, true, true);
2864 lastErrPos = token.pos;
2865 }
2866 stats.addAll(stat);
2867 }
2868 }
2869 }
2870
2871 /*
2872 * Parse a Statement (JLS 14.5). As an enhancement to improve error recovery,
2873 * this method will also recognize variable and class declarations (which are
2874 * not legal for a Statement) by delegating the parsing to BlockStatement (JLS 14.2).
2875 * If any illegal declarations are found, they will be wrapped in an erroneous tree,
2876 * and an error will be produced by this method.
2877 */
2878 JCStatement parseStatementAsBlock() {
2879 int pos = token.pos;
2880 List<JCStatement> stats = blockStatement();
2881 if (stats.isEmpty()) {
2882 JCErroneous e = syntaxError(pos, Errors.IllegalStartOfStmt);
2883 return toP(F.at(pos).Exec(e));
2884 } else {
2885 JCStatement first = stats.head;
2886 Error error = null;
2887 switch (first.getTag()) {
2888 case CLASSDEF:
2889 error = Errors.ClassNotAllowed;
2890 break;
2891 case VARDEF:
2892 error = Errors.VariableNotAllowed;
2893 break;
2894 }
2895 if (error != null) {
2896 log.error(DiagnosticFlag.SYNTAX, first, error);
2897 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
2898 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
2899 }
2900 return first;
2901 }
2902 }
2903
2904 /**This method parses a statement appearing inside a block.
2905 */
2906 List<JCStatement> blockStatement() {
2907 //todo: skip to anchor on error(?)
2908 Comment dc;
2909 int pos = token.pos;
2910 switch (token.kind) {
2911 case RBRACE: case CASE: case DEFAULT: case EOF:
2912 return List.nil();
2913 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
2914 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
2915 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
2916 case ASSERT:
2917 return List.of(parseSimpleStatement());
2918 case MONKEYS_AT:
2919 case FINAL: {
2920 dc = token.docComment();
2921 JCModifiers mods = modifiersOpt();
2922 if (isDeclaration()) {
2923 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2924 } else {
2925 JCExpression t = parseType(true);
2926 return localVariableDeclarations(mods, t, dc);
2927 }
2928 }
2929 case ABSTRACT: case STRICTFP: {
2930 dc = token.docComment();
2931 JCModifiers mods = modifiersOpt();
2932 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2933 }
2934 case INTERFACE:
2935 case CLASS:
2936 dc = token.docComment();
2937 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2938 case ENUM:
2939 if (!allowRecords) {
2940 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
2941 }
2942 dc = token.docComment();
2943 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2944 case IDENTIFIER:
2945 if (token.name() == names.yield && allowYieldStatement) {
2946 Token next = S.token(1);
2947 boolean isYieldStatement;
2948 switch (next.kind) {
2949 case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
2950 case STRINGFRAGMENT:
2951 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
2952 case NULL: case IDENTIFIER: case UNDERSCORE: case TRUE: case FALSE:
2953 case NEW: case SWITCH: case THIS: case SUPER:
2954 case BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, VOID, BOOLEAN:
2955 isYieldStatement = true;
2956 break;
2957 case PLUSPLUS: case SUBSUB:
2958 isYieldStatement = S.token(2).kind != SEMI;
2959 break;
2960 case BANG: case TILDE:
2961 isYieldStatement = S.token(1).kind != SEMI;
2962 break;
2963 case LPAREN:
2964 int lookahead = 2;
2965 int balance = 1;
2966 boolean hasComma = false;
2967 boolean inTypeArgs = false;
2968 Token l;
2969 while ((l = S.token(lookahead)).kind != EOF && balance != 0) {
2970 switch (l.kind) {
2971 case LPAREN: balance++; break;
2972 case RPAREN: balance--; break;
2973 case COMMA: if (balance == 1 && !inTypeArgs) hasComma = true; break;
2974 case LT: inTypeArgs = true; break;
2975 case GT: inTypeArgs = false;
2976 }
2977 lookahead++;
2978 }
2979 isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
2980 break;
2981 case SEMI: //error recovery - this is not a valid statement:
2982 isYieldStatement = true;
2983 break;
2984 default:
2985 isYieldStatement = false;
2986 break;
2987 }
2988
2989 if (isYieldStatement) {
2990 nextToken();
2991 JCExpression t = term(EXPR);
2992 accept(SEMI);
2993 return List.of(toP(F.at(pos).Yield(t)));
2994 }
2995
2996 //else intentional fall-through
2997 } else {
2998 if (isNonSealedClassStart(true)) {
2999 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3000 nextToken();
3001 nextToken();
3002 nextToken();
3003 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3004 } else if (isSealedClassStart(true)) {
3005 checkSourceLevel(Feature.SEALED_CLASSES);
3006 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3007 nextToken();
3008 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3009 }
3010 }
3011 }
3012 dc = token.docComment();
3013 if (isRecordStart() && allowRecords) {
3014 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3015 } else {
3016 Token prevToken = token;
3017 JCExpression t = term(EXPR | TYPE);
3018 if (token.kind == COLON && t.hasTag(IDENT)) {
3019 nextToken();
3020 JCStatement stat = parseStatementAsBlock();
3021 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3022 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3023 pos = token.pos;
3024 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3025 F.at(pos);
3026 return localVariableDeclarations(mods, t, dc);
3027 } else {
3028 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3029 t = checkExprStat(t);
3030 accept(SEMI);
3031 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3032 return List.of(expr);
3033 }
3034 }
3035 }
3036 //where
3037 private List<JCStatement> localVariableDeclarations(JCModifiers mods, JCExpression type, Comment dc) {
3038 if (dc != null) {
3039 // ignore a well-placed doc comment, but save any misplaced ones
3040 saveDanglingDocComments(dc);
3041 }
3042 ListBuffer<JCStatement> stats =
3043 variableDeclarators(mods, type, new ListBuffer<>(), true);
3044 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
3045 accept(SEMI);
3046 storeEnd(stats.last(), S.prevToken().endPos);
3047 return stats.toList();
3048 }
3049
3050 /** Statement =
3051 * Block
3052 * | IF ParExpression Statement [ELSE Statement]
3053 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
3054 * | FOR "(" FormalParameter : Expression ")" Statement
3055 * | WHILE ParExpression Statement
3056 * | DO Statement WHILE ParExpression ";"
3057 * | TRY Block ( Catches | [Catches] FinallyPart )
3058 * | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
3059 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
3060 * | SYNCHRONIZED ParExpression Block
3061 * | RETURN [Expression] ";"
3062 * | THROW Expression ";"
3063 * | BREAK [Ident] ";"
3064 * | CONTINUE [Ident] ";"
3065 * | ASSERT Expression [ ":" Expression ] ";"
3066 * | ";"
3067 */
3068 public JCStatement parseSimpleStatement() {
3069 ignoreDanglingComments(); // ignore comments before statement
3070 int pos = token.pos;
3071 switch (token.kind) {
3072 case LBRACE:
3073 return block();
3074 case IF: {
3075 nextToken();
3076 JCExpression cond = parExpression();
3077 JCStatement thenpart = parseStatementAsBlock();
3078 JCStatement elsepart = null;
3079 if (token.kind == ELSE) {
3080 nextToken();
3081 elsepart = parseStatementAsBlock();
3082 }
3083 return F.at(pos).If(cond, thenpart, elsepart);
3084 }
3085 case FOR: {
3086 nextToken();
3087 accept(LPAREN);
3088 List<JCStatement> inits = token.kind == SEMI ? List.nil() : forInit();
3089 if (inits.length() == 1 &&
3090 inits.head.hasTag(VARDEF) &&
3091 ((JCVariableDecl) inits.head).init == null &&
3092 token.kind == COLON) {
3093 JCVariableDecl var = (JCVariableDecl)inits.head;
3094 accept(COLON);
3095 JCExpression expr = parseExpression();
3096 accept(RPAREN);
3097 JCStatement body = parseStatementAsBlock();
3098 return F.at(pos).ForeachLoop(var, expr, body);
3099 } else {
3100 accept(SEMI);
3101 JCExpression cond = token.kind == SEMI ? null : parseExpression();
3102 accept(SEMI);
3103 List<JCExpressionStatement> steps = token.kind == RPAREN ? List.nil() : forUpdate();
3104 accept(RPAREN);
3105 JCStatement body = parseStatementAsBlock();
3106 return F.at(pos).ForLoop(inits, cond, steps, body);
3107 }
3108 }
3109 case WHILE: {
3110 nextToken();
3111 JCExpression cond = parExpression();
3112 JCStatement body = parseStatementAsBlock();
3113 return F.at(pos).WhileLoop(cond, body);
3114 }
3115 case DO: {
3116 nextToken();
3117 JCStatement body = parseStatementAsBlock();
3118 accept(WHILE);
3119 JCExpression cond = parExpression();
3120 accept(SEMI);
3121 JCDoWhileLoop t = toP(F.at(pos).DoLoop(body, cond));
3122 return t;
3123 }
3124 case TRY: {
3125 nextToken();
3126 List<JCTree> resources = List.nil();
3127 if (token.kind == LPAREN) {
3128 nextToken();
3129 resources = resources();
3130 accept(RPAREN);
3131 }
3132 JCBlock body = block();
3133 ListBuffer<JCCatch> catchers = new ListBuffer<>();
3134 JCBlock finalizer = null;
3135 if (token.kind == CATCH || token.kind == FINALLY) {
3136 while (token.kind == CATCH) catchers.append(catchClause());
3137 if (token.kind == FINALLY) {
3138 nextToken();
3139 finalizer = block();
3140 }
3141 } else {
3142 if (resources.isEmpty()) {
3143 log.error(DiagnosticFlag.SYNTAX, pos, Errors.TryWithoutCatchFinallyOrResourceDecls);
3144 }
3145 }
3146 return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
3147 }
3148 case SWITCH: {
3149 nextToken();
3150 JCExpression selector = parExpression();
3151 accept(LBRACE);
3152 List<JCCase> cases = switchBlockStatementGroups();
3153 JCSwitch t = to(F.at(pos).Switch(selector, cases));
3154 t.bracePos = token.endPos;
3155 accept(RBRACE);
3156 return t;
3157 }
3158 case SYNCHRONIZED: {
3159 nextToken();
3160 JCExpression lock = parExpression();
3161 JCBlock body = block();
3162 return F.at(pos).Synchronized(lock, body);
3163 }
3164 case RETURN: {
3165 nextToken();
3166 JCExpression result = token.kind == SEMI ? null : parseExpression();
3167 accept(SEMI);
3168 JCReturn t = toP(F.at(pos).Return(result));
3169 return t;
3170 }
3171 case THROW: {
3172 nextToken();
3173 JCExpression exc = parseExpression();
3174 accept(SEMI);
3175 JCThrow t = toP(F.at(pos).Throw(exc));
3176 return t;
3177 }
3178 case BREAK: {
3179 nextToken();
3180 Name label = LAX_IDENTIFIER.test(token.kind) ? ident() : null;
3181 accept(SEMI);
3182 JCBreak t = toP(F.at(pos).Break(label));
3183 return t;
3184 }
3185 case CONTINUE: {
3186 nextToken();
3187 Name label = LAX_IDENTIFIER.test(token.kind) ? ident() : null;
3188 accept(SEMI);
3189 JCContinue t = toP(F.at(pos).Continue(label));
3190 return t;
3191 }
3192 case SEMI:
3193 nextToken();
3194 return toP(F.at(pos).Skip());
3195 case ELSE:
3196 int elsePos = token.pos;
3197 nextToken();
3198 return doRecover(elsePos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.ElseWithoutIf);
3199 case FINALLY:
3200 int finallyPos = token.pos;
3201 nextToken();
3202 return doRecover(finallyPos, BasicErrorRecoveryAction.BLOCK_STMT, Errors.FinallyWithoutTry);
3203 case CATCH:
3204 return doRecover(token.pos, BasicErrorRecoveryAction.CATCH_CLAUSE, Errors.CatchWithoutTry);
3205 case ASSERT: {
3206 nextToken();
3207 JCExpression assertion = parseExpression();
3208 JCExpression message = null;
3209 if (token.kind == COLON) {
3210 nextToken();
3211 message = parseExpression();
3212 }
3213 accept(SEMI);
3214 JCAssert t = toP(F.at(pos).Assert(assertion, message));
3215 return t;
3216 }
3217 default:
3218 Assert.error();
3219 return null;
3220 }
3221 }
3222
3223 @Override
3224 public JCStatement parseStatement() {
3225 return parseStatementAsBlock();
3226 }
3227
3228 private JCStatement doRecover(int startPos, ErrorRecoveryAction action, Error errorKey) {
3229 int errPos = S.errPos();
3230 JCTree stm = action.doRecover(this);
3231 S.errPos(errPos);
3232 return toP(F.Exec(syntaxError(startPos, List.of(stm), errorKey)));
3233 }
3234
3235 /** CatchClause = CATCH "(" FormalParameter ")" Block
3236 * TODO: the "FormalParameter" is not correct, it uses the special "catchTypes" rule below.
3237 */
3238 protected JCCatch catchClause() {
3239 int pos = token.pos;
3240 accept(CATCH);
3241 accept(LPAREN);
3242 JCModifiers mods = optFinal(Flags.PARAMETER);
3243 List<JCExpression> catchTypes = catchTypes();
3244 JCExpression paramType = catchTypes.size() > 1 ?
3245 toP(F.at(catchTypes.head.getStartPosition()).TypeUnion(catchTypes)) :
3246 catchTypes.head;
3247 JCVariableDecl formal = variableDeclaratorId(mods, paramType, true, false, false);
3248 accept(RPAREN);
3249 JCBlock body = block();
3250 return F.at(pos).Catch(formal, body);
3251 }
3252
3253 List<JCExpression> catchTypes() {
3254 ListBuffer<JCExpression> catchTypes = new ListBuffer<>();
3255 catchTypes.add(parseType());
3256 while (token.kind == BAR) {
3257 nextToken();
3258 // Instead of qualident this is now parseType.
3259 // But would that allow too much, e.g. arrays or generics?
3260 catchTypes.add(parseType());
3261 }
3262 return catchTypes.toList();
3263 }
3264
3265 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
3266 * SwitchBlockStatementGroup = SwitchLabel BlockStatements
3267 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
3268 */
3269 List<JCCase> switchBlockStatementGroups() {
3270 ListBuffer<JCCase> cases = new ListBuffer<>();
3271 while (true) {
3272 int pos = token.pos;
3273 switch (token.kind) {
3274 case CASE:
3275 case DEFAULT:
3276 cases.appendList(switchBlockStatementGroup());
3277 break;
3278 case RBRACE: case EOF:
3279 return cases.toList();
3280 default:
3281 nextToken(); // to ensure progress
3282 syntaxError(pos, Errors.Expected3(CASE, DEFAULT, RBRACE));
3283 }
3284 }
3285 }
3286
3287 protected List<JCCase> switchBlockStatementGroup() {
3288 int pos = token.pos;
3289 List<JCStatement> stats;
3290 JCCase c;
3291 ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
3292 switch (token.kind) {
3293 case CASE: {
3294 nextToken();
3295 ListBuffer<JCCaseLabel> pats = new ListBuffer<>();
3296 boolean allowDefault = false;
3297 while (true) {
3298 JCCaseLabel label = parseCaseLabel(allowDefault);
3299 pats.append(label);
3300 if (token.kind != COMMA) break;
3301 nextToken();
3302 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
3303 allowDefault = TreeInfo.isNullCaseLabel(label);
3304 };
3305 JCExpression guard = parseGuard(pats.last());
3306 CaseTree.CaseKind caseKind;
3307 JCTree body = null;
3308 if (token.kind == ARROW) {
3309 checkSourceLevel(Feature.SWITCH_RULE);
3310 accept(ARROW);
3311 caseKind = JCCase.RULE;
3312 JCStatement statement = parseStatementAsBlock();
3313 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
3314 log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
3315 }
3316 stats = List.of(statement);
3317 body = stats.head;
3318 } else {
3319 accept(COLON, tk -> Errors.Expected2(COLON, ARROW));
3320 caseKind = JCCase.STATEMENT;
3321 stats = blockStatements();
3322 }
3323 c = F.at(pos).Case(caseKind, pats.toList(), guard, stats, body);
3324 if (stats.isEmpty())
3325 storeEnd(c, S.prevToken().endPos);
3326 return cases.append(c).toList();
3327 }
3328 case DEFAULT: {
3329 nextToken();
3330 JCCaseLabel defaultPattern = toP(F.at(pos).DefaultCaseLabel());
3331 JCExpression guard = parseGuard(defaultPattern);
3332 CaseTree.CaseKind caseKind;
3333 JCTree body = null;
3334 if (token.kind == ARROW) {
3335 checkSourceLevel(Feature.SWITCH_RULE);
3336 accept(ARROW);
3337 caseKind = JCCase.RULE;
3338 JCStatement statement = parseStatementAsBlock();
3339 if (!statement.hasTag(EXEC) && !statement.hasTag(BLOCK) && !statement.hasTag(Tag.THROW)) {
3340 log.error(statement.pos(), Errors.SwitchCaseUnexpectedStatement);
3341 }
3342 stats = List.of(statement);
3343 body = stats.head;
3344 } else {
3345 accept(COLON, tk -> Errors.Expected2(COLON, ARROW));
3346 caseKind = JCCase.STATEMENT;
3347 stats = blockStatements();
3348 }
3349 c = F.at(pos).Case(caseKind, List.of(defaultPattern), guard, stats, body);
3350 if (stats.isEmpty())
3351 storeEnd(c, S.prevToken().endPos);
3352 return cases.append(c).toList();
3353 }
3354 }
3355 throw new AssertionError("should not reach here");
3356 }
3357
3358 private JCCaseLabel parseCaseLabel(boolean allowDefault) {
3359 int patternPos = token.pos;
3360 JCCaseLabel label;
3361
3362 if (token.kind == DEFAULT) {
3363 checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
3364 if (!allowDefault) {
3365 reportSyntaxError(new SimpleDiagnosticPosition(token.pos),
3366 Errors.DefaultLabelNotAllowed);
3367 }
3368 nextToken();
3369 label = toP(F.at(patternPos).DefaultCaseLabel());
3370 } else {
3371 JCModifiers mods = optFinal(0);
3372 boolean pattern = mods.flags != 0 || mods.annotations.nonEmpty() ||
3373 analyzePattern(0) == PatternResult.PATTERN;
3374 if (pattern) {
3375 checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
3376 JCPattern p = parsePattern(patternPos, mods, null, false, true);
3377 return toP(F.at(patternPos).PatternCaseLabel(p));
3378 } else {
3379 JCExpression expr = term(EXPR | NOLAMBDA);
3380 return toP(F.at(patternPos).ConstantCaseLabel(expr));
3381 }
3382 }
3383
3384 return label;
3385 }
3386
3387 private JCExpression parseGuard(JCCaseLabel label) {
3388 JCExpression guard = null;
3389
3390 if (token.kind == IDENTIFIER && token.name() == names.when) {
3391 int pos = token.pos;
3392
3393 nextToken();
3394 guard = term(EXPR | NOLAMBDA);
3395
3396 if (!(label instanceof JCPatternCaseLabel)) {
3397 guard = syntaxError(pos, List.of(guard), Errors.GuardNotAllowed);
3398 }
3399 }
3400
3401 return guard;
3402 }
3403 @SuppressWarnings("fallthrough")
3404 PatternResult analyzePattern(int lookahead) {
3405 int typeDepth = 0;
3406 int parenDepth = 0;
3407 PatternResult pendingResult = PatternResult.EXPRESSION;
3408 while (true) {
3409 TokenKind token = S.token(lookahead).kind;
3410 switch (token) {
3411 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
3412 case DOUBLE: case BOOLEAN: case CHAR: case VOID:
3413 case ASSERT, ENUM, IDENTIFIER:
3414 if (typeDepth == 0 && peekToken(lookahead, LAX_IDENTIFIER)) {
3415 if (parenDepth == 0) {
3416 return PatternResult.PATTERN;
3417 } else {
3418 pendingResult = PatternResult.PATTERN;
3419 }
3420 } else if (typeDepth == 0 && parenDepth == 0 && (peekToken(lookahead, tk -> tk == ARROW || tk == COMMA))) {
3421 return PatternResult.EXPRESSION;
3422 }
3423 break;
3424 case UNDERSCORE:
3425 // TODO: REFACTOR to remove the code duplication
3426 if (typeDepth == 0 && peekToken(lookahead, tk -> tk == RPAREN || tk == COMMA)) {
3427 return PatternResult.PATTERN;
3428 } else if (typeDepth == 0 && peekToken(lookahead, LAX_IDENTIFIER)) {
3429 if (parenDepth == 0) {
3430 return PatternResult.PATTERN;
3431 } else {
3432 pendingResult = PatternResult.PATTERN;
3433 }
3434 }
3435 break;
3436 case DOT, QUES, EXTENDS, SUPER, COMMA: break;
3437 case LT: typeDepth++; break;
3438 case GTGTGT: typeDepth--;
3439 case GTGT: typeDepth--;
3440 case GT:
3441 typeDepth--;
3442 if (typeDepth == 0 && !peekToken(lookahead, DOT)) {
3443 return peekToken(lookahead, LAX_IDENTIFIER) ||
3444 peekToken(lookahead, tk -> tk == LPAREN) ? PatternResult.PATTERN
3445 : PatternResult.EXPRESSION;
3446 } else if (typeDepth < 0) return PatternResult.EXPRESSION;
3447 break;
3448 case MONKEYS_AT:
3449 lookahead = skipAnnotation(lookahead);
3450 break;
3451 case LBRACKET:
3452 if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
3453 return PatternResult.PATTERN;
3454 } else if (peekToken(lookahead, RBRACKET)) {
3455 lookahead++;
3456 break;
3457 } else {
3458 // This is a potential guard, if we are already in a pattern
3459 return pendingResult;
3460 }
3461 case LPAREN:
3462 if (S.token(lookahead + 1).kind == RPAREN) {
3463 return parenDepth != 0 && S.token(lookahead + 2).kind == ARROW
3464 ? PatternResult.EXPRESSION
3465 : PatternResult.PATTERN;
3466 }
3467 parenDepth++; break;
3468 case RPAREN:
3469 parenDepth--;
3470 if (parenDepth == 0 &&
3471 typeDepth == 0 &&
3472 peekToken(lookahead, TokenKind.IDENTIFIER) &&
3473 S.token(lookahead + 1).name() == names.when) {
3474 return PatternResult.PATTERN;
3475 }
3476 break;
3477 case ARROW: return parenDepth > 0 ? PatternResult.EXPRESSION
3478 : pendingResult;
3479 case FINAL:
3480 if (parenDepth > 0) return PatternResult.PATTERN;
3481 default: return pendingResult;
3482 }
3483 lookahead++;
3484 }
3485 }
3486
3487 private enum PatternResult {
3488 EXPRESSION,
3489 PATTERN;
3490 }
3491
3492 /** MoreStatementExpressions = { COMMA StatementExpression }
3493 */
3494 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
3495 JCExpression first,
3496 T stats) {
3497 // This Exec is a "StatementExpression"; it subsumes no terminating token
3498 stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
3499 while (token.kind == COMMA) {
3500 nextToken();
3501 pos = token.pos;
3502 JCExpression t = parseExpression();
3503 // This Exec is a "StatementExpression"; it subsumes no terminating token
3504 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3505 }
3506 return stats;
3507 }
3508
3509 /** ForInit = StatementExpression MoreStatementExpressions
3510 * | { FINAL | '@' Annotation } Type VariableDeclarators
3511 */
3512 List<JCStatement> forInit() {
3513 ListBuffer<JCStatement> stats = new ListBuffer<>();
3514 int pos = token.pos;
3515 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3516 return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3517 } else {
3518 JCExpression t = term(EXPR | TYPE);
3519 if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3520 return variableDeclarators(modifiersOpt(), t, stats, true).toList();
3521 } else if (wasTypeMode() && token.kind == COLON) {
3522 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3523 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3524 } else {
3525 return moreStatementExpressions(pos, t, stats).toList();
3526 }
3527 }
3528 }
3529
3530 /** ForUpdate = StatementExpression MoreStatementExpressions
3531 */
3532 List<JCExpressionStatement> forUpdate() {
3533 return moreStatementExpressions(token.pos,
3534 parseExpression(),
3535 new ListBuffer<JCExpressionStatement>()).toList();
3536 }
3537
3538 /** AnnotationsOpt = { '@' Annotation }
3539 *
3540 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3541 */
3542 protected List<JCAnnotation> annotationsOpt(Tag kind) {
3543 if (token.kind != MONKEYS_AT) return List.nil(); // optimization
3544 ListBuffer<JCAnnotation> buf = new ListBuffer<>();
3545 int prevmode = mode;
3546 while (token.kind == MONKEYS_AT) {
3547 int pos = token.pos;
3548 nextToken();
3549 buf.append(annotation(pos, kind));
3550 }
3551 setLastMode(mode);
3552 setMode(prevmode);
3553 List<JCAnnotation> annotations = buf.toList();
3554
3555 return annotations;
3556 }
3557
3558 List<JCAnnotation> typeAnnotationsOpt() {
3559 List<JCAnnotation> annotations = annotationsOpt(Tag.TYPE_ANNOTATION);
3560 return annotations;
3561 }
3562
3563 /** ModifiersOpt = { Modifier }
3564 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
3565 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
3566 * | "@" Annotation
3567 */
3568 protected JCModifiers modifiersOpt() {
3569 return modifiersOpt(null);
3570 }
3571 protected JCModifiers modifiersOpt(JCModifiers partial) {
3572 long flags;
3573 ListBuffer<JCAnnotation> annotations = new ListBuffer<>();
3574 int pos;
3575 if (partial == null) {
3576 flags = 0;
3577 pos = token.pos;
3578 } else {
3579 flags = partial.flags;
3580 annotations.appendList(partial.annotations);
3581 pos = partial.pos;
3582 }
3583 if (token.deprecatedFlag()) {
3584 flags |= Flags.DEPRECATED;
3585 }
3586 int lastPos;
3587 loop:
3588 while (true) {
3589 long flag;
3590 switch (token.kind) {
3591 case PRIVATE : flag = Flags.PRIVATE; break;
3592 case PROTECTED : flag = Flags.PROTECTED; break;
3593 case PUBLIC : flag = Flags.PUBLIC; break;
3594 case STATIC : flag = Flags.STATIC; break;
3595 case TRANSIENT : flag = Flags.TRANSIENT; break;
3596 case FINAL : flag = Flags.FINAL; break;
3597 case ABSTRACT : flag = Flags.ABSTRACT; break;
3598 case NATIVE : flag = Flags.NATIVE; break;
3599 case VOLATILE : flag = Flags.VOLATILE; break;
3600 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3601 case STRICTFP : flag = Flags.STRICTFP; break;
3602 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3603 case DEFAULT : flag = Flags.DEFAULT; break;
3604 case ERROR : flag = 0; nextToken(); break;
3605 case IDENTIFIER : {
3606 if (isNonSealedClassStart(false)) {
3607 flag = Flags.NON_SEALED;
3608 nextToken();
3609 nextToken();
3610 break;
3611 }
3612 if (isSealedClassStart(false)) {
3613 checkSourceLevel(Feature.SEALED_CLASSES);
3614 flag = Flags.SEALED;
3615 break;
3616 }
3617 break loop;
3618 }
3619 default: break loop;
3620 }
3621 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3622 lastPos = token.pos;
3623 nextToken();
3624 if (flag == Flags.ANNOTATION) {
3625 if (token.kind != INTERFACE) {
3626 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3627 // if first modifier is an annotation, set pos to annotation's.
3628 if (flags == 0 && annotations.isEmpty())
3629 pos = ann.pos;
3630 annotations.append(ann);
3631 flag = 0;
3632 }
3633 }
3634 flags |= flag;
3635 }
3636 switch (token.kind) {
3637 case ENUM: flags |= Flags.ENUM; break;
3638 case INTERFACE: flags |= Flags.INTERFACE; break;
3639 default: break;
3640 }
3641
3642 /* A modifiers tree with no modifier tokens or annotations
3643 * has no text position. */
3644 if ((flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0 && annotations.isEmpty())
3645 pos = Position.NOPOS;
3646
3647 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
3648 if (pos != Position.NOPOS)
3649 storeEnd(mods, S.prevToken().endPos);
3650 return mods;
3651 }
3652
3653 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
3654 *
3655 * @param pos position of "@" token
3656 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3657 */
3658 JCAnnotation annotation(int pos, Tag kind) {
3659 // accept(AT); // AT consumed by caller
3660 JCTree ident = qualident(false);
3661 List<JCExpression> fieldValues = annotationFieldValuesOpt();
3662 JCAnnotation ann;
3663 if (kind == Tag.ANNOTATION) {
3664 ann = F.at(pos).Annotation(ident, fieldValues);
3665 } else if (kind == Tag.TYPE_ANNOTATION) {
3666 ann = F.at(pos).TypeAnnotation(ident, fieldValues);
3667 } else {
3668 throw new AssertionError("Unhandled annotation kind: " + kind);
3669 }
3670 return toP(ann);
3671 }
3672
3673 List<JCExpression> annotationFieldValuesOpt() {
3674 return (token.kind == LPAREN) ? annotationFieldValues() : List.nil();
3675 }
3676
3677 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
3678 List<JCExpression> annotationFieldValues() {
3679 accept(LPAREN);
3680 ListBuffer<JCExpression> buf = new ListBuffer<>();
3681 if (token.kind != RPAREN) {
3682 buf.append(annotationFieldValue());
3683 while (token.kind == COMMA) {
3684 nextToken();
3685 buf.append(annotationFieldValue());
3686 }
3687 }
3688 accept(RPAREN);
3689 return buf.toList();
3690 }
3691
3692 /** AnnotationFieldValue = AnnotationValue
3693 * | Identifier "=" AnnotationValue
3694 */
3695 JCExpression annotationFieldValue() {
3696 if (LAX_IDENTIFIER.test(token.kind)) {
3697 selectExprMode();
3698 JCExpression t1 = term1();
3699 if (t1.hasTag(IDENT) && token.kind == EQ) {
3700 int pos = token.pos;
3701 accept(EQ);
3702 JCExpression v = annotationValue();
3703 return toP(F.at(pos).Assign(t1, v));
3704 } else {
3705 return t1;
3706 }
3707 }
3708 return annotationValue();
3709 }
3710
3711 /* AnnotationValue = ConditionalExpression
3712 * | Annotation
3713 * | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
3714 */
3715 JCExpression annotationValue() {
3716 int pos;
3717 switch (token.kind) {
3718 case MONKEYS_AT:
3719 pos = token.pos;
3720 nextToken();
3721 return annotation(pos, Tag.ANNOTATION);
3722 case LBRACE:
3723 pos = token.pos;
3724 accept(LBRACE);
3725 ListBuffer<JCExpression> buf = new ListBuffer<>();
3726 if (token.kind == COMMA) {
3727 nextToken();
3728 } else if (token.kind != RBRACE) {
3729 buf.append(annotationValue());
3730 while (token.kind == COMMA) {
3731 nextToken();
3732 if (token.kind == RBRACE) break;
3733 buf.append(annotationValue());
3734 }
3735 }
3736 accept(RBRACE, tk -> Errors.AnnotationMissingElementValue);
3737 return toP(F.at(pos).NewArray(null, List.nil(), buf.toList()));
3738 default:
3739 selectExprMode();
3740 return term1();
3741 }
3742 }
3743
3744 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
3745 */
3746 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
3747 JCExpression type,
3748 T vdefs,
3749 boolean localDecl)
3750 {
3751 return variableDeclaratorsRest(token.pos, mods, type, identOrUnderscore(), false, null, vdefs, localDecl);
3752 }
3753
3754 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
3755 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
3756 *
3757 * @param reqInit Is an initializer always required?
3758 * @param dc The documentation comment for the variable declarations, or null.
3759 */
3760 protected <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
3761 JCModifiers mods,
3762 JCExpression type,
3763 Name name,
3764 boolean reqInit,
3765 Comment dc,
3766 T vdefs,
3767 boolean localDecl)
3768 {
3769 JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl, false);
3770 vdefs.append(head);
3771 while (token.kind == COMMA) {
3772 // All but last of multiple declarators subsume a comma
3773 storeEnd((JCTree)vdefs.last(), token.endPos);
3774 nextToken();
3775 vdefs.append(variableDeclarator(mods, type, reqInit, dc, localDecl));
3776 }
3777 return vdefs;
3778 }
3779
3780 /** VariableDeclarator = Ident VariableDeclaratorRest
3781 * ConstantDeclarator = Ident ConstantDeclaratorRest
3782 */
3783 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc, boolean localDecl) {
3784 return variableDeclaratorRest(token.pos, mods, type, identOrUnderscore(), reqInit, dc, localDecl, true);
3785 }
3786
3787 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
3788 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
3789 *
3790 * @param reqInit Is an initializer always required?
3791 * @param dc The documentation comment for the variable declarations, or null.
3792 */
3793 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
3794 boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
3795 boolean declaredUsingVar = false;
3796 JCExpression init = null;
3797 type = bracketsOpt(type);
3798
3799 if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3800 if (!localDecl) {
3801 log.error(DiagnosticFlag.SYNTAX, pos, Errors.UseOfUnderscoreNotAllowed);
3802 }
3803 name = names.empty;
3804 }
3805
3806 saveDanglingDocComments(dc);
3807
3808 if (token.kind == EQ) {
3809 nextToken();
3810 init = variableInitializer();
3811 }
3812 else if (reqInit) syntaxError(token.pos, Errors.Expected(EQ));
3813
3814 if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.empty
3815 && localDecl
3816 && init == null
3817 && token.kind != COLON) { // if its unnamed local variable, it needs to have an init unless in enhanced-for
3818 syntaxError(token.pos, Errors.Expected(EQ));
3819 }
3820
3821 int varTypePos = Position.NOPOS;
3822 JCTree elemType = TreeInfo.innermostType(type, true);
3823 if (elemType.hasTag(IDENT)) {
3824 Name typeName = ((JCIdent) elemType).name;
3825 if (restrictedTypeNameStartingAtSource(typeName, pos, !compound && localDecl) != null) {
3826 if (typeName != names.var) {
3827 reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedHere(typeName));
3828 } else if (type.hasTag(TYPEARRAY) && !compound) {
3829 //error - 'var' and arrays
3830 reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName));
3831 } else {
3832 declaredUsingVar = true;
3833 varTypePos = elemType.pos;
3834 if (compound)
3835 //error - 'var' in compound local var decl
3836 reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
3837 //implicit type
3838 type = null;
3839 }
3840 }
3841 }
3842 JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init,
3843 declaredUsingVar ? JCVariableDecl.DeclKind.VAR : JCVariableDecl.DeclKind.EXPLICIT, varTypePos));
3844 return attach(result, dc);
3845 }
3846
3847 Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
3848 switch (e.getTag()) {
3849 case IDENT:
3850 return restrictedTypeNameStartingAtSource(((JCIdent)e).name, e.pos, shouldWarn) != null ? ((JCIdent)e).name : null;
3851 case TYPEARRAY:
3852 return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
3853 default:
3854 return null;
3855 }
3856 }
3857
3858 Source restrictedTypeNameStartingAtSource(Name name, int pos, boolean shouldWarn) {
3859 if (name == names.var) {
3860 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3861 return Source.JDK10;
3862 } else if (shouldWarn) {
3863 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3864 }
3865 }
3866 if (name == names.yield) {
3867 if (allowYieldStatement) {
3868 return Source.JDK14;
3869 } else if (shouldWarn) {
3870 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3871 }
3872 }
3873 if (name == names.record) {
3874 if (allowRecords) {
3875 return Source.JDK14;
3876 } else if (shouldWarn) {
3877 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3878 }
3879 }
3880 if (name == names.sealed) {
3881 if (allowSealedTypes) {
3882 return Source.JDK15;
3883 } else if (shouldWarn) {
3884 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3885 }
3886 }
3887 if (name == names.permits) {
3888 if (allowSealedTypes) {
3889 return Source.JDK15;
3890 } else if (shouldWarn) {
3891 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3892 }
3893 }
3894 return null;
3895 }
3896
3897 /** VariableDeclaratorId = Ident BracketsOpt
3898 */
3899 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
3900 int pos = token.pos;
3901 Name name;
3902 if (allowThisIdent ||
3903 !lambdaParameter ||
3904 LAX_IDENTIFIER.test(token.kind) ||
3905 mods.flags != Flags.PARAMETER ||
3906 mods.annotations.nonEmpty()) {
3907 JCExpression pn;
3908 if (token.kind == UNDERSCORE && (catchParameter || lambdaParameter)) {
3909 pn = toP(F.at(token.pos).Ident(identOrUnderscore()));
3910 } else {
3911 pn = qualident(false);
3912 }
3913 if (pn.hasTag(Tag.IDENT) && ((JCIdent)pn).name != names._this) {
3914 name = ((JCIdent)pn).name;
3915 } else if (lambdaParameter && type == null) {
3916 // we have a lambda parameter that is not an identifier this is a syntax error
3917 type = pn;
3918 name = names.empty;
3919 reportSyntaxError(pos, Errors.Expected(IDENTIFIER));
3920 } else {
3921 if (allowThisIdent) {
3922 if ((mods.flags & Flags.VARARGS) != 0) {
3923 log.error(token.pos, Errors.VarargsAndReceiver);
3924 }
3925 if (token.kind == LBRACKET) {
3926 log.error(token.pos, Errors.ArrayAndReceiver);
3927 }
3928 if (pn.hasTag(Tag.SELECT) && ((JCFieldAccess)pn).name != names._this) {
3929 log.error(token.pos, Errors.WrongReceiver);
3930 }
3931 }
3932 return toP(F.at(pos).ReceiverVarDef(mods, pn, type));
3933 }
3934 } else {
3935 /** if it is a lambda parameter and the token kind is not an identifier,
3936 * and there are no modifiers or annotations, then this means that the compiler
3937 * supposed the lambda to be explicit but it can contain a mix of implicit,
3938 * var or explicit parameters. So we assign the error name to the parameter name
3939 * instead of issuing an error and analyze the lambda parameters as a whole at
3940 * a higher level.
3941 */
3942 name = names.error;
3943 }
3944 if ((mods.flags & Flags.VARARGS) != 0 &&
3945 token.kind == LBRACKET) {
3946 log.error(token.pos, Errors.VarargsAndOldArraySyntax);
3947 }
3948 if (recordComponent && token.kind == LBRACKET) {
3949 log.error(token.pos, Errors.RecordComponentAndOldArraySyntax);
3950 }
3951 type = bracketsOpt(type);
3952
3953 if (Feature.UNNAMED_VARIABLES.allowedInSource(source) && name == names.underscore) {
3954 name = names.empty;
3955 }
3956
3957 boolean declaredUsingVar = type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var;
3958 JCVariableDecl.DeclKind declKind = declaredUsingVar ? JCVariableDecl.DeclKind.VAR :
3959 type != null ? JCVariableDecl.DeclKind.EXPLICIT : JCVariableDecl.DeclKind.IMPLICIT;
3960 int typePos = type != null ? type.pos : pos;
3961 return toP(F.at(pos).VarDef(mods, name, type, null, declKind, typePos));
3962 }
3963
3964 /** Resources = Resource { ";" Resources }
3965 */
3966 List<JCTree> resources() {
3967 ListBuffer<JCTree> defs = new ListBuffer<>();
3968 defs.append(resource());
3969 while (token.kind == SEMI) {
3970 // All but last of multiple declarators must subsume a semicolon
3971 storeEnd(defs.last(), token.endPos);
3972 int semiColonPos = token.pos;
3973 nextToken();
3974 if (token.kind == RPAREN) { // Optional trailing semicolon
3975 // after last resource
3976 break;
3977 }
3978 defs.append(resource());
3979 }
3980 return defs.toList();
3981 }
3982
3983 /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
3984 * | Expression
3985 */
3986 protected JCTree resource() {
3987 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3988 JCModifiers mods = optFinal(0);
3989 JCExpression t = parseType(true);
3990 return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
3991 }
3992 JCExpression t = term(EXPR | TYPE);
3993 if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3994 JCModifiers mods = F.Modifiers(0);
3995 return variableDeclaratorRest(token.pos, mods, t, identOrUnderscore(), true, null, true, false);
3996 } else {
3997 checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES);
3998 if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
3999 log.error(t.pos(), Errors.TryWithResourcesExprNeedsVar);
4000 }
4001
4002 return t;
4003 }
4004 }
4005
4006 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
4007 */
4008 public JCTree.JCCompilationUnit parseCompilationUnit() {
4009 Token firstToken = token;
4010 JCModifiers mods = null;
4011 boolean consumedToplevelDoc = false;
4012 boolean seenImport = false;
4013 boolean seenPackage = false;
4014 ListBuffer<JCTree> defs = new ListBuffer<>();
4015 if (token.kind == MONKEYS_AT)
4016 mods = modifiersOpt();
4017
4018 if (token.kind == PACKAGE) {
4019 int packagePos = token.pos;
4020 List<JCAnnotation> annotations = List.nil();
4021 seenPackage = true;
4022 if (mods != null) {
4023 checkNoMods(mods.flags & ~Flags.DEPRECATED);
4024 annotations = mods.annotations;
4025 mods = null;
4026 }
4027 nextToken();
4028 JCExpression pid = qualident(false);
4029 accept(SEMI);
4030 JCPackageDecl pd = toP(F.at(packagePos).PackageDecl(annotations, pid));
4031 attach(pd, firstToken.docComment());
4032 consumedToplevelDoc = true;
4033 defs.append(pd);
4034 updateUnexpectedTopLevelDefinitionStartError(true);
4035 }
4036
4037 boolean firstTypeDecl = true; // have we seen a class, enum, or interface declaration yet?
4038 boolean isImplicitClass = false;
4039 OUTER: while (token.kind != EOF) {
4040 if (token.pos <= errorEndPos) {
4041 // error recovery
4042 skip(firstTypeDecl, false, false, false);
4043 if (token.kind == EOF)
4044 break;
4045 }
4046 // JLS 7.3 doesn't allow extra semicolons after package or import declarations,
4047 // but here we try to provide a more helpful error message if we encounter any.
4048 // Do that by slurping in as many semicolons as possible, and then seeing what
4049 // comes after before deciding how best to handle them.
4050 ListBuffer<JCTree> semiList = new ListBuffer<>();
4051 while (firstTypeDecl && mods == null && token.kind == SEMI) {
4052 int pos = token.pos;
4053 nextToken();
4054 semiList.append(toP(F.at(pos).Skip()));
4055 if (token.kind == EOF)
4056 break OUTER;
4057 }
4058 if (firstTypeDecl && mods == null && token.kind == IMPORT) {
4059 if (!semiList.isEmpty()) {
4060 if (source.compareTo(Source.JDK21) >= 0)
4061 reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
4062 else
4063 log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
4064 }
4065 seenImport = true;
4066 defs.append(importDeclaration());
4067 } else {
4068 Comment docComment = token.docComment();
4069 if (firstTypeDecl && !seenImport && !seenPackage) {
4070 docComment = firstToken.docComment();
4071 consumedToplevelDoc = true;
4072 }
4073 if (mods != null || token.kind != SEMI)
4074 mods = modifiersOpt(mods);
4075 if (firstTypeDecl && token.kind == IDENTIFIER) {
4076 if (!semiList.isEmpty()) {
4077 if (source.compareTo(Source.JDK21) >= 0)
4078 reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
4079 else
4080 log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
4081 }
4082 ModuleKind kind = ModuleKind.STRONG;
4083 if (token.name() == names.open) {
4084 kind = ModuleKind.OPEN;
4085 nextToken();
4086 }
4087 if (token.kind == IDENTIFIER && token.name() == names.module) {
4088 if (mods != null) {
4089 checkNoMods(mods.flags & ~Flags.DEPRECATED);
4090 }
4091 defs.append(moduleDecl(mods, kind, docComment));
4092 consumedToplevelDoc = true;
4093 break;
4094 } else if (kind != ModuleKind.STRONG) {
4095 reportSyntaxError(token.pos, Errors.ExpectedModule);
4096 }
4097 }
4098
4099 defs.appendList(semiList.toList());
4100 boolean isTopLevelMethodOrField = false;
4101
4102 // Due to a significant number of existing negative tests
4103 // this code speculatively tests to see if a top level method
4104 // or field can parse. If the method or field can parse then
4105 // it is parsed. Otherwise, parsing continues as though
4106 // implicitly declared classes did not exist and error reporting
4107 // is the same as in the past.
4108 if (!isDeclaration(true)) {
4109 final JCModifiers finalMods = mods;
4110 JavacParser speculative = new VirtualParser(this);
4111 List<JCTree> speculativeResult =
4112 speculative.topLevelMethodOrFieldDeclaration(finalMods, null);
4113 if (speculativeResult.head.hasTag(METHODDEF) ||
4114 speculativeResult.head.hasTag(VARDEF)) {
4115 isTopLevelMethodOrField = true;
4116 }
4117 }
4118
4119 if (isTopLevelMethodOrField) {
4120 checkSourceLevel(token.pos, Feature.IMPLICIT_CLASSES);
4121 defs.appendList(topLevelMethodOrFieldDeclaration(mods, docComment));
4122 isImplicitClass = true;
4123 } else if (isDefiniteStatementStartToken()) {
4124 int startPos = token.pos;
4125 List<JCStatement> statements = blockStatement();
4126 defs.append(syntaxError(startPos,
4127 statements,
4128 Errors.StatementNotExpected,
4129 true));
4130 } else {
4131 JCTree def = typeDeclaration(mods, docComment);
4132 if (def instanceof JCExpressionStatement statement)
4133 def = statement.expr;
4134 defs.append(def);
4135 }
4136
4137 mods = null;
4138 firstTypeDecl = false;
4139 }
4140 }
4141 List<JCTree> topLevelDefs = isImplicitClass ? constructImplicitClass(defs.toList(), S.prevToken().endPos) : defs.toList();
4142 JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(topLevelDefs);
4143 if (!consumedToplevelDoc)
4144 attach(toplevel, firstToken.docComment());
4145 if (defs.isEmpty())
4146 storeEnd(toplevel, S.prevToken().endPos);
4147 if (keepDocComments)
4148 toplevel.docComments = docComments;
4149 if (keepLineMap)
4150 toplevel.lineMap = S.getLineMap();
4151 return toplevel;
4152 }
4153
4154 // Restructure top level to be an implicitly declared class.
4155 private List<JCTree> constructImplicitClass(List<JCTree> origDefs, int endPos) {
4156 ListBuffer<JCTree> topDefs = new ListBuffer<>();
4157 ListBuffer<JCTree> defs = new ListBuffer<>();
4158
4159 for (JCTree def : origDefs) {
4160 if (def.hasTag(Tag.PACKAGEDEF)) {
4161 log.error(def.pos(), Errors.ImplicitClassShouldNotHavePackageDeclaration);
4162 } else if (def.hasTag(Tag.IMPORT) || def.hasTag(Tag.MODULEIMPORT)) {
4163 topDefs.append(def);
4164 } else if (!def.hasTag(Tag.SKIP)) {
4165 defs.append(def);
4166 }
4167 }
4168
4169 int primaryPos = getStartPos(defs.first());
4170 String simplename = PathFileObject.getSimpleName(log.currentSourceFile());
4171
4172 if (simplename.endsWith(".java")) {
4173 simplename = simplename.substring(0, simplename.length() - ".java".length());
4174 }
4175 if (!SourceVersion.isIdentifier(simplename) || SourceVersion.isKeyword(simplename)) {
4176 log.error(primaryPos, Errors.BadFileName(simplename));
4177 }
4178
4179 Name name = names.fromString(simplename);
4180 JCModifiers implicitMods = F.at(Position.NOPOS)
4181 .Modifiers(Flags.FINAL|Flags.IMPLICIT_CLASS, List.nil());
4182 JCClassDecl implicit = F.at(primaryPos).ClassDef(
4183 implicitMods, name, List.nil(), null, List.nil(), List.nil(),
4184 defs.toList());
4185 storeEnd(implicit, endPos);
4186 topDefs.append(implicit);
4187 return topDefs.toList();
4188 }
4189
4190 JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
4191 int pos = token.pos;
4192 checkSourceLevel(Feature.MODULES);
4193
4194 nextToken();
4195 JCExpression name = qualident(false);
4196 List<JCDirective> directives = null;
4197
4198 accept(LBRACE);
4199 directives = moduleDirectiveList();
4200 accept(RBRACE);
4201 int endPos = S.prevToken().endPos;
4202 accept(EOF);
4203
4204 JCModuleDecl result = F.at(pos).ModuleDef(mods, kind, name, directives);
4205 storeEnd(result, endPos);
4206 return attach(result, dc);
4207 }
4208
4209 List<JCDirective> moduleDirectiveList() {
4210 ListBuffer<JCDirective> defs = new ListBuffer<>();
4211 while (token.kind == IDENTIFIER) {
4212 int pos = token.pos;
4213 if (token.name() == names.requires) {
4214 nextToken();
4215 boolean isTransitive = false;
4216 boolean isStaticPhase = false;
4217 loop:
4218 while (true) {
4219 switch (token.kind) {
4220 case IDENTIFIER:
4221 if (token.name() == names.transitive) {
4222 Token t1 = S.token(1);
4223 if (t1.kind == SEMI || t1.kind == DOT) {
4224 break loop;
4225 }
4226 if (isTransitive) {
4227 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
4228 }
4229 isTransitive = true;
4230 break;
4231 } else {
4232 break loop;
4233 }
4234 case STATIC:
4235 if (isStaticPhase) {
4236 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
4237 }
4238 isStaticPhase = true;
4239 break;
4240 default:
4241 break loop;
4242 }
4243 nextToken();
4244 }
4245 JCExpression moduleName = qualident(false);
4246 accept(SEMI);
4247 defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
4248 } else if (token.name() == names.exports || token.name() == names.opens) {
4249 boolean exports = token.name() == names.exports;
4250 nextToken();
4251 JCExpression pkgName = qualident(false);
4252 List<JCExpression> moduleNames = null;
4253 if (token.kind == IDENTIFIER && token.name() == names.to) {
4254 nextToken();
4255 moduleNames = qualidentList(false);
4256 }
4257 accept(SEMI);
4258 JCDirective d;
4259 if (exports) {
4260 d = F.at(pos).Exports(pkgName, moduleNames);
4261 } else {
4262 d = F.at(pos).Opens(pkgName, moduleNames);
4263 }
4264 defs.append(toP(d));
4265 } else if (token.name() == names.provides) {
4266 nextToken();
4267 JCExpression serviceName = qualident(false);
4268 List<JCExpression> implNames;
4269 if (token.kind == IDENTIFIER && token.name() == names.with) {
4270 nextToken();
4271 implNames = qualidentList(false);
4272 } else {
4273 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
4274 implNames = List.nil();
4275 }
4276 accept(SEMI);
4277 defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
4278 } else if (token.name() == names.uses) {
4279 nextToken();
4280 JCExpression service = qualident(false);
4281 accept(SEMI);
4282 defs.append(toP(F.at(pos).Uses(service)));
4283 } else {
4284 setErrorEndPos(pos);
4285 reportSyntaxError(pos, Errors.InvalidModuleDirective);
4286 break;
4287 }
4288 }
4289 return defs.toList();
4290 }
4291
4292 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
4293 */
4294 protected JCTree importDeclaration() {
4295 int pos = token.pos;
4296 nextToken();
4297 boolean importStatic = false;
4298 if (token.kind == STATIC) {
4299 importStatic = true;
4300 nextToken();
4301 } else if (token.kind == IDENTIFIER && token.name() == names.module &&
4302 peekToken(TokenKind.IDENTIFIER)) {
4303 checkSourceLevel(Feature.MODULE_IMPORTS);
4304 nextToken();
4305 JCExpression moduleName = qualident(false);
4306 accept(SEMI);
4307 return toP(F.at(pos).ModuleImport(moduleName));
4308 }
4309 JCExpression pid = toP(F.at(token.pos).Ident(ident()));
4310 do {
4311 int pos1 = token.pos;
4312 accept(DOT);
4313 if (token.kind == STAR) {
4314 pid = to(F.at(pos1).Select(pid, names.asterisk));
4315 nextToken();
4316 break;
4317 } else {
4318 pid = toP(F.at(pos1).Select(pid, ident()));
4319 }
4320 } while (token.kind == DOT);
4321 accept(SEMI);
4322 return toP(F.at(pos).Import((JCFieldAccess)pid, importStatic));
4323 }
4324
4325 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
4326 * | ";"
4327 */
4328 JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
4329 int pos = token.pos;
4330 if (mods == null && token.kind == SEMI) {
4331 nextToken();
4332 return toP(F.at(pos).Skip());
4333 } else {
4334 return classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
4335 }
4336 }
4337
4338 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
4339 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
4340 * @param mods Any modifiers starting the class or interface declaration
4341 * @param dc The documentation comment for the class, or null.
4342 */
4343 protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
4344 if (token.kind == CLASS) {
4345 return classDeclaration(mods, dc);
4346 } if (isRecordStart()) {
4347 return recordDeclaration(mods, dc);
4348 } else if (token.kind == INTERFACE) {
4349 return interfaceDeclaration(mods, dc);
4350 } else if (token.kind == ENUM) {
4351 return enumDeclaration(mods, dc);
4352 } else {
4353 int pos = token.pos;
4354 List<JCTree> errs;
4355 if (LAX_IDENTIFIER.test(token.kind)) {
4356 errs = List.of(mods, toP(F.at(pos).Ident(ident())));
4357 setErrorEndPos(token.pos);
4358 } else {
4359 errs = List.of(mods);
4360 }
4361
4362 return toP(F.Exec(syntaxError(pos, errs, unexpectedTopLevelDefinitionStartError)));
4363
4364 }
4365 }
4366
4367 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
4368 * [IMPLEMENTS TypeList] ClassBody
4369 * @param mods The modifiers starting the class declaration
4370 * @param dc The documentation comment for the class, or null.
4371 */
4372 protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
4373 int pos = token.pos;
4374 accept(CLASS);
4375 Name name = typeName();
4376
4377 List<JCTypeParameter> typarams = typeParametersOpt();
4378
4379 JCExpression extending = null;
4380 if (token.kind == EXTENDS) {
4381 nextToken();
4382 extending = parseType();
4383 }
4384 List<JCExpression> implementing = List.nil();
4385 if (token.kind == IMPLEMENTS) {
4386 nextToken();
4387 implementing = typeList();
4388 }
4389 List<JCExpression> permitting = permitsClause(mods, "class");
4390
4391 saveDanglingDocComments(dc);
4392
4393 List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
4394 JCClassDecl result = toP(F.at(pos).ClassDef(
4395 mods, name, typarams, extending, implementing, permitting, defs));
4396 return attach(result, dc);
4397 }
4398
4399 protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) {
4400 int pos = token.pos;
4401 nextToken();
4402 mods.flags |= Flags.RECORD;
4403 Name name = typeName();
4404
4405 List<JCTypeParameter> typarams = typeParametersOpt();
4406
4407 List<JCVariableDecl> headerFields = formalParameters(false, true);
4408
4409 List<JCExpression> implementing = List.nil();
4410 if (token.kind == IMPLEMENTS) {
4411 nextToken();
4412 implementing = typeList();
4413 }
4414
4415 saveDanglingDocComments(dc);
4416
4417 List<JCTree> defs = classInterfaceOrRecordBody(name, false, true);
4418 java.util.List<JCVariableDecl> fields = new ArrayList<>();
4419 for (JCVariableDecl field : headerFields) {
4420 fields.add(field);
4421 }
4422 for (JCTree def : defs) {
4423 if (def.hasTag(METHODDEF)) {
4424 JCMethodDecl methDef = (JCMethodDecl) def;
4425 if (methDef.name == names.init && methDef.params.isEmpty() && (methDef.mods.flags & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0) {
4426 ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>();
4427 for (JCVariableDecl param : headerFields) {
4428 tmpParams.add(F.at(param)
4429 // we will get flags plus annotations from the record component
4430 .VarDef(F.Modifiers(Flags.PARAMETER | Flags.GENERATED_MEMBER | Flags.MANDATED | param.mods.flags & Flags.VARARGS,
4431 param.mods.annotations),
4432 param.name, param.vartype, null));
4433 }
4434 methDef.params = tmpParams.toList();
4435 }
4436 }
4437 }
4438 for (int i = fields.size() - 1; i >= 0; i--) {
4439 JCVariableDecl field = fields.get(i);
4440 defs = defs.prepend(field);
4441 }
4442 JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs));
4443 return attach(result, dc);
4444 }
4445
4446 Name typeName() {
4447 int pos = token.pos;
4448 Name name = ident();
4449 Source source = restrictedTypeNameStartingAtSource(name, pos, true);
4450 if (source != null) {
4451 reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, source));
4452 }
4453 return name;
4454 }
4455
4456 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
4457 * [EXTENDS TypeList] InterfaceBody
4458 * @param mods The modifiers starting the interface declaration
4459 * @param dc The documentation comment for the interface, or null.
4460 */
4461 protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
4462 int pos = token.pos;
4463 accept(INTERFACE);
4464
4465 Name name = typeName();
4466
4467 List<JCTypeParameter> typarams = typeParametersOpt();
4468
4469 List<JCExpression> extending = List.nil();
4470 if (token.kind == EXTENDS) {
4471 nextToken();
4472 extending = typeList();
4473 }
4474 List<JCExpression> permitting = permitsClause(mods, "interface");
4475
4476 saveDanglingDocComments(dc);
4477
4478 List<JCTree> defs;
4479 defs = classInterfaceOrRecordBody(name, true, false);
4480 JCClassDecl result = toP(F.at(pos).ClassDef(
4481 mods, name, typarams, null, extending, permitting, defs));
4482 return attach(result, dc);
4483 }
4484
4485 List<JCExpression> permitsClause(JCModifiers mods, String classOrInterface) {
4486 if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
4487 checkSourceLevel(Feature.SEALED_CLASSES);
4488 if ((mods.flags & Flags.SEALED) == 0) {
4489 log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed(classOrInterface)));
4490 }
4491 nextToken();
4492 return qualidentList(false);
4493 }
4494 return List.nil();
4495 }
4496
4497 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
4498 * @param mods The modifiers starting the enum declaration
4499 * @param dc The documentation comment for the enum, or null.
4500 */
4501 protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
4502 int pos = token.pos;
4503 accept(ENUM);
4504
4505 Name name = typeName();
4506
4507 int typeNamePos = token.pos;
4508 List<JCTypeParameter> typarams = typeParametersOpt(true);
4509 if (typarams == null || !typarams.isEmpty()) {
4510 int errorPosition = typarams == null
4511 ? typeNamePos
4512 : typarams.head.pos;
4513 log.error(DiagnosticFlag.SYNTAX, errorPosition, Errors.EnumCantBeGeneric);
4514 }
4515
4516 List<JCExpression> implementing = List.nil();
4517 if (token.kind == IMPLEMENTS) {
4518 nextToken();
4519 implementing = typeList();
4520 }
4521
4522 saveDanglingDocComments(dc);
4523
4524 List<JCTree> defs = enumBody(name);
4525 mods.flags |= Flags.ENUM;
4526 JCClassDecl result = toP(F.at(pos).
4527 ClassDef(mods, name, List.nil(),
4528 null, implementing, defs));
4529 return attach(result, dc);
4530 }
4531
4532 /** EnumBody = "{" { EnumeratorDeclarationList } [","]
4533 * [ ";" {ClassBodyDeclaration} ] "}"
4534 */
4535 List<JCTree> enumBody(Name enumName) {
4536 accept(LBRACE);
4537 ListBuffer<JCTree> defs = new ListBuffer<>();
4538 boolean wasSemi = false;
4539 boolean hasStructuralErrors = false;
4540 boolean wasError = false;
4541 if (token.kind == COMMA) {
4542 nextToken();
4543 if (token.kind == SEMI) {
4544 wasSemi = true;
4545 nextToken();
4546 } else if (token.kind != RBRACE) {
4547 reportSyntaxError(S.prevToken().endPos,
4548 Errors.Expected2(RBRACE, SEMI));
4549 wasError = true;
4550 }
4551 }
4552 while (token.kind != RBRACE && token.kind != EOF) {
4553 if (token.kind == SEMI) {
4554 accept(SEMI);
4555 wasSemi = true;
4556 if (token.kind == RBRACE || token.kind == EOF) break;
4557 }
4558 EnumeratorEstimate memberType = estimateEnumeratorOrMember(enumName);
4559 if (memberType == EnumeratorEstimate.UNKNOWN) {
4560 memberType = wasSemi ? EnumeratorEstimate.MEMBER
4561 : EnumeratorEstimate.ENUMERATOR;
4562 }
4563 if (memberType == EnumeratorEstimate.ENUMERATOR) {
4564 wasError = false;
4565 if (wasSemi && !hasStructuralErrors) {
4566 reportSyntaxError(token.pos, Errors.EnumConstantNotExpected);
4567 hasStructuralErrors = true;
4568 }
4569 defs.append(enumeratorDeclaration(enumName));
4570 if (token.pos <= errorEndPos) {
4571 // error recovery
4572 skip(false, true, true, false);
4573 } else {
4574 if (token.kind != RBRACE && token.kind != SEMI && token.kind != EOF) {
4575 if (token.kind == COMMA) {
4576 nextToken();
4577 } else {
4578 setErrorEndPos(token.pos);
4579 reportSyntaxError(S.prevToken().endPos,
4580 Errors.Expected3(COMMA, RBRACE, SEMI));
4581 wasError = true;
4582 }
4583 }
4584 }
4585 } else {
4586 if (!wasSemi && !hasStructuralErrors && !wasError) {
4587 reportSyntaxError(token.pos, Errors.EnumConstantExpected);
4588 hasStructuralErrors = true;
4589 }
4590 wasError = false;
4591 defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, enumName,
4592 false, false));
4593 if (token.pos <= errorEndPos) {
4594 // error recovery
4595 skip(false, true, true, false);
4596 }
4597 }
4598 }
4599 accept(RBRACE);
4600 return defs.toList();
4601 }
4602
4603 @SuppressWarnings("fallthrough")
4604 private EnumeratorEstimate estimateEnumeratorOrMember(Name enumName) {
4605 // if we are seeing a record declaration inside of an enum we want the same error message as expected for a
4606 // let's say an interface declaration inside an enum
4607 boolean ident = token.kind == TokenKind.IDENTIFIER ||
4608 token.kind == TokenKind.UNDERSCORE;
4609 if (ident && token.name() != enumName &&
4610 (!allowRecords || !isRecordStart())) {
4611 Token next = S.token(1);
4612 switch (next.kind) {
4613 case LPAREN: case LBRACE: case COMMA: case SEMI:
4614 return EnumeratorEstimate.ENUMERATOR;
4615 }
4616 }
4617 switch (token.kind) {
4618 case IDENTIFIER:
4619 if (allowRecords && isRecordStart()) {
4620 return EnumeratorEstimate.MEMBER;
4621 }
4622 case MONKEYS_AT: case LT: case UNDERSCORE:
4623 return EnumeratorEstimate.UNKNOWN;
4624 default:
4625 return EnumeratorEstimate.MEMBER;
4626 }
4627 }
4628
4629 private enum EnumeratorEstimate {
4630 ENUMERATOR,
4631 MEMBER,
4632 UNKNOWN;
4633 }
4634
4635 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
4636 */
4637 JCTree enumeratorDeclaration(Name enumName) {
4638 Comment dc = token.docComment();
4639 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
4640 if (token.deprecatedFlag()) {
4641 flags |= Flags.DEPRECATED;
4642 }
4643 int pos = token.pos;
4644 List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
4645 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
4646 List<JCExpression> typeArgs = typeArgumentsOpt();
4647 int identPos = token.pos;
4648 Name name = ident();
4649 int createPos = token.pos;
4650
4651 saveDanglingDocComments(dc);
4652
4653 List<JCExpression> args = (token.kind == LPAREN)
4654 ? arguments() : List.nil();
4655
4656 JCClassDecl body = null;
4657 if (token.kind == LBRACE) {
4658 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM);
4659 List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
4660 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
4661 }
4662 if (args.isEmpty() && body == null)
4663 createPos = identPos;
4664 JCIdent ident = F.at(identPos).Ident(enumName);
4665 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
4666 if (createPos != identPos)
4667 storeEnd(create, S.prevToken().endPos);
4668 ident = F.at(identPos).Ident(enumName);
4669 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
4670 return attach(result, dc);
4671 }
4672
4673 /** TypeList = Type {"," Type}
4674 */
4675 List<JCExpression> typeList() {
4676 ListBuffer<JCExpression> ts = new ListBuffer<>();
4677 ts.append(parseType());
4678 while (token.kind == COMMA) {
4679 nextToken();
4680 ts.append(parseType());
4681 }
4682 return ts.toList();
4683 }
4684
4685 /** ClassBody = "{" {ClassBodyDeclaration} "}"
4686 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
4687 */
4688 List<JCTree> classInterfaceOrRecordBody(Name className, boolean isInterface, boolean isRecord) {
4689 accept(LBRACE);
4690 if (token.pos <= errorEndPos) {
4691 // error recovery
4692 skip(false, true, false, false);
4693 if (token.kind == LBRACE)
4694 nextToken();
4695 else
4696 return List.nil();
4697 }
4698 ListBuffer<JCTree> defs = new ListBuffer<>();
4699 while (token.kind != RBRACE && token.kind != EOF) {
4700 defs.appendList(classOrInterfaceOrRecordBodyDeclaration(null, className, isInterface, isRecord));
4701 if (token.pos <= errorEndPos) {
4702 // error recovery
4703 skip(false, true, true, false);
4704 }
4705 }
4706 accept(RBRACE);
4707 return defs.toList();
4708 }
4709
4710 /** ClassBodyDeclaration =
4711 * ";"
4712 * | [STATIC] Block
4713 * | ModifiersOpt
4714 * ( Type Ident
4715 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
4716 * | VOID Ident VoidMethodDeclaratorRest
4717 * | TypeParameters [Annotations]
4718 * ( Type Ident MethodDeclaratorRest
4719 * | VOID Ident VoidMethodDeclaratorRest
4720 * )
4721 * | Ident ConstructorDeclaratorRest
4722 * | TypeParameters Ident ConstructorDeclaratorRest
4723 * | ClassOrInterfaceOrEnumDeclaration
4724 * )
4725 * InterfaceBodyDeclaration =
4726 * ";"
4727 * | ModifiersOpt
4728 * ( Type Ident
4729 * ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
4730 * | VOID Ident MethodDeclaratorRest
4731 * | TypeParameters [Annotations]
4732 * ( Type Ident MethodDeclaratorRest
4733 * | VOID Ident VoidMethodDeclaratorRest
4734 * )
4735 * | ClassOrInterfaceOrEnumDeclaration
4736 * )
4737 *
4738 */
4739 protected List<JCTree> classOrInterfaceOrRecordBodyDeclaration(JCModifiers mods, Name className,
4740 boolean isInterface,
4741 boolean isRecord) {
4742 if (token.kind == SEMI) {
4743 nextToken();
4744 return List.nil();
4745 } else {
4746 Comment dc = token.docComment();
4747 int pos = token.pos;
4748 mods = modifiersOpt(mods);
4749 if (isDeclaration()) {
4750 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
4751 } else if (token.kind == LBRACE &&
4752 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
4753 mods.annotations.isEmpty()) {
4754 if (isInterface) {
4755 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
4756 } else if (isRecord && (mods.flags & Flags.STATIC) == 0) {
4757 log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InstanceInitializerNotAllowedInRecords);
4758 }
4759 ignoreDanglingComments(); // no declaration with which dangling comments can be associated
4760 return List.of(block(pos, mods.flags));
4761 } else if (isDefiniteStatementStartToken()) {
4762 int startPos = token.pos;
4763 List<JCStatement> statements = blockStatement();
4764 return List.of(syntaxError(startPos,
4765 statements,
4766 Errors.StatementNotExpected));
4767 } else {
4768 return constructorOrMethodOrFieldDeclaration(mods, className, isInterface, isRecord, dc);
4769 }
4770 }
4771 }
4772
4773 private List<JCTree> constructorOrMethodOrFieldDeclaration(JCModifiers mods, Name className,
4774 boolean isInterface,
4775 boolean isRecord, Comment dc) {
4776 int pos;
4777 pos = token.pos;
4778 List<JCTypeParameter> typarams = typeParametersOpt();
4779 // if there are type parameters but no modifiers, save the start
4780 // position of the method in the modifiers.
4781 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4782 mods.pos = pos;
4783 storeEnd(mods, pos);
4784 }
4785 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4786
4787 if (annosAfterParams.nonEmpty()) {
4788 mods.annotations = mods.annotations.appendList(annosAfterParams);
4789 if (mods.pos == Position.NOPOS)
4790 mods.pos = mods.annotations.head.pos;
4791 }
4792
4793 Token tk = token;
4794 pos = token.pos;
4795 JCExpression type;
4796 boolean isVoid = token.kind == VOID;
4797
4798 if (isVoid) {
4799 type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4800 nextToken();
4801 } else {
4802 // method returns types are un-annotated types
4803 type = unannotatedType(false);
4804 }
4805
4806 // Constructor
4807 if ((token.kind == LPAREN && !isInterface ||
4808 isRecord && token.kind == LBRACE) && type.hasTag(IDENT)) {
4809 if (isInterface || tk.name() != className) {
4810 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4811 } else if (annosAfterParams.nonEmpty()) {
4812 illegal(annosAfterParams.head.pos);
4813 }
4814
4815 if (isRecord && token.kind == LBRACE) {
4816 mods.flags |= Flags.COMPACT_RECORD_CONSTRUCTOR;
4817 }
4818
4819 return List.of(methodDeclaratorRest(
4820 pos, mods, null, names.init, typarams,
4821 isInterface, true, isRecord, dc));
4822 }
4823
4824 // Record constructor
4825 if (isRecord && type.hasTag(IDENT) && token.kind == THROWS) {
4826 // trying to define a compact constructor with a throws clause
4827 log.error(DiagnosticFlag.SYNTAX, token.pos,
4828 Errors.InvalidCanonicalConstructorInRecord(
4829 Fragments.Compact,
4830 className,
4831 Fragments.ThrowsClauseNotAllowedForCanonicalConstructor(Fragments.Compact)));
4832 skip(false, true, false, false);
4833 return List.of(methodDeclaratorRest(
4834 pos, mods, null, names.init, typarams,
4835 isInterface, true, isRecord, dc));
4836 }
4837
4838 pos = token.pos;
4839 Name name = ident();
4840
4841 // Method
4842 if (token.kind == LPAREN) {
4843 return List.of(methodDeclaratorRest(
4844 pos, mods, type, name, typarams,
4845 isInterface, isVoid, false, dc));
4846 }
4847
4848 // Field
4849 if (!isVoid && typarams.isEmpty()) {
4850 if (!isRecord || (isRecord && (mods.flags & Flags.STATIC) != 0)) {
4851 List<JCTree> defs =
4852 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4853 new ListBuffer<JCTree>(), false).toList();
4854 accept(SEMI);
4855 storeEnd(defs.last(), S.prevToken().endPos);
4856 return defs;
4857 }
4858
4859 int errPos = pos;
4860 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4861 new ListBuffer<JCTree>(), false).toList();
4862 accept(SEMI);
4863 return List.of(syntaxError(errPos, null, Errors.RecordCannotDeclareInstanceFields));
4864 }
4865
4866 pos = token.pos;
4867 List<JCTree> err;
4868
4869 // Error recovery
4870 if (isVoid || typarams.nonEmpty()) {
4871 JCMethodDecl m =
4872 toP(F.at(pos).MethodDef(mods, name, type, typarams,
4873 List.nil(), List.nil(), null, null));
4874 attach(m, dc);
4875 err = List.of(m);
4876 } else {
4877 err = List.nil();
4878 }
4879
4880 return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
4881 }
4882
4883 private List<JCTree> topLevelMethodOrFieldDeclaration(JCModifiers mods, Comment dc) throws AssertionError {
4884 int pos = token.pos;
4885 dc = dc == null ? token.docComment() : dc;
4886 List<JCTypeParameter> typarams = typeParametersOpt();
4887
4888 // if there are type parameters but no modifiers, save the start
4889 // position of the method in the modifiers.
4890 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4891 mods.pos = pos;
4892 storeEnd(mods, pos);
4893 }
4894
4895 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4896
4897 if (annosAfterParams.nonEmpty()) {
4898 mods.annotations = mods.annotations.appendList(annosAfterParams);
4899 if (mods.pos == Position.NOPOS)
4900 mods.pos = mods.annotations.head.pos;
4901 }
4902
4903 pos = token.pos;
4904 JCExpression type;
4905 boolean isVoid = token.kind == VOID;
4906
4907 if (isVoid) {
4908 type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4909 nextToken();
4910 } else {
4911 type = unannotatedType(false);
4912 }
4913
4914 if (token.kind == IDENTIFIER) {
4915 pos = token.pos;
4916 Name name = ident();
4917
4918 // Method
4919 if (token.kind == LPAREN) {
4920 return List.of(methodDeclaratorRest(pos, mods, type, name, typarams,
4921 false, isVoid, false, dc));
4922 }
4923
4924 // Field
4925 if (!isVoid && typarams.isEmpty() &&
4926 (token.kind == EQ || token.kind == SEMI || token.kind == COMMA)) {
4927 List<JCTree> defs =
4928 variableDeclaratorsRest(pos, mods, type, name, false, dc,
4929 new ListBuffer<JCTree>(), false).toList();
4930 accept(SEMI);
4931 storeEnd(defs.last(), S.prevToken().endPos);
4932
4933 return defs;
4934 }
4935 } else if (token.kind == LPAREN && type.hasTag(IDENT)) {
4936 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4937
4938 return List.of(methodDeclaratorRest(
4939 pos, mods, null, names.init, typarams,
4940 false, true, false, dc));
4941 }
4942
4943 return List.of(F.Erroneous());
4944 }
4945
4946 protected boolean isDeclaration() {
4947 return isDeclaration(allowRecords);
4948 }
4949
4950 private boolean isDeclaration(boolean allowRecords) {
4951 return token.kind == CLASS ||
4952 token.kind == INTERFACE ||
4953 token.kind == ENUM ||
4954 isRecordStart() && allowRecords;
4955 }
4956
4957 /**
4958 * {@return true if and only if the current token is definitelly a token that
4959 * starts a statement.}
4960 */
4961 private boolean isDefiniteStatementStartToken() {
4962 return switch (token.kind) {
4963 case IF, WHILE, DO, SWITCH, RETURN, TRY, FOR, ASSERT, BREAK,
4964 CONTINUE, THROW -> true;
4965 default -> false;
4966 };
4967 }
4968
4969 protected boolean isRecordStart() {
4970 if (token.kind == IDENTIFIER && token.name() == names.record && peekToken(TokenKind.IDENTIFIER)) {
4971 checkSourceLevel(Feature.RECORDS);
4972 return true;
4973 } else {
4974 return false;
4975 }
4976 }
4977
4978 protected boolean isNonSealedClassStart(boolean local) {
4979 if (isNonSealedIdentifier(token, 0)) {
4980 Token next = S.token(3);
4981 return allowedAfterSealedOrNonSealed(next, local, true);
4982 }
4983 return false;
4984 }
4985
4986 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4987 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4988 Token tokenSub = S.token(lookAheadOffset + 1);
4989 Token tokenSealed = S.token(lookAheadOffset + 2);
4990 if (someToken.endPos == tokenSub.pos &&
4991 tokenSub.endPos == tokenSealed.pos &&
4992 tokenSealed.name() == names.sealed) {
4993 checkSourceLevel(Feature.SEALED_CLASSES);
4994 return true;
4995 }
4996 }
4997 return false;
4998 }
4999
5000 protected boolean isSealedClassStart(boolean local) {
5001 if (token.name() == names.sealed) {
5002 Token next = S.token(1);
5003 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5004 checkSourceLevel(Feature.SEALED_CLASSES);
5005 return true;
5006 }
5007 }
5008 return false;
5009 }
5010
5011 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5012 return local ?
5013 switch (next.kind) {
5014 case MONKEYS_AT -> {
5015 Token afterNext = S.token(2);
5016 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5017 }
5018 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5019 default -> false;
5020 } :
5021 switch (next.kind) {
5022 case MONKEYS_AT -> {
5023 Token afterNext = S.token(2);
5024 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5025 }
5026 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5027 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
5028 default -> false;
5029 };
5030 }
5031
5032 /** MethodDeclaratorRest =
5033 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5034 * VoidMethodDeclaratorRest =
5035 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5036 * ConstructorDeclaratorRest =
5037 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5038 */
5039 protected JCTree methodDeclaratorRest(int pos,
5040 JCModifiers mods,
5041 JCExpression type,
5042 Name name,
5043 List<JCTypeParameter> typarams,
5044 boolean isInterface, boolean isVoid,
5045 boolean isRecord,
5046 Comment dc) {
5047 if (isInterface) {
5048 if ((mods.flags & Flags.PRIVATE) != 0) {
5049 checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
5050 }
5051 }
5052 JCVariableDecl prevReceiverParam = this.receiverParam;
5053 try {
5054 this.receiverParam = null;
5055 // Parsing formalParameters sets the receiverParam, if present
5056 List<JCVariableDecl> params = List.nil();
5057 List<JCExpression> thrown = List.nil();
5058 boolean unclosedParameterList;
5059 if (!isRecord || name != names.init || token.kind == LPAREN) {
5060 params = formalParameters();
5061 unclosedParameterList = token.pos == errorEndPos;
5062 if (!isVoid) type = bracketsOpt(type);
5063 if (token.kind == THROWS) {
5064 nextToken();
5065 thrown = qualidentList(true);
5066 }
5067 } else {
5068 unclosedParameterList = false;
5069 }
5070
5071 saveDanglingDocComments(dc);
5072
5073 JCBlock body = null;
5074 JCExpression defaultValue;
5075 if (token.kind == LBRACE) {
5076 body = block();
5077 defaultValue = null;
5078 } else {
5079 if (token.kind == DEFAULT) {
5080 accept(DEFAULT);
5081 defaultValue = annotationValue();
5082 accept(SEMI);
5083 } else {
5084 defaultValue = null;
5085 accept(SEMI, tk -> Errors.Expected2(LBRACE, SEMI));
5086 }
5087 if (token.pos <= errorEndPos) {
5088 // error recovery
5089 // look if there is a probable missing opening brace,
5090 // and if yes, parse as a block
5091 boolean parseAsBlock = openingBraceMissing(unclosedParameterList);
5092
5093 if (parseAsBlock) {
5094 body = block();
5095 }
5096 }
5097 }
5098
5099 JCMethodDecl result =
5100 toP(F.at(pos).MethodDef(mods, name, type, typarams,
5101 receiverParam, params, thrown,
5102 body, defaultValue));
5103 return attach(result, dc);
5104 } finally {
5105 this.receiverParam = prevReceiverParam;
5106 }
5107 }
5108
5109 /**
5110 * After seeing a method header, and not seeing an opening left brace,
5111 * attempt to estimate if acting as if the left brace was present and
5112 * parsing the upcoming code will get better results than not parsing
5113 * the code as a block.
5114 *
5115 * The estimate is as follows:
5116 * - tokens are skipped until member, statement or identifier is found,
5117 * - then, if there is a left brace, parse as a block,
5118 * - otherwise, if the head was broken, do not parse as a block,
5119 * - otherwise, look at the next token and:
5120 * - if it definitelly starts a statement, parse as a block,
5121 * - otherwise, if it is a closing/right brace, count opening and closing
5122 * braces in the rest of the file, to see if imaginarily "adding" an opening
5123 * brace would lead to a balanced count - if yes, parse as a block,
5124 * - otherwise, speculatively parse the following code as a block, and if
5125 * it contains statements that cannot be members, parse as a block,
5126 * - otherwise, don't parse as a block.
5127 *
5128 * @param unclosedParameterList whether there was a serious problem in the
5129 * parameters list
5130 * @return true if and only if the following code should be parsed as a block.
5131 */
5132 private boolean openingBraceMissing(boolean unclosedParameterList) {
5133 skip(false, true, !unclosedParameterList, !unclosedParameterList);
5134
5135 if (token.kind == LBRACE) {
5136 return true;
5137 } else if (unclosedParameterList) {
5138 return false;
5139 } else {
5140 return switch (token.kind) {
5141 //definitelly sees a statement:
5142 case CASE, DEFAULT, IF, FOR, WHILE, DO, TRY, SWITCH,
5143 RETURN, THROW, BREAK, CONTINUE, ELSE, FINALLY,
5144 CATCH, THIS, SUPER, NEW -> true;
5145 case RBRACE -> {
5146 //check if adding an opening brace would balance out
5147 //the opening and closing braces:
5148 int braceBalance = 1;
5149 VirtualScanner virtualScanner = new VirtualScanner(S);
5150
5151 virtualScanner.nextToken();
5152
5153 while (virtualScanner.token().kind != TokenKind.EOF) {
5154 switch (virtualScanner.token().kind) {
5155 case LBRACE -> braceBalance++;
5156 case RBRACE -> braceBalance--;
5157 }
5158 virtualScanner.nextToken();
5159 }
5160
5161 yield braceBalance == 0;
5162 }
5163 default -> {
5164 //speculatively try to parse as a block, and check
5165 //if the result would suggest there is a block
5166 //e.g.: it contains a statement that is not
5167 //a member declaration
5168 JavacParser speculative = new VirtualParser(this);
5169 JCBlock speculativeResult =
5170 speculative.block();
5171 if (!speculativeResult.stats.isEmpty()) {
5172 JCStatement last = speculativeResult.stats.last();
5173 yield !speculativeResult.stats.stream().allMatch(s -> s.hasTag(VARDEF) ||
5174 s.hasTag(CLASSDEF) ||
5175 s.hasTag(BLOCK) ||
5176 s == last) ||
5177 !(last instanceof JCExpressionStatement exprStatement &&
5178 exprStatement.expr.hasTag(ERRONEOUS));
5179 } else {
5180 yield false;
5181 }
5182 }
5183 };
5184 }
5185 }
5186
5187 /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
5188 */
5189 List<JCExpression> qualidentList(boolean allowAnnos) {
5190 ListBuffer<JCExpression> ts = new ListBuffer<>();
5191
5192 List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
5193 JCExpression qi = qualident(allowAnnos);
5194 if (!typeAnnos.isEmpty()) {
5195 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
5196 ts.append(at);
5197 } else {
5198 ts.append(qi);
5199 }
5200 while (token.kind == COMMA) {
5201 nextToken();
5202
5203 typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
5204 qi = qualident(allowAnnos);
5205 if (!typeAnnos.isEmpty()) {
5206 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
5207 ts.append(at);
5208 } else {
5209 ts.append(qi);
5210 }
5211 }
5212 return ts.toList();
5213 }
5214
5215 /**
5216 * {@literal
5217 * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
5218 * }
5219 */
5220 protected List<JCTypeParameter> typeParametersOpt() {
5221 return typeParametersOpt(false);
5222 }
5223 /** Parses a potentially empty type parameter list if needed with `allowEmpty`.
5224 * The caller is free to choose the desirable error message in this (erroneous) case.
5225 */
5226 protected List<JCTypeParameter> typeParametersOpt(boolean parseEmpty) {
5227 if (token.kind == LT) {
5228 ListBuffer<JCTypeParameter> typarams = new ListBuffer<>();
5229 nextToken();
5230
5231 if (parseEmpty && token.kind == GT) {
5232 accept(GT);
5233 return null;
5234 }
5235
5236 typarams.append(typeParameter());
5237 while (token.kind == COMMA) {
5238 nextToken();
5239 typarams.append(typeParameter());
5240 }
5241 accept(GT);
5242 return typarams.toList();
5243 } else {
5244 return List.nil();
5245 }
5246 }
5247
5248 /**
5249 * {@literal
5250 * TypeParameter = [Annotations] TypeVariable [TypeParameterBound]
5251 * TypeParameterBound = EXTENDS Type {"&" Type}
5252 * TypeVariable = Ident
5253 * }
5254 */
5255 JCTypeParameter typeParameter() {
5256 int pos = token.pos;
5257 List<JCAnnotation> annos = typeAnnotationsOpt();
5258 Name name = typeName();
5259 ListBuffer<JCExpression> bounds = new ListBuffer<>();
5260 if (token.kind == EXTENDS) {
5261 nextToken();
5262 bounds.append(parseType());
5263 while (token.kind == AMP) {
5264 nextToken();
5265 bounds.append(parseType());
5266 }
5267 }
5268 return toP(F.at(pos).TypeParameter(name, bounds.toList(), annos));
5269 }
5270
5271 /** FormalParameters = "(" [ FormalParameterList ] ")"
5272 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
5273 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
5274 */
5275 List<JCVariableDecl> formalParameters() {
5276 return formalParameters(false, false);
5277 }
5278 List<JCVariableDecl> formalParameters(boolean lambdaParameters, boolean recordComponents) {
5279 ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5280 JCVariableDecl lastParam;
5281 accept(LPAREN);
5282 if (token.kind != RPAREN) {
5283 this.allowThisIdent = !lambdaParameters && !recordComponents;
5284 lastParam = formalParameter(lambdaParameters, recordComponents);
5285 if (lastParam.nameexpr != null) {
5286 this.receiverParam = lastParam;
5287 } else {
5288 params.append(lastParam);
5289 }
5290 this.allowThisIdent = false;
5291 while (token.kind == COMMA) {
5292 if ((lastParam.mods.flags & Flags.VARARGS) != 0) {
5293 log.error(DiagnosticFlag.SYNTAX, lastParam, Errors.VarargsMustBeLast);
5294 }
5295 nextToken();
5296 params.append(lastParam = formalParameter(lambdaParameters, recordComponents));
5297 }
5298 }
5299 if (token.kind == RPAREN) {
5300 nextToken();
5301 } else {
5302 setErrorEndPos(token.pos);
5303 reportSyntaxError(S.prevToken().endPos, Errors.Expected3(COMMA, RPAREN, LBRACKET));
5304 }
5305 return params.toList();
5306 }
5307
5308 List<JCVariableDecl> implicitParameters(boolean hasParens) {
5309 if (hasParens) {
5310 accept(LPAREN);
5311 }
5312 ListBuffer<JCVariableDecl> params = new ListBuffer<>();
5313 if (token.kind != RPAREN && token.kind != ARROW) {
5314 params.append(implicitParameter());
5315 while (token.kind == COMMA) {
5316 nextToken();
5317 params.append(implicitParameter());
5318 }
5319 }
5320 if (hasParens) {
5321 accept(RPAREN);
5322 }
5323 return params.toList();
5324 }
5325
5326 JCModifiers optFinal(long flags) {
5327 JCModifiers mods = modifiersOpt();
5328 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
5329 mods.flags |= flags;
5330 return mods;
5331 }
5332
5333 /**
5334 * Inserts the annotations (and possibly a new array level)
5335 * to the left-most type in an array or nested type.
5336 *
5337 * When parsing a type like {@code @B Outer.Inner @A []}, the
5338 * {@code @A} annotation should target the array itself, while
5339 * {@code @B} targets the nested type {@code Outer}.
5340 *
5341 * Currently the parser parses the annotation first, then
5342 * the array, and then inserts the annotation to the left-most
5343 * nested type.
5344 *
5345 * When {@code createNewLevel} is true, then a new array
5346 * level is inserted as the most inner type, and have the
5347 * annotations target it. This is useful in the case of
5348 * varargs, e.g. {@code String @A [] @B ...}, as the parser
5349 * first parses the type {@code String @A []} then inserts
5350 * a new array level with {@code @B} annotation.
5351 */
5352 private JCExpression insertAnnotationsToMostInner(
5353 JCExpression type, List<JCAnnotation> annos,
5354 boolean createNewLevel) {
5355 int origEndPos = getEndPos(type);
5356 JCExpression mostInnerType = type;
5357 JCArrayTypeTree mostInnerArrayType = null;
5358 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEARRAY)) {
5359 mostInnerArrayType = (JCArrayTypeTree) TreeInfo.typeIn(mostInnerType);
5360 mostInnerType = mostInnerArrayType.elemtype;
5361 }
5362
5363 if (createNewLevel) {
5364 mostInnerType = to(F.at(token.pos).TypeArray(mostInnerType));
5365 origEndPos = getEndPos(mostInnerType);
5366 }
5367
5368 JCExpression mostInnerTypeToReturn = mostInnerType;
5369 if (annos.nonEmpty()) {
5370 JCExpression lastToModify = mostInnerType;
5371
5372 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT) ||
5373 TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5374 while (TreeInfo.typeIn(mostInnerType).hasTag(SELECT)) {
5375 lastToModify = mostInnerType;
5376 mostInnerType = ((JCFieldAccess) TreeInfo.typeIn(mostInnerType)).getExpression();
5377 }
5378 while (TreeInfo.typeIn(mostInnerType).hasTag(TYPEAPPLY)) {
5379 lastToModify = mostInnerType;
5380 mostInnerType = ((JCTypeApply) TreeInfo.typeIn(mostInnerType)).clazz;
5381 }
5382 }
5383
5384 mostInnerType = F.at(annos.head.pos).AnnotatedType(annos, mostInnerType);
5385
5386 if (TreeInfo.typeIn(lastToModify).hasTag(TYPEAPPLY)) {
5387 ((JCTypeApply) TreeInfo.typeIn(lastToModify)).clazz = mostInnerType;
5388 } else if (TreeInfo.typeIn(lastToModify).hasTag(SELECT)) {
5389 ((JCFieldAccess) TreeInfo.typeIn(lastToModify)).selected = mostInnerType;
5390 } else {
5391 // We never saw a SELECT or TYPEAPPLY, return the annotated type.
5392 mostInnerTypeToReturn = mostInnerType;
5393 }
5394 }
5395
5396 if (mostInnerArrayType == null) {
5397 return mostInnerTypeToReturn;
5398 } else {
5399 mostInnerArrayType.elemtype = mostInnerTypeToReturn;
5400 return storeEnd(type, origEndPos);
5401 }
5402 }
5403
5404 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
5405 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
5406 */
5407 protected JCVariableDecl formalParameter(boolean lambdaParameter, boolean recordComponent) {
5408 JCModifiers mods = !recordComponent ? optFinal(Flags.PARAMETER) : modifiersOpt();
5409 if (recordComponent && mods.flags != 0) {
5410 log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers);
5411 }
5412 if (recordComponent) {
5413 mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.GENERATED_MEMBER;
5414 }
5415 // need to distinguish between vararg annos and array annos
5416 // look at typeAnnotationsPushedBack comment
5417 this.permitTypeAnnotationsPushBack = true;
5418 JCExpression type = parseType(lambdaParameter);
5419 this.permitTypeAnnotationsPushBack = false;
5420
5421 if (token.kind == ELLIPSIS) {
5422 List<JCAnnotation> varargsAnnos = typeAnnotationsPushedBack;
5423 typeAnnotationsPushedBack = List.nil();
5424 mods.flags |= Flags.VARARGS;
5425 // insert var arg type annotations
5426 type = insertAnnotationsToMostInner(type, varargsAnnos, true);
5427 nextToken();
5428 } else {
5429 // if not a var arg, then typeAnnotationsPushedBack should be null
5430 if (typeAnnotationsPushedBack.nonEmpty()) {
5431 reportSyntaxError(typeAnnotationsPushedBack.head.pos, Errors.IllegalStartOfType);
5432 }
5433 typeAnnotationsPushedBack = List.nil();
5434 }
5435 return variableDeclaratorId(mods, type, false, lambdaParameter, recordComponent);
5436 }
5437
5438 protected JCVariableDecl implicitParameter() {
5439 JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER);
5440 return variableDeclaratorId(mods, null, false, true, false);
5441 }
5442
5443 /* ---------- auxiliary methods -------------- */
5444 /** Check that given tree is a legal expression statement.
5445 */
5446 protected JCExpression checkExprStat(JCExpression t) {
5447 if (!TreeInfo.isExpressionStatement(t)) {
5448 JCExpression ret = F.at(t.pos).Erroneous(List.<JCTree>of(t));
5449 log.error(DiagnosticFlag.SYNTAX, ret, Errors.NotStmt);
5450 return ret;
5451 } else {
5452 return t;
5453 }
5454 }
5455
5456 /** Return precedence of operator represented by token,
5457 * -1 if token is not a binary operator. @see TreeInfo.opPrec
5458 */
5459 static int prec(TokenKind token) {
5460 JCTree.Tag oc = optag(token);
5461 return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1;
5462 }
5463
5464 /**
5465 * Return the lesser of two positions, making allowance for either one
5466 * being unset.
5467 */
5468 static int earlier(int pos1, int pos2) {
5469 if (pos1 == Position.NOPOS)
5470 return pos2;
5471 if (pos2 == Position.NOPOS)
5472 return pos1;
5473 return (pos1 < pos2 ? pos1 : pos2);
5474 }
5475
5476 /** Return operation tag of binary operator represented by token,
5477 * No_TAG if token is not a binary operator.
5478 */
5479 static JCTree.Tag optag(TokenKind token) {
5480 switch (token) {
5481 case BARBAR:
5482 return OR;
5483 case AMPAMP:
5484 return AND;
5485 case BAR:
5486 return BITOR;
5487 case BAREQ:
5488 return BITOR_ASG;
5489 case CARET:
5490 return BITXOR;
5491 case CARETEQ:
5492 return BITXOR_ASG;
5493 case AMP:
5494 return BITAND;
5495 case AMPEQ:
5496 return BITAND_ASG;
5497 case EQEQ:
5498 return JCTree.Tag.EQ;
5499 case BANGEQ:
5500 return NE;
5501 case LT:
5502 return JCTree.Tag.LT;
5503 case GT:
5504 return JCTree.Tag.GT;
5505 case LTEQ:
5506 return LE;
5507 case GTEQ:
5508 return GE;
5509 case LTLT:
5510 return SL;
5511 case LTLTEQ:
5512 return SL_ASG;
5513 case GTGT:
5514 return SR;
5515 case GTGTEQ:
5516 return SR_ASG;
5517 case GTGTGT:
5518 return USR;
5519 case GTGTGTEQ:
5520 return USR_ASG;
5521 case PLUS:
5522 return JCTree.Tag.PLUS;
5523 case PLUSEQ:
5524 return PLUS_ASG;
5525 case SUB:
5526 return MINUS;
5527 case SUBEQ:
5528 return MINUS_ASG;
5529 case STAR:
5530 return MUL;
5531 case STAREQ:
5532 return MUL_ASG;
5533 case SLASH:
5534 return DIV;
5535 case SLASHEQ:
5536 return DIV_ASG;
5537 case PERCENT:
5538 return MOD;
5539 case PERCENTEQ:
5540 return MOD_ASG;
5541 case INSTANCEOF:
5542 return TYPETEST;
5543 default:
5544 return NO_TAG;
5545 }
5546 }
5547
5548 /** Return operation tag of unary operator represented by token,
5549 * No_TAG if token is not a binary operator.
5550 */
5551 static JCTree.Tag unoptag(TokenKind token) {
5552 switch (token) {
5553 case PLUS:
5554 return POS;
5555 case SUB:
5556 return NEG;
5557 case BANG:
5558 return NOT;
5559 case TILDE:
5560 return COMPL;
5561 case PLUSPLUS:
5562 return PREINC;
5563 case SUBSUB:
5564 return PREDEC;
5565 default:
5566 return NO_TAG;
5567 }
5568 }
5569
5570 /** Return type tag of basic type represented by token,
5571 * NONE if token is not a basic type identifier.
5572 */
5573 static TypeTag typetag(TokenKind token) {
5574 switch (token) {
5575 case BYTE:
5576 return TypeTag.BYTE;
5577 case CHAR:
5578 return TypeTag.CHAR;
5579 case SHORT:
5580 return TypeTag.SHORT;
5581 case INT:
5582 return TypeTag.INT;
5583 case LONG:
5584 return TypeTag.LONG;
5585 case FLOAT:
5586 return TypeTag.FLOAT;
5587 case DOUBLE:
5588 return TypeTag.DOUBLE;
5589 case BOOLEAN:
5590 return TypeTag.BOOLEAN;
5591 default:
5592 return TypeTag.NONE;
5593 }
5594 }
5595
5596 void checkSourceLevel(Feature feature) {
5597 checkSourceLevel(token.pos, feature);
5598 }
5599
5600 protected void checkSourceLevel(int pos, Feature feature) {
5601 if (preview.isPreview(feature) && !preview.isEnabled()) {
5602 //preview feature without --preview flag, error
5603 log.error(pos, preview.disabledError(feature));
5604 } else if (!feature.allowedInSource(source)) {
5605 //incompatible source level, error
5606 log.error(pos, feature.error(source.name));
5607 } else if (preview.isPreview(feature)) {
5608 //use of preview feature, warn
5609 preview.warnPreview(pos, feature);
5610 }
5611 }
5612
5613 private void updateUnexpectedTopLevelDefinitionStartError(boolean hasPackageDecl) {
5614 //TODO: proper tests for this logic (and updates):
5615 if (parseModuleInfo) {
5616 unexpectedTopLevelDefinitionStartError = Errors.ExpectedModuleOrOpen;
5617 } else if (Feature.IMPLICIT_CLASSES.allowedInSource(source) && !hasPackageDecl) {
5618 unexpectedTopLevelDefinitionStartError = Errors.ClassMethodOrFieldExpected;
5619 } else if (allowRecords) {
5620 unexpectedTopLevelDefinitionStartError = Errors.Expected4(CLASS, INTERFACE, ENUM, "record");
5621 } else {
5622 unexpectedTopLevelDefinitionStartError = Errors.Expected3(CLASS, INTERFACE, ENUM);
5623 }
5624 }
5625 }