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