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.Warnings;
46 import com.sun.tools.javac.tree.*;
47 import com.sun.tools.javac.tree.JCTree.*;
48 import com.sun.tools.javac.util.*;
49 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
50 import com.sun.tools.javac.util.JCDiagnostic.Error;
51 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
52 import com.sun.tools.javac.util.List;
53
54 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
55 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
56 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
62 import static com.sun.tools.javac.tree.JCTree.Tag.*;
63 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
64 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
65 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
66 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
67
68 /**
69 * The parser maps a token sequence into an abstract syntax tree.
70 * The parser is a hand-written recursive-descent parser that
71 * implements the grammar described in the Java Language Specification.
72 * For efficiency reasons, an operator precedence scheme is used
73 * for parsing binary operation expressions.
74 *
75 * <p><b>This is NOT part of any supported API.
76 * If you write code that depends on this, you do so at your own risk.
77 * This code and its internal interfaces are subject to change or
78 * deletion without notice.</b>
79 */
80 public class JavacParser implements Parser {
81
174 boolean keepLineMap,
175 boolean keepEndPositions,
176 boolean parseModuleInfo) {
177 this.S = S;
178 nextToken(); // prime the pump
179 this.F = fac.F;
180 this.log = fac.log;
181 this.names = fac.names;
182 this.source = fac.source;
183 this.preview = fac.preview;
184 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
185 this.keepDocComments = keepDocComments;
186 this.parseModuleInfo = parseModuleInfo;
187 this.docComments = newDocCommentTable(keepDocComments, fac);
188 this.keepLineMap = keepLineMap;
189 this.errorTree = F.Erroneous();
190 this.endPosTable = newEndPosTable(keepEndPositions);
191 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
192 this.allowRecords = Feature.RECORDS.allowedInSource(source);
193 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
194 }
195
196 /** Construct a parser from an existing parser, with minimal overhead.
197 */
198 @SuppressWarnings("this-escape")
199 protected JavacParser(JavacParser parser,
200 Lexer S) {
201 this.S = S;
202 this.token = parser.token;
203 this.F = parser.F;
204 this.log = parser.log;
205 this.names = parser.names;
206 this.source = parser.source;
207 this.preview = parser.preview;
208 this.allowStringFolding = parser.allowStringFolding;
209 this.keepDocComments = false;
210 this.parseModuleInfo = false;
211 this.docComments = null;
212 this.errorTree = F.Erroneous();
213 this.endPosTable = newEndPosTable(false);
214 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
215 this.allowRecords = Feature.RECORDS.allowedInSource(source);
216 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
217 }
218
219 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
220 return keepEndPositions
221 ? new SimpleEndPosTable(this)
222 : new EmptyEndPosTable(this);
223 }
224
225 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
226 return keepDocComments ? new LazyDocCommentTable(fac) : null;
227 }
228
229 /** Switch: should we fold strings?
230 */
231 boolean allowStringFolding;
232
233 /** Switch: should we keep docComments?
234 */
235 boolean keepDocComments;
236
237 /** Switch: should we keep line table?
238 */
239 boolean keepLineMap;
240
241 /** Switch: is "this" allowed as an identifier?
242 * This is needed to parse receiver types.
243 */
244 boolean allowThisIdent;
245
246 /** Switch: is yield statement allowed in this source level?
247 */
248 boolean allowYieldStatement;
249
250 /** Switch: are records allowed in this source level?
251 */
252 boolean allowRecords;
253
254 /** Switch: are sealed types allowed in this source level?
255 */
256 boolean allowSealedTypes;
257
258 /** The type of the method receiver, as specified by a first "this" parameter.
259 */
260 JCVariableDecl receiverParam;
261
262 /** When terms are parsed, the mode determines which is expected:
263 * mode = EXPR : an expression
264 * mode = TYPE : a type
265 * mode = NOPARAMS : no parameters allowed for type
266 * mode = TYPEARG : type argument
267 * mode |= NOLAMBDA : lambdas are not allowed
268 */
269 protected static final int EXPR = 1 << 0;
270 protected static final int TYPE = 1 << 1;
271 protected static final int NOPARAMS = 1 << 2;
272 protected static final int TYPEARG = 1 << 3;
273 protected static final int DIAMOND = 1 << 4;
1551 token.kind == MONKEYS_AT) {
1552 //error recovery, case like:
1553 //int i = expr.<missing-ident>
1554 //@Deprecated
1555 if (typeArgs != null) illegal();
1556 return toP(t);
1557 }
1558 if (tyannos != null && tyannos.nonEmpty()) {
1559 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1560 }
1561 break;
1562 case ELLIPSIS:
1563 if (this.permitTypeAnnotationsPushBack) {
1564 this.typeAnnotationsPushedBack = annos;
1565 } else if (annos.nonEmpty()) {
1566 // Don't return here -- error recovery attempt
1567 illegal(annos.head.pos);
1568 }
1569 break loop;
1570 case LT:
1571 if (!isMode(TYPE) && isUnboundMemberRef()) {
1572 //this is an unbound method reference whose qualifier
1573 //is a generic type i.e. A<S>::m
1574 int pos1 = token.pos;
1575 accept(LT);
1576 ListBuffer<JCExpression> args = new ListBuffer<>();
1577 args.append(typeArgument());
1578 while (token.kind == COMMA) {
1579 nextToken();
1580 args.append(typeArgument());
1581 }
1582 accept(GT);
1583 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1584 while (token.kind == DOT) {
1585 nextToken();
1586 selectTypeMode();
1587 t = toP(F.at(token.pos).Select(t, ident()));
1588 t = typeArgumentsOpt(t);
1589 }
1590 t = bracketsOpt(t);
1591 if (token.kind != COLCOL) {
1592 //method reference expected here
1800 return illegal(annos.head.pos);
1801 }
1802 break;
1803 }
1804 }
1805 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1806 selectExprMode();
1807 t = to(F.at(token.pos).Unary(
1808 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1809 nextToken();
1810 }
1811 return toP(t);
1812 }
1813
1814 /**
1815 * If we see an identifier followed by a '<' it could be an unbound
1816 * method reference or a binary expression. To disambiguate, look for a
1817 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1818 */
1819 @SuppressWarnings("fallthrough")
1820 boolean isUnboundMemberRef() {
1821 int pos = 0, depth = 0;
1822 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1823 switch (t.kind) {
1824 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1825 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1826 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1827 case DOUBLE: case BOOLEAN: case CHAR:
1828 case MONKEYS_AT:
1829 break;
1830
1831 case LPAREN:
1832 // skip annotation values
1833 int nesting = 0;
1834 for (; ; pos++) {
1835 TokenKind tk2 = S.token(pos).kind;
1836 switch (tk2) {
1837 case EOF:
1838 return false;
1839 case LPAREN:
1840 nesting++;
2469 List<JCExpression> typeArgs = null;
2470 if (token.kind == LT) {
2471 typeArgs = typeArguments(false);
2472 }
2473 Name refName;
2474 ReferenceMode refMode;
2475 if (token.kind == NEW) {
2476 refMode = ReferenceMode.NEW;
2477 refName = names.init;
2478 nextToken();
2479 } else {
2480 refMode = ReferenceMode.INVOKE;
2481 refName = ident();
2482 }
2483 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2484 }
2485
2486 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2487 */
2488 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2489 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2490
2491 switch (token.kind) {
2492 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2493 case DOUBLE: case BOOLEAN:
2494 if (typeArgs == null) {
2495 if (newAnnotations.isEmpty()) {
2496 return arrayCreatorRest(newpos, basicType());
2497 } else {
2498 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2499 }
2500 }
2501 break;
2502 default:
2503 }
2504 JCExpression t = qualident(true);
2505
2506 int prevmode = mode;
2507 selectTypeMode();
2508 boolean diamondFound = false;
2509 int lastTypeargsPos = -1;
2510 if (token.kind == LT) {
2511 lastTypeargsPos = token.pos;
2512 t = typeArguments(t, true);
2513 diamondFound = isMode(DIAMOND);
2546 }
2547 else if (typeArgs != null) {
2548 int pos = newpos;
2549 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2550 // note: this should always happen but we should
2551 // not rely on this as the parser is continuously
2552 // modified to improve error recovery.
2553 pos = typeArgs.head.pos;
2554 }
2555 setErrorEndPos(S.prevToken().endPos);
2556 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2557 reportSyntaxError(err, Errors.CannotCreateArrayWithTypeArguments);
2558 return toP(err);
2559 }
2560 return e;
2561 } else if (token.kind == LPAREN) {
2562 // handle type annotations for instantiations and anonymous classes
2563 if (newAnnotations.nonEmpty()) {
2564 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2565 }
2566 return classCreatorRest(newpos, null, typeArgs, t);
2567 } else {
2568 setErrorEndPos(token.pos);
2569 reportSyntaxError(token.pos, Errors.Expected2(LPAREN, LBRACKET));
2570 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null));
2571 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2572 }
2573 }
2574
2575 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2576 */
2577 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2578 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2579
2580 JCExpression t = toP(F.at(token.pos).Ident(ident()));
2581
2582 if (newAnnotations.nonEmpty()) {
2583 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2584 }
2585
2586 if (token.kind == LT) {
2587 int prevmode = mode;
2588 t = typeArguments(t, true);
2589 setMode(prevmode);
2590 }
2591 return classCreatorRest(newpos, encl, typeArgs, t);
2592 }
2593
2594 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2595 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
2596 */
2597 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2598 List<JCAnnotation> annos = typeAnnotationsOpt();
2599
2600 accept(LBRACKET);
2601 if (token.kind == RBRACKET) {
2602 accept(RBRACKET);
2603 elemtype = bracketsOpt(elemtype, annos);
2604 if (token.kind == LBRACE) {
2605 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2606 if (annos.nonEmpty()) {
2607 // when an array initializer is present then
2608 // the parsed annotations should target the
2609 // new array tree
2610 // bracketsOpt inserts the annotation in
2611 // elemtype, and it needs to be corrected
2649 if (token.kind == LBRACE) {
2650 elems = arrayInitializerElements(newpos, elemtype);
2651 }
2652
2653 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), elems));
2654 na.dimAnnotations = dimAnnotations.toList();
2655
2656 if (elems != null) {
2657 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2658 }
2659
2660 return na;
2661 }
2662 }
2663
2664 /** ClassCreatorRest = Arguments [ClassBody]
2665 */
2666 JCNewClass classCreatorRest(int newpos,
2667 JCExpression encl,
2668 List<JCExpression> typeArgs,
2669 JCExpression t)
2670 {
2671 List<JCExpression> args = arguments();
2672 JCClassDecl body = null;
2673 if (token.kind == LBRACE) {
2674 int pos = token.pos;
2675 List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2676 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2677 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2678 }
2679 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2680 }
2681
2682 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2683 */
2684 JCExpression arrayInitializer(int newpos, JCExpression t) {
2685 List<JCExpression> elems = arrayInitializerElements(newpos, t);
2686 return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2687 }
2688
2689 List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2690 accept(LBRACE);
2691 ListBuffer<JCExpression> elems = new ListBuffer<>();
2692 if (token.kind == COMMA) {
2693 nextToken();
2694 } else if (token.kind != RBRACE) {
2695 elems.append(variableInitializer());
2696 while (token.kind == COMMA) {
2890 accept(SEMI);
2891 return List.of(toP(F.at(pos).Yield(t)));
2892 }
2893
2894 //else intentional fall-through
2895 } else {
2896 if (isNonSealedClassStart(true)) {
2897 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2898 nextToken();
2899 nextToken();
2900 nextToken();
2901 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2902 } else if (isSealedClassStart(true)) {
2903 checkSourceLevel(Feature.SEALED_CLASSES);
2904 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2905 nextToken();
2906 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2907 }
2908 }
2909 }
2910 if (isRecordStart() && allowRecords) {
2911 dc = token.docComment();
2912 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2913 } else {
2914 Token prevToken = token;
2915 JCExpression t = term(EXPR | TYPE);
2916 if (token.kind == COLON && t.hasTag(IDENT)) {
2917 nextToken();
2918 JCStatement stat = parseStatementAsBlock();
2919 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2920 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
2921 pos = token.pos;
2922 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2923 F.at(pos);
2924 return localVariableDeclarations(mods, t);
2925 } else {
2926 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2927 t = checkExprStat(t);
2928 accept(SEMI);
2929 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3383 nextToken();
3384 pos = token.pos;
3385 JCExpression t = parseExpression();
3386 // This Exec is a "StatementExpression"; it subsumes no terminating token
3387 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3388 }
3389 return stats;
3390 }
3391
3392 /** ForInit = StatementExpression MoreStatementExpressions
3393 * | { FINAL | '@' Annotation } Type VariableDeclarators
3394 */
3395 List<JCStatement> forInit() {
3396 ListBuffer<JCStatement> stats = new ListBuffer<>();
3397 int pos = token.pos;
3398 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3399 return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3400 } else {
3401 JCExpression t = term(EXPR | TYPE);
3402 if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3403 return variableDeclarators(modifiersOpt(), t, stats, true).toList();
3404 } else if (wasTypeMode() && token.kind == COLON) {
3405 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3406 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3407 } else {
3408 return moreStatementExpressions(pos, t, stats).toList();
3409 }
3410 }
3411 }
3412
3413 /** ForUpdate = StatementExpression MoreStatementExpressions
3414 */
3415 List<JCExpressionStatement> forUpdate() {
3416 return moreStatementExpressions(token.pos,
3417 parseExpression(),
3418 new ListBuffer<JCExpressionStatement>()).toList();
3419 }
3420
3421 /** AnnotationsOpt = { '@' Annotation }
3422 *
3423 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3480 case ABSTRACT : flag = Flags.ABSTRACT; break;
3481 case NATIVE : flag = Flags.NATIVE; break;
3482 case VOLATILE : flag = Flags.VOLATILE; break;
3483 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3484 case STRICTFP : flag = Flags.STRICTFP; break;
3485 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3486 case DEFAULT : flag = Flags.DEFAULT; break;
3487 case ERROR : flag = 0; nextToken(); break;
3488 case IDENTIFIER : {
3489 if (isNonSealedClassStart(false)) {
3490 flag = Flags.NON_SEALED;
3491 nextToken();
3492 nextToken();
3493 break;
3494 }
3495 if (isSealedClassStart(false)) {
3496 checkSourceLevel(Feature.SEALED_CLASSES);
3497 flag = Flags.SEALED;
3498 break;
3499 }
3500 break loop;
3501 }
3502 default: break loop;
3503 }
3504 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3505 lastPos = token.pos;
3506 nextToken();
3507 if (flag == Flags.ANNOTATION) {
3508 if (token.kind != INTERFACE) {
3509 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3510 // if first modifier is an annotation, set pos to annotation's.
3511 if (flags == 0 && annotations.isEmpty())
3512 pos = ann.pos;
3513 annotations.append(ann);
3514 flag = 0;
3515 }
3516 }
3517 flags |= flag;
3518 }
3519 switch (token.kind) {
3746 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3747 return Source.JDK10;
3748 } else if (shouldWarn) {
3749 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3750 }
3751 }
3752 if (name == names.yield) {
3753 if (allowYieldStatement) {
3754 return Source.JDK14;
3755 } else if (shouldWarn) {
3756 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3757 }
3758 }
3759 if (name == names.record) {
3760 if (allowRecords) {
3761 return Source.JDK14;
3762 } else if (shouldWarn) {
3763 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3764 }
3765 }
3766 if (name == names.sealed) {
3767 if (allowSealedTypes) {
3768 return Source.JDK15;
3769 } else if (shouldWarn) {
3770 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3771 }
3772 }
3773 if (name == names.permits) {
3774 if (allowSealedTypes) {
3775 return Source.JDK15;
3776 } else if (shouldWarn) {
3777 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3778 }
3779 }
3780 return null;
3781 }
3782
3783 /** VariableDeclaratorId = Ident BracketsOpt
3784 */
3785 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4813 Token next = S.token(3);
4814 return allowedAfterSealedOrNonSealed(next, local, true);
4815 }
4816 return false;
4817 }
4818
4819 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4820 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4821 Token tokenSub = S.token(lookAheadOffset + 1);
4822 Token tokenSealed = S.token(lookAheadOffset + 2);
4823 if (someToken.endPos == tokenSub.pos &&
4824 tokenSub.endPos == tokenSealed.pos &&
4825 tokenSealed.name() == names.sealed) {
4826 checkSourceLevel(Feature.SEALED_CLASSES);
4827 return true;
4828 }
4829 }
4830 return false;
4831 }
4832
4833 protected boolean isSealedClassStart(boolean local) {
4834 if (token.name() == names.sealed) {
4835 Token next = S.token(1);
4836 if (allowedAfterSealedOrNonSealed(next, local, false)) {
4837 checkSourceLevel(Feature.SEALED_CLASSES);
4838 return true;
4839 }
4840 }
4841 return false;
4842 }
4843
4844 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4845 return local ?
4846 switch (next.kind) {
4847 case MONKEYS_AT -> {
4848 Token afterNext = S.token(2);
4849 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4850 }
4851 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4852 default -> false;
4853 } :
4854 switch (next.kind) {
4855 case MONKEYS_AT -> {
4856 Token afterNext = S.token(2);
4857 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4858 }
4859 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4860 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
4861 default -> false;
4862 };
4863 }
4864
4865 /** MethodDeclaratorRest =
4866 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4867 * VoidMethodDeclaratorRest =
4868 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
4869 * ConstructorDeclaratorRest =
4870 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4871 */
4872 protected JCTree methodDeclaratorRest(int pos,
4873 JCModifiers mods,
4874 JCExpression type,
4875 Name name,
4876 List<JCTypeParameter> typarams,
4877 boolean isInterface, boolean isVoid,
4878 boolean isRecord,
4879 Comment dc) {
4880 if (isInterface) {
|
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.Flags.Flag;
41 import com.sun.tools.javac.code.Source.Feature;
42 import com.sun.tools.javac.file.PathFileObject;
43 import com.sun.tools.javac.parser.Tokens.*;
44 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
45 import com.sun.tools.javac.resources.CompilerProperties.Errors;
46 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
47 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
48 import com.sun.tools.javac.tree.*;
49 import com.sun.tools.javac.tree.JCTree.*;
50 import com.sun.tools.javac.util.*;
51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
52 import com.sun.tools.javac.util.JCDiagnostic.Error;
53 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
54 import com.sun.tools.javac.util.List;
55
56 import static com.sun.tools.javac.code.Flags.asFlagSet;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
62 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
63 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
64 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
65 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
66 import static com.sun.tools.javac.tree.JCTree.Tag.*;
67 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
68 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
70 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
71
72 /**
73 * The parser maps a token sequence into an abstract syntax tree.
74 * The parser is a hand-written recursive-descent parser that
75 * implements the grammar described in the Java Language Specification.
76 * For efficiency reasons, an operator precedence scheme is used
77 * for parsing binary operation expressions.
78 *
79 * <p><b>This is NOT part of any supported API.
80 * If you write code that depends on this, you do so at your own risk.
81 * This code and its internal interfaces are subject to change or
82 * deletion without notice.</b>
83 */
84 public class JavacParser implements Parser {
85
178 boolean keepLineMap,
179 boolean keepEndPositions,
180 boolean parseModuleInfo) {
181 this.S = S;
182 nextToken(); // prime the pump
183 this.F = fac.F;
184 this.log = fac.log;
185 this.names = fac.names;
186 this.source = fac.source;
187 this.preview = fac.preview;
188 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
189 this.keepDocComments = keepDocComments;
190 this.parseModuleInfo = parseModuleInfo;
191 this.docComments = newDocCommentTable(keepDocComments, fac);
192 this.keepLineMap = keepLineMap;
193 this.errorTree = F.Erroneous();
194 this.endPosTable = newEndPosTable(keepEndPositions);
195 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
196 this.allowRecords = Feature.RECORDS.allowedInSource(source);
197 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
198 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
199 Feature.VALUE_CLASSES.allowedInSource(source);
200 }
201
202 /** Construct a parser from an existing parser, with minimal overhead.
203 */
204 @SuppressWarnings("this-escape")
205 protected JavacParser(JavacParser parser,
206 Lexer S) {
207 this.S = S;
208 this.token = parser.token;
209 this.F = parser.F;
210 this.log = parser.log;
211 this.names = parser.names;
212 this.source = parser.source;
213 this.preview = parser.preview;
214 this.allowStringFolding = parser.allowStringFolding;
215 this.keepDocComments = false;
216 this.parseModuleInfo = false;
217 this.docComments = null;
218 this.errorTree = F.Erroneous();
219 this.endPosTable = newEndPosTable(false);
220 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
221 this.allowRecords = Feature.RECORDS.allowedInSource(source);
222 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
223 this.allowValueClasses = parser.allowValueClasses;
224 }
225
226 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
227 return keepEndPositions
228 ? new SimpleEndPosTable(this)
229 : new EmptyEndPosTable(this);
230 }
231
232 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
233 return keepDocComments ? new LazyDocCommentTable(fac) : null;
234 }
235
236 /** Switch: should we fold strings?
237 */
238 boolean allowStringFolding;
239
240 /** Switch: should we keep docComments?
241 */
242 boolean keepDocComments;
243
244 /** Switch: should we keep line table?
245 */
246 boolean keepLineMap;
247
248 /** Switch: is "this" allowed as an identifier?
249 * This is needed to parse receiver types.
250 */
251 boolean allowThisIdent;
252
253 /** Switch: is yield statement allowed in this source level?
254 */
255 boolean allowYieldStatement;
256
257 /** Switch: are records allowed in this source level?
258 */
259 boolean allowRecords;
260
261 /** Switch: are value classes allowed in this source level?
262 */
263 boolean allowValueClasses;
264
265 /** Switch: are sealed types allowed in this source level?
266 */
267 boolean allowSealedTypes;
268
269 /** The type of the method receiver, as specified by a first "this" parameter.
270 */
271 JCVariableDecl receiverParam;
272
273 /** When terms are parsed, the mode determines which is expected:
274 * mode = EXPR : an expression
275 * mode = TYPE : a type
276 * mode = NOPARAMS : no parameters allowed for type
277 * mode = TYPEARG : type argument
278 * mode |= NOLAMBDA : lambdas are not allowed
279 */
280 protected static final int EXPR = 1 << 0;
281 protected static final int TYPE = 1 << 1;
282 protected static final int NOPARAMS = 1 << 2;
283 protected static final int TYPEARG = 1 << 3;
284 protected static final int DIAMOND = 1 << 4;
1562 token.kind == MONKEYS_AT) {
1563 //error recovery, case like:
1564 //int i = expr.<missing-ident>
1565 //@Deprecated
1566 if (typeArgs != null) illegal();
1567 return toP(t);
1568 }
1569 if (tyannos != null && tyannos.nonEmpty()) {
1570 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1571 }
1572 break;
1573 case ELLIPSIS:
1574 if (this.permitTypeAnnotationsPushBack) {
1575 this.typeAnnotationsPushedBack = annos;
1576 } else if (annos.nonEmpty()) {
1577 // Don't return here -- error recovery attempt
1578 illegal(annos.head.pos);
1579 }
1580 break loop;
1581 case LT:
1582 if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1583 //this is either an unbound method reference whose qualifier
1584 //is a generic type i.e. A<S>::m
1585 int pos1 = token.pos;
1586 accept(LT);
1587 ListBuffer<JCExpression> args = new ListBuffer<>();
1588 args.append(typeArgument());
1589 while (token.kind == COMMA) {
1590 nextToken();
1591 args.append(typeArgument());
1592 }
1593 accept(GT);
1594 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1595 while (token.kind == DOT) {
1596 nextToken();
1597 selectTypeMode();
1598 t = toP(F.at(token.pos).Select(t, ident()));
1599 t = typeArgumentsOpt(t);
1600 }
1601 t = bracketsOpt(t);
1602 if (token.kind != COLCOL) {
1603 //method reference expected here
1811 return illegal(annos.head.pos);
1812 }
1813 break;
1814 }
1815 }
1816 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1817 selectExprMode();
1818 t = to(F.at(token.pos).Unary(
1819 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1820 nextToken();
1821 }
1822 return toP(t);
1823 }
1824
1825 /**
1826 * If we see an identifier followed by a '<' it could be an unbound
1827 * method reference or a binary expression. To disambiguate, look for a
1828 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1829 */
1830 @SuppressWarnings("fallthrough")
1831 boolean isParameterizedTypePrefix() {
1832 int pos = 0, depth = 0;
1833 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1834 switch (t.kind) {
1835 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1836 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1837 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1838 case DOUBLE: case BOOLEAN: case CHAR:
1839 case MONKEYS_AT:
1840 break;
1841
1842 case LPAREN:
1843 // skip annotation values
1844 int nesting = 0;
1845 for (; ; pos++) {
1846 TokenKind tk2 = S.token(pos).kind;
1847 switch (tk2) {
1848 case EOF:
1849 return false;
1850 case LPAREN:
1851 nesting++;
2480 List<JCExpression> typeArgs = null;
2481 if (token.kind == LT) {
2482 typeArgs = typeArguments(false);
2483 }
2484 Name refName;
2485 ReferenceMode refMode;
2486 if (token.kind == NEW) {
2487 refMode = ReferenceMode.NEW;
2488 refName = names.init;
2489 nextToken();
2490 } else {
2491 refMode = ReferenceMode.INVOKE;
2492 refName = ident();
2493 }
2494 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2495 }
2496
2497 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2498 */
2499 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2500 final JCModifiers mods = modifiersOpt();
2501 List<JCAnnotation> newAnnotations = mods.annotations;
2502 switch (token.kind) {
2503 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2504 case DOUBLE: case BOOLEAN:
2505 if (mods.flags != 0) {
2506 log.error(token.pos, Errors.ModNotAllowedHere(asFlagSet(mods.flags)));
2507 }
2508 if (typeArgs == null) {
2509 if (newAnnotations.isEmpty()) {
2510 return arrayCreatorRest(newpos, basicType());
2511 } else {
2512 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2513 }
2514 }
2515 break;
2516 default:
2517 }
2518 JCExpression t = qualident(true);
2519
2520 int prevmode = mode;
2521 selectTypeMode();
2522 boolean diamondFound = false;
2523 int lastTypeargsPos = -1;
2524 if (token.kind == LT) {
2525 lastTypeargsPos = token.pos;
2526 t = typeArguments(t, true);
2527 diamondFound = isMode(DIAMOND);
2560 }
2561 else if (typeArgs != null) {
2562 int pos = newpos;
2563 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2564 // note: this should always happen but we should
2565 // not rely on this as the parser is continuously
2566 // modified to improve error recovery.
2567 pos = typeArgs.head.pos;
2568 }
2569 setErrorEndPos(S.prevToken().endPos);
2570 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2571 reportSyntaxError(err, Errors.CannotCreateArrayWithTypeArguments);
2572 return toP(err);
2573 }
2574 return e;
2575 } else if (token.kind == LPAREN) {
2576 // handle type annotations for instantiations and anonymous classes
2577 if (newAnnotations.nonEmpty()) {
2578 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2579 }
2580 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t, mods.flags);
2581 if ((newClass.def == null) && (mods.flags != 0)) {
2582 log.error(newClass.pos, Errors.ModNotAllowedHere(asFlagSet(mods.flags)));
2583 }
2584 return newClass;
2585 } else {
2586 setErrorEndPos(token.pos);
2587 reportSyntaxError(token.pos, Errors.Expected2(LPAREN, LBRACKET));
2588 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null));
2589 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2590 }
2591 }
2592
2593 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2594 */
2595 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2596 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2597
2598 JCExpression t = toP(F.at(token.pos).Ident(ident()));
2599
2600 if (newAnnotations.nonEmpty()) {
2601 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2602 }
2603
2604 if (token.kind == LT) {
2605 int prevmode = mode;
2606 t = typeArguments(t, true);
2607 setMode(prevmode);
2608 }
2609 return classCreatorRest(newpos, encl, typeArgs, t, 0);
2610 }
2611
2612 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2613 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
2614 */
2615 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2616 List<JCAnnotation> annos = typeAnnotationsOpt();
2617
2618 accept(LBRACKET);
2619 if (token.kind == RBRACKET) {
2620 accept(RBRACKET);
2621 elemtype = bracketsOpt(elemtype, annos);
2622 if (token.kind == LBRACE) {
2623 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2624 if (annos.nonEmpty()) {
2625 // when an array initializer is present then
2626 // the parsed annotations should target the
2627 // new array tree
2628 // bracketsOpt inserts the annotation in
2629 // elemtype, and it needs to be corrected
2667 if (token.kind == LBRACE) {
2668 elems = arrayInitializerElements(newpos, elemtype);
2669 }
2670
2671 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), elems));
2672 na.dimAnnotations = dimAnnotations.toList();
2673
2674 if (elems != null) {
2675 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2676 }
2677
2678 return na;
2679 }
2680 }
2681
2682 /** ClassCreatorRest = Arguments [ClassBody]
2683 */
2684 JCNewClass classCreatorRest(int newpos,
2685 JCExpression encl,
2686 List<JCExpression> typeArgs,
2687 JCExpression t,
2688 long flags)
2689 {
2690 List<JCExpression> args = arguments();
2691 JCClassDecl body = null;
2692 if (token.kind == LBRACE) {
2693 int pos = token.pos;
2694 List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2695 JCModifiers mods = F.at(Position.NOPOS).Modifiers(flags);
2696 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2697 }
2698 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2699 }
2700
2701 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2702 */
2703 JCExpression arrayInitializer(int newpos, JCExpression t) {
2704 List<JCExpression> elems = arrayInitializerElements(newpos, t);
2705 return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2706 }
2707
2708 List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2709 accept(LBRACE);
2710 ListBuffer<JCExpression> elems = new ListBuffer<>();
2711 if (token.kind == COMMA) {
2712 nextToken();
2713 } else if (token.kind != RBRACE) {
2714 elems.append(variableInitializer());
2715 while (token.kind == COMMA) {
2909 accept(SEMI);
2910 return List.of(toP(F.at(pos).Yield(t)));
2911 }
2912
2913 //else intentional fall-through
2914 } else {
2915 if (isNonSealedClassStart(true)) {
2916 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2917 nextToken();
2918 nextToken();
2919 nextToken();
2920 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2921 } else if (isSealedClassStart(true)) {
2922 checkSourceLevel(Feature.SEALED_CLASSES);
2923 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2924 nextToken();
2925 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2926 }
2927 }
2928 }
2929 if ((isValueModifier()) && allowValueClasses) {
2930 checkSourceLevel(Feature.VALUE_CLASSES);
2931 dc = token.docComment();
2932 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2933 }
2934 if (isRecordStart() && allowRecords) {
2935 dc = token.docComment();
2936 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2937 } else {
2938 Token prevToken = token;
2939 JCExpression t = term(EXPR | TYPE);
2940 if (token.kind == COLON && t.hasTag(IDENT)) {
2941 nextToken();
2942 JCStatement stat = parseStatementAsBlock();
2943 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2944 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
2945 pos = token.pos;
2946 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2947 F.at(pos);
2948 return localVariableDeclarations(mods, t);
2949 } else {
2950 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2951 t = checkExprStat(t);
2952 accept(SEMI);
2953 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3407 nextToken();
3408 pos = token.pos;
3409 JCExpression t = parseExpression();
3410 // This Exec is a "StatementExpression"; it subsumes no terminating token
3411 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3412 }
3413 return stats;
3414 }
3415
3416 /** ForInit = StatementExpression MoreStatementExpressions
3417 * | { FINAL | '@' Annotation } Type VariableDeclarators
3418 */
3419 List<JCStatement> forInit() {
3420 ListBuffer<JCStatement> stats = new ListBuffer<>();
3421 int pos = token.pos;
3422 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3423 return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3424 } else {
3425 JCExpression t = term(EXPR | TYPE);
3426 if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3427 pos = token.pos;
3428 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3429 F.at(pos);
3430 return variableDeclarators(mods, t, stats, true).toList();
3431 } else if (wasTypeMode() && token.kind == COLON) {
3432 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3433 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3434 } else {
3435 return moreStatementExpressions(pos, t, stats).toList();
3436 }
3437 }
3438 }
3439
3440 /** ForUpdate = StatementExpression MoreStatementExpressions
3441 */
3442 List<JCExpressionStatement> forUpdate() {
3443 return moreStatementExpressions(token.pos,
3444 parseExpression(),
3445 new ListBuffer<JCExpressionStatement>()).toList();
3446 }
3447
3448 /** AnnotationsOpt = { '@' Annotation }
3449 *
3450 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3507 case ABSTRACT : flag = Flags.ABSTRACT; break;
3508 case NATIVE : flag = Flags.NATIVE; break;
3509 case VOLATILE : flag = Flags.VOLATILE; break;
3510 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3511 case STRICTFP : flag = Flags.STRICTFP; break;
3512 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3513 case DEFAULT : flag = Flags.DEFAULT; break;
3514 case ERROR : flag = 0; nextToken(); break;
3515 case IDENTIFIER : {
3516 if (isNonSealedClassStart(false)) {
3517 flag = Flags.NON_SEALED;
3518 nextToken();
3519 nextToken();
3520 break;
3521 }
3522 if (isSealedClassStart(false)) {
3523 checkSourceLevel(Feature.SEALED_CLASSES);
3524 flag = Flags.SEALED;
3525 break;
3526 }
3527 if (isValueModifier()) {
3528 checkSourceLevel(Feature.VALUE_CLASSES);
3529 flag = Flags.VALUE_CLASS;
3530 break;
3531 }
3532 break loop;
3533 }
3534 default: break loop;
3535 }
3536 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3537 lastPos = token.pos;
3538 nextToken();
3539 if (flag == Flags.ANNOTATION) {
3540 if (token.kind != INTERFACE) {
3541 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3542 // if first modifier is an annotation, set pos to annotation's.
3543 if (flags == 0 && annotations.isEmpty())
3544 pos = ann.pos;
3545 annotations.append(ann);
3546 flag = 0;
3547 }
3548 }
3549 flags |= flag;
3550 }
3551 switch (token.kind) {
3778 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3779 return Source.JDK10;
3780 } else if (shouldWarn) {
3781 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3782 }
3783 }
3784 if (name == names.yield) {
3785 if (allowYieldStatement) {
3786 return Source.JDK14;
3787 } else if (shouldWarn) {
3788 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3789 }
3790 }
3791 if (name == names.record) {
3792 if (allowRecords) {
3793 return Source.JDK14;
3794 } else if (shouldWarn) {
3795 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3796 }
3797 }
3798 if (name == names.value) {
3799 if (allowValueClasses) {
3800 return Source.JDK22;
3801 } else if (shouldWarn) {
3802 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK22));
3803 }
3804 }
3805 if (name == names.sealed) {
3806 if (allowSealedTypes) {
3807 return Source.JDK15;
3808 } else if (shouldWarn) {
3809 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3810 }
3811 }
3812 if (name == names.permits) {
3813 if (allowSealedTypes) {
3814 return Source.JDK15;
3815 } else if (shouldWarn) {
3816 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3817 }
3818 }
3819 return null;
3820 }
3821
3822 /** VariableDeclaratorId = Ident BracketsOpt
3823 */
3824 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4852 Token next = S.token(3);
4853 return allowedAfterSealedOrNonSealed(next, local, true);
4854 }
4855 return false;
4856 }
4857
4858 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4859 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4860 Token tokenSub = S.token(lookAheadOffset + 1);
4861 Token tokenSealed = S.token(lookAheadOffset + 2);
4862 if (someToken.endPos == tokenSub.pos &&
4863 tokenSub.endPos == tokenSealed.pos &&
4864 tokenSealed.name() == names.sealed) {
4865 checkSourceLevel(Feature.SEALED_CLASSES);
4866 return true;
4867 }
4868 }
4869 return false;
4870 }
4871
4872 protected boolean isValueModifier() {
4873 if (token.kind == IDENTIFIER && token.name() == names.value) {
4874 boolean isValueModifier = false;
4875 Token next = S.token(1);
4876 switch (next.kind) {
4877 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
4878 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
4879 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
4880 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
4881 case CLASS: case INTERFACE: case ENUM:
4882 isValueModifier = true;
4883 break;
4884 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
4885 if (next.name() == names.record || next.name() == names.value
4886 || (mode & EXPR) != 0)
4887 isValueModifier = true;
4888 break;
4889 }
4890 if (isValueModifier) {
4891 checkSourceLevel(Feature.VALUE_CLASSES);
4892 return true;
4893 }
4894 }
4895 return false;
4896 }
4897
4898 protected boolean isSealedClassStart(boolean local) {
4899 if (token.name() == names.sealed) {
4900 Token next = S.token(1);
4901 if (allowedAfterSealedOrNonSealed(next, local, false)) {
4902 checkSourceLevel(Feature.SEALED_CLASSES);
4903 return true;
4904 }
4905 }
4906 return false;
4907 }
4908
4909 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4910 return local ?
4911 switch (next.kind) {
4912 case MONKEYS_AT -> {
4913 Token afterNext = S.token(2);
4914 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4915 }
4916 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4917 default -> false;
4918 } :
4919 switch (next.kind) {
4920 case MONKEYS_AT -> {
4921 Token afterNext = S.token(2);
4922 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4923 }
4924 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4925 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
4926 next.name() == names.sealed ||
4927 allowValueClasses && next.name() == names.value;
4928 default -> false;
4929 };
4930 }
4931
4932 /** MethodDeclaratorRest =
4933 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4934 * VoidMethodDeclaratorRest =
4935 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
4936 * ConstructorDeclaratorRest =
4937 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4938 */
4939 protected JCTree methodDeclaratorRest(int pos,
4940 JCModifiers mods,
4941 JCExpression type,
4942 Name name,
4943 List<JCTypeParameter> typarams,
4944 boolean isInterface, boolean isVoid,
4945 boolean isRecord,
4946 Comment dc) {
4947 if (isInterface) {
|