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 {
184 boolean keepEndPositions,
185 boolean parseModuleInfo) {
186 this.S = S;
187 nextToken(); // prime the pump
188 this.F = fac.F;
189 this.log = fac.log;
190 this.names = fac.names;
191 this.source = fac.source;
192 this.preview = fac.preview;
193 this.deferredLintHandler = fac.deferredLintHandler;
194 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
195 this.keepDocComments = keepDocComments;
196 this.parseModuleInfo = parseModuleInfo;
197 this.docComments = newDocCommentTable(keepDocComments, fac);
198 this.keepLineMap = keepLineMap;
199 this.errorTree = F.Erroneous();
200 this.endPosTable = newEndPosTable(keepEndPositions);
201 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
202 this.allowRecords = Feature.RECORDS.allowedInSource(source);
203 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
204 updateUnexpectedTopLevelDefinitionStartError(false);
205 }
206
207 /** Construct a parser from an existing parser, with minimal overhead.
208 */
209 @SuppressWarnings("this-escape")
210 protected JavacParser(JavacParser parser,
211 Lexer S) {
212 this.S = S;
213 this.token = parser.token;
214 this.F = parser.F;
215 this.log = parser.log;
216 this.names = parser.names;
217 this.source = parser.source;
218 this.preview = parser.preview;
219 this.deferredLintHandler = parser.deferredLintHandler;
220 this.allowStringFolding = parser.allowStringFolding;
221 this.keepDocComments = parser.keepDocComments;
222 this.parseModuleInfo = false;
223 this.docComments = parser.docComments;
224 this.errorTree = F.Erroneous();
225 this.endPosTable = newEndPosTable(false);
226 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
227 this.allowRecords = Feature.RECORDS.allowedInSource(source);
228 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
229 updateUnexpectedTopLevelDefinitionStartError(false);
230 }
231
232 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
233 return keepEndPositions
234 ? new SimpleEndPosTable(this)
235 : new EmptyEndPosTable(this);
236 }
237
238 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
239 return keepDocComments ? new LazyDocCommentTable(fac) : null;
240 }
241
242 /** Switch: should we fold strings?
243 */
244 boolean allowStringFolding;
245
246 /** Switch: should we keep docComments?
247 */
248 boolean keepDocComments;
249
250 /** Switch: should we keep line table?
251 */
252 boolean keepLineMap;
253
254 /** Switch: is "this" allowed as an identifier?
255 * This is needed to parse receiver types.
256 */
257 boolean allowThisIdent;
258
259 /** Switch: is yield statement allowed in this source level?
260 */
261 boolean allowYieldStatement;
262
263 /** Switch: are records allowed in this source level?
264 */
265 boolean allowRecords;
266
267 /** Switch: are sealed types allowed in this source level?
268 */
269 boolean allowSealedTypes;
270
271 /** The type of the method receiver, as specified by a first "this" parameter.
272 */
273 JCVariableDecl receiverParam;
274
275 /** When terms are parsed, the mode determines which is expected:
276 * mode = EXPR : an expression
277 * mode = TYPE : a type
278 * mode = NOPARAMS : no parameters allowed for type
279 * mode = TYPEARG : type argument
280 * mode |= NOLAMBDA : lambdas are not allowed
281 */
282 protected static final int EXPR = 1 << 0;
283 protected static final int TYPE = 1 << 1;
284 protected static final int NOPARAMS = 1 << 2;
285 protected static final int TYPEARG = 1 << 3;
286 protected static final int DIAMOND = 1 << 4;
1645 token.kind == MONKEYS_AT) {
1646 //error recovery, case like:
1647 //int i = expr.<missing-ident>
1648 //@Deprecated
1649 if (typeArgs != null) illegal();
1650 return toP(t);
1651 }
1652 if (tyannos != null && tyannos.nonEmpty()) {
1653 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1654 }
1655 break;
1656 case ELLIPSIS:
1657 if (this.permitTypeAnnotationsPushBack) {
1658 this.typeAnnotationsPushedBack = annos;
1659 } else if (annos.nonEmpty()) {
1660 // Don't return here -- error recovery attempt
1661 illegal(annos.head.pos);
1662 }
1663 break loop;
1664 case LT:
1665 if (!isMode(TYPE) && isUnboundMemberRef()) {
1666 //this is an unbound method reference whose qualifier
1667 //is a generic type i.e. A<S>::m
1668 int pos1 = token.pos;
1669 accept(LT);
1670 ListBuffer<JCExpression> args = new ListBuffer<>();
1671 args.append(typeArgument());
1672 while (token.kind == COMMA) {
1673 nextToken();
1674 args.append(typeArgument());
1675 }
1676 accept(GT);
1677 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1678 while (token.kind == DOT) {
1679 nextToken();
1680 selectTypeMode();
1681 t = toP(F.at(token.pos).Select(t, ident()));
1682 t = typeArgumentsOpt(t);
1683 }
1684 t = bracketsOpt(t);
1685 if (token.kind != COLCOL) {
1686 //method reference expected here
1888 return illegal(annos.head.pos);
1889 }
1890 break;
1891 }
1892 }
1893 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1894 selectExprMode();
1895 t = to(F.at(token.pos).Unary(
1896 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1897 nextToken();
1898 }
1899 return toP(t);
1900 }
1901
1902 /**
1903 * If we see an identifier followed by a '<' it could be an unbound
1904 * method reference or a binary expression. To disambiguate, look for a
1905 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1906 */
1907 @SuppressWarnings("fallthrough")
1908 boolean isUnboundMemberRef() {
1909 int pos = 0, depth = 0;
1910 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1911 switch (t.kind) {
1912 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1913 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1914 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1915 case DOUBLE: case BOOLEAN: case CHAR:
1916 case MONKEYS_AT:
1917 break;
1918
1919 case LPAREN:
1920 // skip annotation values
1921 int nesting = 0;
1922 for (; ; pos++) {
1923 TokenKind tk2 = S.token(pos).kind;
1924 switch (tk2) {
1925 case EOF:
1926 return false;
1927 case LPAREN:
1928 nesting++;
2983 accept(SEMI);
2984 return List.of(toP(F.at(pos).Yield(t)));
2985 }
2986
2987 //else intentional fall-through
2988 } else {
2989 if (isNonSealedClassStart(true)) {
2990 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2991 nextToken();
2992 nextToken();
2993 nextToken();
2994 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2995 } else if (isSealedClassStart(true)) {
2996 checkSourceLevel(Feature.SEALED_CLASSES);
2997 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2998 nextToken();
2999 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3000 }
3001 }
3002 }
3003 dc = token.docComment();
3004 if (isRecordStart() && allowRecords) {
3005 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3006 } else {
3007 Token prevToken = token;
3008 JCExpression t = term(EXPR | TYPE);
3009 if (token.kind == COLON && t.hasTag(IDENT)) {
3010 nextToken();
3011 JCStatement stat = parseStatementAsBlock();
3012 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3013 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3014 pos = token.pos;
3015 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3016 F.at(pos);
3017 return localVariableDeclarations(mods, t, dc);
3018 } else {
3019 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3020 t = checkExprStat(t);
3021 accept(SEMI);
3022 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3588 case ABSTRACT : flag = Flags.ABSTRACT; break;
3589 case NATIVE : flag = Flags.NATIVE; break;
3590 case VOLATILE : flag = Flags.VOLATILE; break;
3591 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3592 case STRICTFP : flag = Flags.STRICTFP; break;
3593 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3594 case DEFAULT : flag = Flags.DEFAULT; break;
3595 case ERROR : flag = 0; nextToken(); break;
3596 case IDENTIFIER : {
3597 if (isNonSealedClassStart(false)) {
3598 flag = Flags.NON_SEALED;
3599 nextToken();
3600 nextToken();
3601 break;
3602 }
3603 if (isSealedClassStart(false)) {
3604 checkSourceLevel(Feature.SEALED_CLASSES);
3605 flag = Flags.SEALED;
3606 break;
3607 }
3608 break loop;
3609 }
3610 default: break loop;
3611 }
3612 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3613 lastPos = token.pos;
3614 nextToken();
3615 if (flag == Flags.ANNOTATION) {
3616 if (token.kind != INTERFACE) {
3617 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3618 // if first modifier is an annotation, set pos to annotation's.
3619 if (flags == 0 && annotations.isEmpty())
3620 pos = ann.pos;
3621 annotations.append(ann);
3622 flag = 0;
3623 }
3624 }
3625 flags |= flag;
3626 }
3627 switch (token.kind) {
3856 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3857 return Source.JDK10;
3858 } else if (shouldWarn) {
3859 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3860 }
3861 }
3862 if (name == names.yield) {
3863 if (allowYieldStatement) {
3864 return Source.JDK14;
3865 } else if (shouldWarn) {
3866 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3867 }
3868 }
3869 if (name == names.record) {
3870 if (allowRecords) {
3871 return Source.JDK14;
3872 } else if (shouldWarn) {
3873 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3874 }
3875 }
3876 if (name == names.sealed) {
3877 if (allowSealedTypes) {
3878 return Source.JDK15;
3879 } else if (shouldWarn) {
3880 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3881 }
3882 }
3883 if (name == names.permits) {
3884 if (allowSealedTypes) {
3885 return Source.JDK15;
3886 } else if (shouldWarn) {
3887 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3888 }
3889 }
3890 return null;
3891 }
3892
3893 /** VariableDeclaratorId = Ident BracketsOpt
3894 */
3895 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4977 Token next = S.token(3);
4978 return allowedAfterSealedOrNonSealed(next, local, true);
4979 }
4980 return false;
4981 }
4982
4983 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4984 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4985 Token tokenSub = S.token(lookAheadOffset + 1);
4986 Token tokenSealed = S.token(lookAheadOffset + 2);
4987 if (someToken.endPos == tokenSub.pos &&
4988 tokenSub.endPos == tokenSealed.pos &&
4989 tokenSealed.name() == names.sealed) {
4990 checkSourceLevel(Feature.SEALED_CLASSES);
4991 return true;
4992 }
4993 }
4994 return false;
4995 }
4996
4997 protected boolean isSealedClassStart(boolean local) {
4998 if (token.name() == names.sealed) {
4999 Token next = S.token(1);
5000 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5001 checkSourceLevel(Feature.SEALED_CLASSES);
5002 return true;
5003 }
5004 }
5005 return false;
5006 }
5007
5008 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5009 return local ?
5010 switch (next.kind) {
5011 case MONKEYS_AT -> {
5012 Token afterNext = S.token(2);
5013 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5014 }
5015 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5016 default -> false;
5017 } :
5018 switch (next.kind) {
5019 case MONKEYS_AT -> {
5020 Token afterNext = S.token(2);
5021 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5022 }
5023 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5024 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
5025 default -> false;
5026 };
5027 }
5028
5029 /** MethodDeclaratorRest =
5030 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5031 * VoidMethodDeclaratorRest =
5032 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5033 * ConstructorDeclaratorRest =
5034 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5035 */
5036 protected JCTree methodDeclaratorRest(int pos,
5037 JCModifiers mods,
5038 JCExpression type,
5039 Name name,
5040 List<JCTypeParameter> typarams,
5041 boolean isInterface, boolean isVoid,
5042 boolean isRecord,
5043 Comment dc) {
5044 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.LintWarnings;
48 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
49 import com.sun.tools.javac.tree.*;
50 import com.sun.tools.javac.tree.JCTree.*;
51 import com.sun.tools.javac.util.*;
52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
53 import com.sun.tools.javac.util.JCDiagnostic.Error;
54 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
55 import com.sun.tools.javac.util.List;
56
57 import static com.sun.tools.javac.code.Flags.asFlagSet;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
62 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
63 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
64 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
65 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
66 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
67 import com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
68 import static com.sun.tools.javac.tree.JCTree.Tag.*;
69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
70 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
71 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
72 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
73
74 /**
75 * The parser maps a token sequence into an abstract syntax tree.
76 * The parser is a hand-written recursive-descent parser that
77 * implements the grammar described in the Java Language Specification.
78 * For efficiency reasons, an operator precedence scheme is used
79 * for parsing binary operation expressions.
80 *
81 * <p><b>This is NOT part of any supported API.
82 * If you write code that depends on this, you do so at your own risk.
83 * This code and its internal interfaces are subject to change or
84 * deletion without notice.</b>
85 */
86 public class JavacParser implements Parser {
188 boolean keepEndPositions,
189 boolean parseModuleInfo) {
190 this.S = S;
191 nextToken(); // prime the pump
192 this.F = fac.F;
193 this.log = fac.log;
194 this.names = fac.names;
195 this.source = fac.source;
196 this.preview = fac.preview;
197 this.deferredLintHandler = fac.deferredLintHandler;
198 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
199 this.keepDocComments = keepDocComments;
200 this.parseModuleInfo = parseModuleInfo;
201 this.docComments = newDocCommentTable(keepDocComments, fac);
202 this.keepLineMap = keepLineMap;
203 this.errorTree = F.Erroneous();
204 this.endPosTable = newEndPosTable(keepEndPositions);
205 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
206 this.allowRecords = Feature.RECORDS.allowedInSource(source);
207 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
208 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
209 Feature.VALUE_CLASSES.allowedInSource(source);
210 updateUnexpectedTopLevelDefinitionStartError(false);
211 }
212
213 /** Construct a parser from an existing parser, with minimal overhead.
214 */
215 @SuppressWarnings("this-escape")
216 protected JavacParser(JavacParser parser,
217 Lexer S) {
218 this.S = S;
219 this.token = parser.token;
220 this.F = parser.F;
221 this.log = parser.log;
222 this.names = parser.names;
223 this.source = parser.source;
224 this.preview = parser.preview;
225 this.deferredLintHandler = parser.deferredLintHandler;
226 this.allowStringFolding = parser.allowStringFolding;
227 this.keepDocComments = parser.keepDocComments;
228 this.parseModuleInfo = false;
229 this.docComments = parser.docComments;
230 this.errorTree = F.Erroneous();
231 this.endPosTable = newEndPosTable(false);
232 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
233 this.allowRecords = Feature.RECORDS.allowedInSource(source);
234 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
235 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
236 Feature.VALUE_CLASSES.allowedInSource(source);
237 updateUnexpectedTopLevelDefinitionStartError(false);
238 }
239
240 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
241 return keepEndPositions
242 ? new SimpleEndPosTable(this)
243 : new EmptyEndPosTable(this);
244 }
245
246 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
247 return keepDocComments ? new LazyDocCommentTable(fac) : null;
248 }
249
250 /** Switch: should we fold strings?
251 */
252 boolean allowStringFolding;
253
254 /** Switch: should we keep docComments?
255 */
256 boolean keepDocComments;
257
258 /** Switch: should we keep line table?
259 */
260 boolean keepLineMap;
261
262 /** Switch: is "this" allowed as an identifier?
263 * This is needed to parse receiver types.
264 */
265 boolean allowThisIdent;
266
267 /** Switch: is yield statement allowed in this source level?
268 */
269 boolean allowYieldStatement;
270
271 /** Switch: are records allowed in this source level?
272 */
273 boolean allowRecords;
274
275 /** Switch: are value classes allowed in this source level?
276 */
277 boolean allowValueClasses;
278
279 /** Switch: are sealed types allowed in this source level?
280 */
281 boolean allowSealedTypes;
282
283 /** The type of the method receiver, as specified by a first "this" parameter.
284 */
285 JCVariableDecl receiverParam;
286
287 /** When terms are parsed, the mode determines which is expected:
288 * mode = EXPR : an expression
289 * mode = TYPE : a type
290 * mode = NOPARAMS : no parameters allowed for type
291 * mode = TYPEARG : type argument
292 * mode |= NOLAMBDA : lambdas are not allowed
293 */
294 protected static final int EXPR = 1 << 0;
295 protected static final int TYPE = 1 << 1;
296 protected static final int NOPARAMS = 1 << 2;
297 protected static final int TYPEARG = 1 << 3;
298 protected static final int DIAMOND = 1 << 4;
1657 token.kind == MONKEYS_AT) {
1658 //error recovery, case like:
1659 //int i = expr.<missing-ident>
1660 //@Deprecated
1661 if (typeArgs != null) illegal();
1662 return toP(t);
1663 }
1664 if (tyannos != null && tyannos.nonEmpty()) {
1665 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1666 }
1667 break;
1668 case ELLIPSIS:
1669 if (this.permitTypeAnnotationsPushBack) {
1670 this.typeAnnotationsPushedBack = annos;
1671 } else if (annos.nonEmpty()) {
1672 // Don't return here -- error recovery attempt
1673 illegal(annos.head.pos);
1674 }
1675 break loop;
1676 case LT:
1677 if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1678 //this is either an unbound method reference whose qualifier
1679 //is a generic type i.e. A<S>::m
1680 int pos1 = token.pos;
1681 accept(LT);
1682 ListBuffer<JCExpression> args = new ListBuffer<>();
1683 args.append(typeArgument());
1684 while (token.kind == COMMA) {
1685 nextToken();
1686 args.append(typeArgument());
1687 }
1688 accept(GT);
1689 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1690 while (token.kind == DOT) {
1691 nextToken();
1692 selectTypeMode();
1693 t = toP(F.at(token.pos).Select(t, ident()));
1694 t = typeArgumentsOpt(t);
1695 }
1696 t = bracketsOpt(t);
1697 if (token.kind != COLCOL) {
1698 //method reference expected here
1900 return illegal(annos.head.pos);
1901 }
1902 break;
1903 }
1904 }
1905 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1906 selectExprMode();
1907 t = to(F.at(token.pos).Unary(
1908 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1909 nextToken();
1910 }
1911 return toP(t);
1912 }
1913
1914 /**
1915 * If we see an identifier followed by a '<' it could be an unbound
1916 * method reference or a binary expression. To disambiguate, look for a
1917 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1918 */
1919 @SuppressWarnings("fallthrough")
1920 boolean isParameterizedTypePrefix() {
1921 int pos = 0, depth = 0;
1922 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1923 switch (t.kind) {
1924 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1925 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1926 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1927 case DOUBLE: case BOOLEAN: case CHAR:
1928 case MONKEYS_AT:
1929 break;
1930
1931 case LPAREN:
1932 // skip annotation values
1933 int nesting = 0;
1934 for (; ; pos++) {
1935 TokenKind tk2 = S.token(pos).kind;
1936 switch (tk2) {
1937 case EOF:
1938 return false;
1939 case LPAREN:
1940 nesting++;
2995 accept(SEMI);
2996 return List.of(toP(F.at(pos).Yield(t)));
2997 }
2998
2999 //else intentional fall-through
3000 } else {
3001 if (isNonSealedClassStart(true)) {
3002 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3003 nextToken();
3004 nextToken();
3005 nextToken();
3006 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3007 } else if (isSealedClassStart(true)) {
3008 checkSourceLevel(Feature.SEALED_CLASSES);
3009 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3010 nextToken();
3011 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3012 }
3013 }
3014 }
3015 if ((isValueModifier()) && allowValueClasses) {
3016 checkSourceLevel(Feature.VALUE_CLASSES);
3017 dc = token.docComment();
3018 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
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));
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 if (isValueModifier()) {
3626 checkSourceLevel(Feature.VALUE_CLASSES);
3627 flag = Flags.VALUE_CLASS;
3628 break;
3629 }
3630 break loop;
3631 }
3632 default: break loop;
3633 }
3634 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3635 lastPos = token.pos;
3636 nextToken();
3637 if (flag == Flags.ANNOTATION) {
3638 if (token.kind != INTERFACE) {
3639 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3640 // if first modifier is an annotation, set pos to annotation's.
3641 if (flags == 0 && annotations.isEmpty())
3642 pos = ann.pos;
3643 annotations.append(ann);
3644 flag = 0;
3645 }
3646 }
3647 flags |= flag;
3648 }
3649 switch (token.kind) {
3878 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3879 return Source.JDK10;
3880 } else if (shouldWarn) {
3881 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3882 }
3883 }
3884 if (name == names.yield) {
3885 if (allowYieldStatement) {
3886 return Source.JDK14;
3887 } else if (shouldWarn) {
3888 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3889 }
3890 }
3891 if (name == names.record) {
3892 if (allowRecords) {
3893 return Source.JDK14;
3894 } else if (shouldWarn) {
3895 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3896 }
3897 }
3898 if (name == names.value) {
3899 if (allowValueClasses) {
3900 return Source.JDK23;
3901 } else if (shouldWarn) {
3902 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3903 }
3904 }
3905 if (name == names.sealed) {
3906 if (allowSealedTypes) {
3907 return Source.JDK15;
3908 } else if (shouldWarn) {
3909 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3910 }
3911 }
3912 if (name == names.permits) {
3913 if (allowSealedTypes) {
3914 return Source.JDK15;
3915 } else if (shouldWarn) {
3916 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3917 }
3918 }
3919 return null;
3920 }
3921
3922 /** VariableDeclaratorId = Ident BracketsOpt
3923 */
3924 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
5006 Token next = S.token(3);
5007 return allowedAfterSealedOrNonSealed(next, local, true);
5008 }
5009 return false;
5010 }
5011
5012 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
5013 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
5014 Token tokenSub = S.token(lookAheadOffset + 1);
5015 Token tokenSealed = S.token(lookAheadOffset + 2);
5016 if (someToken.endPos == tokenSub.pos &&
5017 tokenSub.endPos == tokenSealed.pos &&
5018 tokenSealed.name() == names.sealed) {
5019 checkSourceLevel(Feature.SEALED_CLASSES);
5020 return true;
5021 }
5022 }
5023 return false;
5024 }
5025
5026 protected boolean isValueModifier() {
5027 if (token.kind == IDENTIFIER && token.name() == names.value) {
5028 boolean isValueModifier = false;
5029 Token next = S.token(1);
5030 switch (next.kind) {
5031 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
5032 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
5033 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
5034 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
5035 case CLASS: case INTERFACE: case ENUM:
5036 isValueModifier = true;
5037 break;
5038 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
5039 if (next.name() == names.record || next.name() == names.value
5040 || (mode & EXPR) != 0)
5041 isValueModifier = true;
5042 break;
5043 }
5044 if (isValueModifier) {
5045 checkSourceLevel(Feature.VALUE_CLASSES);
5046 return true;
5047 }
5048 }
5049 return false;
5050 }
5051
5052 protected boolean isSealedClassStart(boolean local) {
5053 if (token.name() == names.sealed) {
5054 Token next = S.token(1);
5055 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5056 checkSourceLevel(Feature.SEALED_CLASSES);
5057 return true;
5058 }
5059 }
5060 return false;
5061 }
5062
5063 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5064 return local ?
5065 switch (next.kind) {
5066 case MONKEYS_AT -> {
5067 Token afterNext = S.token(2);
5068 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5069 }
5070 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5071 default -> false;
5072 } :
5073 switch (next.kind) {
5074 case MONKEYS_AT -> {
5075 Token afterNext = S.token(2);
5076 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5077 }
5078 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5079 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5080 next.name() == names.sealed ||
5081 allowValueClasses && next.name() == names.value;
5082 default -> false;
5083 };
5084 }
5085
5086 /** MethodDeclaratorRest =
5087 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5088 * VoidMethodDeclaratorRest =
5089 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5090 * ConstructorDeclaratorRest =
5091 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5092 */
5093 protected JCTree methodDeclaratorRest(int pos,
5094 JCModifiers mods,
5095 JCExpression type,
5096 Name name,
5097 List<JCTypeParameter> typarams,
5098 boolean isInterface, boolean isVoid,
5099 boolean isRecord,
5100 Comment dc) {
5101 if (isInterface) {
|