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