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