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