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 {
177 Lexer S,
178 boolean keepDocComments,
179 boolean keepLineMap,
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.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
195 this.allowRecords = Feature.RECORDS.allowedInSource(source);
196 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
197 updateUnexpectedTopLevelDefinitionStartError(false);
198 }
199
200 /** Construct a parser from an existing parser, with minimal overhead.
201 */
202 @SuppressWarnings("this-escape")
203 protected JavacParser(JavacParser parser,
204 Lexer S) {
205 this.S = S;
206 this.token = parser.token;
207 this.F = parser.F;
208 this.log = parser.log;
209 this.names = parser.names;
210 this.source = parser.source;
211 this.preview = parser.preview;
212 this.allowStringFolding = parser.allowStringFolding;
213 this.keepDocComments = parser.keepDocComments;
214 this.parseModuleInfo = false;
215 this.docComments = parser.docComments;
216 this.errorTree = F.Erroneous();
217 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
218 this.allowRecords = Feature.RECORDS.allowedInSource(source);
219 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
220 updateUnexpectedTopLevelDefinitionStartError(false);
221 }
222
223 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
224 return keepDocComments ? new LazyDocCommentTable(fac) : null;
225 }
226
227 /** Switch: should we fold strings?
228 */
229 boolean allowStringFolding;
230
231 /** Switch: should we keep docComments?
232 */
233 boolean keepDocComments;
234
235 /** Switch: should we keep line table?
236 */
237 boolean keepLineMap;
238
239 /** Switch: is "this" allowed as an identifier?
240 * This is needed to parse receiver types.
241 */
242 boolean allowThisIdent;
243
244 /** Switch: is yield statement allowed in this source level?
245 */
246 boolean allowYieldStatement;
247
248 /** Switch: are records allowed in this source level?
249 */
250 boolean allowRecords;
251
252 /** Switch: are sealed types allowed in this source level?
253 */
254 boolean allowSealedTypes;
255
256 /** The type of the method receiver, as specified by a first "this" parameter.
257 */
258 JCVariableDecl receiverParam;
259
260 /** When terms are parsed, the mode determines which is expected:
261 * mode = EXPR : an expression
262 * mode = TYPE : a type
263 * mode = NOLAMBDA : lambdas are not allowed
264 */
265 protected static final int EXPR = 1 << 0;
266 protected static final int TYPE = 1 << 1;
267 protected static final int NOLAMBDA = 1 << 2;
268
269 protected void setMode(int mode) {
270 this.mode = mode;
271 }
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 = typeApplyOpt(t);
1683 }
1684 t = bracketsOpt(t);
1685 if (token.kind != COLCOL) {
1686 //method reference expected here
1891 return illegal(annos.head.pos);
1892 }
1893 break;
1894 }
1895 }
1896 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1897 selectExprMode();
1898 t = to(F.at(token.pos).Unary(
1899 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1900 nextToken();
1901 }
1902 return toP(t);
1903 }
1904
1905 /**
1906 * If we see an identifier followed by a '<' it could be an unbound
1907 * method reference or a binary expression. To disambiguate, look for a
1908 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1909 */
1910 @SuppressWarnings("fallthrough")
1911 boolean isUnboundMemberRef() {
1912 int pos = 0, depth = 0;
1913 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1914 switch (t.kind) {
1915 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1916 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1917 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1918 case DOUBLE: case BOOLEAN: case CHAR:
1919 case MONKEYS_AT:
1920 break;
1921
1922 case LPAREN:
1923 // skip annotation values
1924 int nesting = 0;
1925 for (; ; pos++) {
1926 TokenKind tk2 = S.token(pos).kind;
1927 switch (tk2) {
1928 case EOF:
1929 return false;
1930 case LPAREN:
1931 nesting++;
2986 accept(SEMI);
2987 return List.of(toP(F.at(pos).Yield(t)));
2988 }
2989
2990 //else intentional fall-through
2991 } else {
2992 if (isNonSealedClassStart(true)) {
2993 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2994 nextToken();
2995 nextToken();
2996 nextToken();
2997 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2998 } else if (isSealedClassStart(true)) {
2999 checkSourceLevel(Feature.SEALED_CLASSES);
3000 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3001 nextToken();
3002 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3003 }
3004 }
3005 }
3006 dc = token.docComment();
3007 if (isRecordStart() && allowRecords) {
3008 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3009 } else {
3010 Token prevToken = token;
3011 JCExpression t = term(EXPR | TYPE);
3012 if (token.kind == COLON && t.hasTag(IDENT)) {
3013 nextToken();
3014 JCStatement stat = parseStatementAsBlock();
3015 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3016 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3017 pos = token.pos;
3018 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3019 F.at(pos);
3020 return localVariableDeclarations(mods, t, dc);
3021 } else {
3022 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3023 t = checkExprStat(t);
3024 accept(SEMI);
3025 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3599 case ABSTRACT : flag = Flags.ABSTRACT; break;
3600 case NATIVE : flag = Flags.NATIVE; break;
3601 case VOLATILE : flag = Flags.VOLATILE; break;
3602 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3603 case STRICTFP : flag = Flags.STRICTFP; break;
3604 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3605 case DEFAULT : flag = Flags.DEFAULT; break;
3606 case ERROR : flag = 0; nextToken(); break;
3607 case IDENTIFIER : {
3608 if (isNonSealedClassStart(false)) {
3609 flag = Flags.NON_SEALED;
3610 nextToken();
3611 nextToken();
3612 break;
3613 }
3614 if (isSealedClassStart(false)) {
3615 checkSourceLevel(Feature.SEALED_CLASSES);
3616 flag = Flags.SEALED;
3617 break;
3618 }
3619 break loop;
3620 }
3621 default: break loop;
3622 }
3623 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3624 lastPos = token.pos;
3625 nextToken();
3626 if (flag == Flags.ANNOTATION) {
3627 if (token.kind != INTERFACE) {
3628 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3629 // if first modifier is an annotation, set pos to annotation's.
3630 if (flags == 0 && annotations.isEmpty())
3631 pos = ann.pos;
3632 annotations.append(ann);
3633 flag = 0;
3634 }
3635 }
3636 flags |= flag;
3637 }
3638 switch (token.kind) {
3866 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3867 return Source.JDK10;
3868 } else if (shouldWarn) {
3869 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3870 }
3871 }
3872 if (name == names.yield) {
3873 if (allowYieldStatement) {
3874 return Source.JDK14;
3875 } else if (shouldWarn) {
3876 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3877 }
3878 }
3879 if (name == names.record) {
3880 if (allowRecords) {
3881 return Source.JDK14;
3882 } else if (shouldWarn) {
3883 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3884 }
3885 }
3886 if (name == names.sealed) {
3887 if (allowSealedTypes) {
3888 return Source.JDK15;
3889 } else if (shouldWarn) {
3890 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3891 }
3892 }
3893 if (name == names.permits) {
3894 if (allowSealedTypes) {
3895 return Source.JDK15;
3896 } else if (shouldWarn) {
3897 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3898 }
3899 }
3900 return null;
3901 }
3902
3903 /** VariableDeclaratorId = Ident BracketsOpt
3904 */
3905 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4986 Token next = S.token(3);
4987 return allowedAfterSealedOrNonSealed(next, local, true);
4988 }
4989 return false;
4990 }
4991
4992 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4993 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4994 Token tokenSub = S.token(lookAheadOffset + 1);
4995 Token tokenSealed = S.token(lookAheadOffset + 2);
4996 if (someToken.endPos == tokenSub.pos &&
4997 tokenSub.endPos == tokenSealed.pos &&
4998 tokenSealed.name() == names.sealed) {
4999 checkSourceLevel(Feature.SEALED_CLASSES);
5000 return true;
5001 }
5002 }
5003 return false;
5004 }
5005
5006 protected boolean isSealedClassStart(boolean local) {
5007 if (token.name() == names.sealed) {
5008 Token next = S.token(1);
5009 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5010 checkSourceLevel(Feature.SEALED_CLASSES);
5011 return true;
5012 }
5013 }
5014 return false;
5015 }
5016
5017 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5018 return local ?
5019 switch (next.kind) {
5020 case MONKEYS_AT -> {
5021 Token afterNext = S.token(2);
5022 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5023 }
5024 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5025 default -> false;
5026 } :
5027 switch (next.kind) {
5028 case MONKEYS_AT -> {
5029 Token afterNext = S.token(2);
5030 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5031 }
5032 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5033 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
5034 default -> false;
5035 };
5036 }
5037
5038 /** MethodDeclaratorRest =
5039 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5040 * VoidMethodDeclaratorRest =
5041 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5042 * ConstructorDeclaratorRest =
5043 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5044 */
5045 protected JCTree methodDeclaratorRest(int pos,
5046 JCModifiers mods,
5047 JCExpression type,
5048 Name name,
5049 List<JCTypeParameter> typarams,
5050 boolean isInterface, boolean isVoid,
5051 boolean isRecord,
5052 Comment dc) {
5053 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 {
181 Lexer S,
182 boolean keepDocComments,
183 boolean keepLineMap,
184 boolean parseModuleInfo) {
185 this.S = S;
186 nextToken(); // prime the pump
187 this.F = fac.F;
188 this.log = fac.log;
189 this.names = fac.names;
190 this.source = fac.source;
191 this.preview = fac.preview;
192 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
193 this.keepDocComments = keepDocComments;
194 this.parseModuleInfo = parseModuleInfo;
195 this.docComments = newDocCommentTable(keepDocComments, fac);
196 this.keepLineMap = keepLineMap;
197 this.errorTree = F.Erroneous();
198 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
199 this.allowRecords = Feature.RECORDS.allowedInSource(source);
200 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
201 this.allowValueClasses = preview.isEnabled() && Feature.VALUE_CLASSES.allowedInSource(source);
202 updateUnexpectedTopLevelDefinitionStartError(false);
203 }
204
205 /** Construct a parser from an existing parser, with minimal overhead.
206 */
207 @SuppressWarnings("this-escape")
208 protected JavacParser(JavacParser parser,
209 Lexer S) {
210 this.S = S;
211 this.token = parser.token;
212 this.F = parser.F;
213 this.log = parser.log;
214 this.names = parser.names;
215 this.source = parser.source;
216 this.preview = parser.preview;
217 this.allowStringFolding = parser.allowStringFolding;
218 this.keepDocComments = parser.keepDocComments;
219 this.parseModuleInfo = false;
220 this.docComments = parser.docComments;
221 this.errorTree = F.Erroneous();
222 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
223 this.allowRecords = Feature.RECORDS.allowedInSource(source);
224 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
225 this.allowValueClasses = preview.isEnabled() && Feature.VALUE_CLASSES.allowedInSource(source);
226 updateUnexpectedTopLevelDefinitionStartError(false);
227 }
228
229 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
230 return keepDocComments ? new LazyDocCommentTable(fac) : null;
231 }
232
233 /** Switch: should we fold strings?
234 */
235 boolean allowStringFolding;
236
237 /** Switch: should we keep docComments?
238 */
239 boolean keepDocComments;
240
241 /** Switch: should we keep line table?
242 */
243 boolean keepLineMap;
244
245 /** Switch: is "this" allowed as an identifier?
246 * This is needed to parse receiver types.
247 */
248 boolean allowThisIdent;
249
250 /** Switch: is yield statement allowed in this source level?
251 */
252 boolean allowYieldStatement;
253
254 /** Switch: are records allowed in this source level?
255 */
256 boolean allowRecords;
257
258 /** Switch: are value classes allowed in this source level?
259 */
260 boolean allowValueClasses;
261
262 /** Switch: are sealed types allowed in this source level?
263 */
264 boolean allowSealedTypes;
265
266 /** The type of the method receiver, as specified by a first "this" parameter.
267 */
268 JCVariableDecl receiverParam;
269
270 /** When terms are parsed, the mode determines which is expected:
271 * mode = EXPR : an expression
272 * mode = TYPE : a type
273 * mode = NOLAMBDA : lambdas are not allowed
274 */
275 protected static final int EXPR = 1 << 0;
276 protected static final int TYPE = 1 << 1;
277 protected static final int NOLAMBDA = 1 << 2;
278
279 protected void setMode(int mode) {
280 this.mode = mode;
281 }
1655 token.kind == MONKEYS_AT) {
1656 //error recovery, case like:
1657 //int i = expr.<missing-ident>
1658 //@Deprecated
1659 if (typeArgs != null) illegal();
1660 return toP(t);
1661 }
1662 if (tyannos != null && tyannos.nonEmpty()) {
1663 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1664 }
1665 break;
1666 case ELLIPSIS:
1667 if (this.permitTypeAnnotationsPushBack) {
1668 this.typeAnnotationsPushedBack = annos;
1669 } else if (annos.nonEmpty()) {
1670 // Don't return here -- error recovery attempt
1671 illegal(annos.head.pos);
1672 }
1673 break loop;
1674 case LT:
1675 if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1676 //this is either an unbound method reference whose qualifier
1677 //is a generic type i.e. A<S>::m
1678 int pos1 = token.pos;
1679 accept(LT);
1680 ListBuffer<JCExpression> args = new ListBuffer<>();
1681 args.append(typeArgument());
1682 while (token.kind == COMMA) {
1683 nextToken();
1684 args.append(typeArgument());
1685 }
1686 accept(GT);
1687 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1688 while (token.kind == DOT) {
1689 nextToken();
1690 selectTypeMode();
1691 t = toP(F.at(token.pos).Select(t, ident()));
1692 t = typeApplyOpt(t);
1693 }
1694 t = bracketsOpt(t);
1695 if (token.kind != COLCOL) {
1696 //method reference expected here
1901 return illegal(annos.head.pos);
1902 }
1903 break;
1904 }
1905 }
1906 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1907 selectExprMode();
1908 t = to(F.at(token.pos).Unary(
1909 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1910 nextToken();
1911 }
1912 return toP(t);
1913 }
1914
1915 /**
1916 * If we see an identifier followed by a '<' it could be an unbound
1917 * method reference or a binary expression. To disambiguate, look for a
1918 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1919 */
1920 @SuppressWarnings("fallthrough")
1921 boolean isParameterizedTypePrefix() {
1922 int pos = 0, depth = 0;
1923 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1924 switch (t.kind) {
1925 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1926 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1927 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1928 case DOUBLE: case BOOLEAN: case CHAR:
1929 case MONKEYS_AT:
1930 break;
1931
1932 case LPAREN:
1933 // skip annotation values
1934 int nesting = 0;
1935 for (; ; pos++) {
1936 TokenKind tk2 = S.token(pos).kind;
1937 switch (tk2) {
1938 case EOF:
1939 return false;
1940 case LPAREN:
1941 nesting++;
2996 accept(SEMI);
2997 return List.of(toP(F.at(pos).Yield(t)));
2998 }
2999
3000 //else intentional fall-through
3001 } else {
3002 if (isNonSealedClassStart(true)) {
3003 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3004 nextToken();
3005 nextToken();
3006 nextToken();
3007 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3008 } else if (isSealedClassStart(true)) {
3009 checkSourceLevel(Feature.SEALED_CLASSES);
3010 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3011 nextToken();
3012 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3013 }
3014 }
3015 }
3016 if ((isValueModifier()) && allowValueClasses) {
3017 checkSourceLevel(Feature.VALUE_CLASSES);
3018 dc = token.docComment();
3019 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
3020 }
3021 dc = token.docComment();
3022 if (isRecordStart() && allowRecords) {
3023 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3024 } else {
3025 Token prevToken = token;
3026 JCExpression t = term(EXPR | TYPE);
3027 if (token.kind == COLON && t.hasTag(IDENT)) {
3028 nextToken();
3029 JCStatement stat = parseStatementAsBlock();
3030 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3031 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3032 pos = token.pos;
3033 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3034 F.at(pos);
3035 return localVariableDeclarations(mods, t, dc);
3036 } else {
3037 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3038 t = checkExprStat(t);
3039 accept(SEMI);
3040 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3614 case ABSTRACT : flag = Flags.ABSTRACT; break;
3615 case NATIVE : flag = Flags.NATIVE; break;
3616 case VOLATILE : flag = Flags.VOLATILE; break;
3617 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3618 case STRICTFP : flag = Flags.STRICTFP; break;
3619 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3620 case DEFAULT : flag = Flags.DEFAULT; break;
3621 case ERROR : flag = 0; nextToken(); break;
3622 case IDENTIFIER : {
3623 if (isNonSealedClassStart(false)) {
3624 flag = Flags.NON_SEALED;
3625 nextToken();
3626 nextToken();
3627 break;
3628 }
3629 if (isSealedClassStart(false)) {
3630 checkSourceLevel(Feature.SEALED_CLASSES);
3631 flag = Flags.SEALED;
3632 break;
3633 }
3634 if (isValueModifier()) {
3635 checkSourceLevel(Feature.VALUE_CLASSES);
3636 flag = Flags.VALUE_CLASS;
3637 break;
3638 }
3639 break loop;
3640 }
3641 default: break loop;
3642 }
3643 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3644 lastPos = token.pos;
3645 nextToken();
3646 if (flag == Flags.ANNOTATION) {
3647 if (token.kind != INTERFACE) {
3648 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3649 // if first modifier is an annotation, set pos to annotation's.
3650 if (flags == 0 && annotations.isEmpty())
3651 pos = ann.pos;
3652 annotations.append(ann);
3653 flag = 0;
3654 }
3655 }
3656 flags |= flag;
3657 }
3658 switch (token.kind) {
3886 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3887 return Source.JDK10;
3888 } else if (shouldWarn) {
3889 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3890 }
3891 }
3892 if (name == names.yield) {
3893 if (allowYieldStatement) {
3894 return Source.JDK14;
3895 } else if (shouldWarn) {
3896 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3897 }
3898 }
3899 if (name == names.record) {
3900 if (allowRecords) {
3901 return Source.JDK14;
3902 } else if (shouldWarn) {
3903 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3904 }
3905 }
3906 if (name == names.value) {
3907 if (allowValueClasses) {
3908 return Source.JDK23;
3909 } else if (shouldWarn) {
3910 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3911 }
3912 }
3913 if (name == names.sealed) {
3914 if (allowSealedTypes) {
3915 return Source.JDK15;
3916 } else if (shouldWarn) {
3917 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3918 }
3919 }
3920 if (name == names.permits) {
3921 if (allowSealedTypes) {
3922 return Source.JDK15;
3923 } else if (shouldWarn) {
3924 log.warning(DiagnosticFlag.SYNTAX, pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3925 }
3926 }
3927 return null;
3928 }
3929
3930 /** VariableDeclaratorId = Ident BracketsOpt
3931 */
3932 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
5013 Token next = S.token(3);
5014 return allowedAfterSealedOrNonSealed(next, local, true);
5015 }
5016 return false;
5017 }
5018
5019 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
5020 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
5021 Token tokenSub = S.token(lookAheadOffset + 1);
5022 Token tokenSealed = S.token(lookAheadOffset + 2);
5023 if (someToken.endPos == tokenSub.pos &&
5024 tokenSub.endPos == tokenSealed.pos &&
5025 tokenSealed.name() == names.sealed) {
5026 checkSourceLevel(Feature.SEALED_CLASSES);
5027 return true;
5028 }
5029 }
5030 return false;
5031 }
5032
5033 protected boolean isValueModifier() {
5034 if (token.kind == IDENTIFIER && token.name() == names.value) {
5035 boolean isValueModifier = false;
5036 Token next = S.token(1);
5037 switch (next.kind) {
5038 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
5039 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
5040 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
5041 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
5042 case CLASS: case INTERFACE: case ENUM:
5043 isValueModifier = true;
5044 break;
5045 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
5046 if (next.name() == names.record || next.name() == names.value
5047 || (mode & EXPR) != 0)
5048 isValueModifier = true;
5049 break;
5050 }
5051 if (isValueModifier) {
5052 checkSourceLevel(Feature.VALUE_CLASSES);
5053 return true;
5054 }
5055 }
5056 return false;
5057 }
5058
5059 protected boolean isSealedClassStart(boolean local) {
5060 if (token.name() == names.sealed) {
5061 Token next = S.token(1);
5062 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5063 checkSourceLevel(Feature.SEALED_CLASSES);
5064 return true;
5065 }
5066 }
5067 return false;
5068 }
5069
5070 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5071 return local ?
5072 switch (next.kind) {
5073 case MONKEYS_AT -> {
5074 Token afterNext = S.token(2);
5075 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5076 }
5077 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5078 default -> false;
5079 } :
5080 switch (next.kind) {
5081 case MONKEYS_AT -> {
5082 Token afterNext = S.token(2);
5083 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5084 }
5085 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5086 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5087 next.name() == names.sealed ||
5088 allowValueClasses && next.name() == names.value;
5089 default -> false;
5090 };
5091 }
5092
5093 /** MethodDeclaratorRest =
5094 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5095 * VoidMethodDeclaratorRest =
5096 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5097 * ConstructorDeclaratorRest =
5098 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5099 */
5100 protected JCTree methodDeclaratorRest(int pos,
5101 JCModifiers mods,
5102 JCExpression type,
5103 Name name,
5104 List<JCTypeParameter> typarams,
5105 boolean isInterface, boolean isVoid,
5106 boolean isRecord,
5107 Comment dc) {
5108 if (isInterface) {
|