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