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