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