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