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