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 = NOLAMBDA : lambdas are not allowed
275 */
276 protected static final int EXPR = 1 << 0;
277 protected static final int TYPE = 1 << 1;
278 protected static final int NOLAMBDA = 1 << 2;
279
280 protected void setMode(int mode) {
281 this.mode = mode;
282 }
1658 token.kind == MONKEYS_AT) {
1659 //error recovery, case like:
1660 //int i = expr.<missing-ident>
1661 //@Deprecated
1662 if (typeArgs != null) illegal();
1663 return toP(t);
1664 }
1665 if (tyannos != null && tyannos.nonEmpty()) {
1666 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1667 }
1668 break;
1669 case ELLIPSIS:
1670 if (this.permitTypeAnnotationsPushBack) {
1671 this.typeAnnotationsPushedBack = annos;
1672 } else if (annos.nonEmpty()) {
1673 // Don't return here -- error recovery attempt
1674 illegal(annos.head.pos);
1675 }
1676 break loop;
1677 case LT:
1678 if (!isMode(TYPE) && isUnboundMemberRef()) {
1679 //this is an unbound method reference whose qualifier
1680 //is a generic type i.e. A<S>::m
1681 int pos1 = token.pos;
1682 accept(LT);
1683 ListBuffer<JCExpression> args = new ListBuffer<>();
1684 args.append(typeArgument());
1685 while (token.kind == COMMA) {
1686 nextToken();
1687 args.append(typeArgument());
1688 }
1689 accept(GT);
1690 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1691 while (token.kind == DOT) {
1692 nextToken();
1693 selectTypeMode();
1694 t = toP(F.at(token.pos).Select(t, ident()));
1695 t = typeApplyOpt(t);
1696 }
1697 t = bracketsOpt(t);
1698 if (token.kind != COLCOL) {
1699 //method reference expected here
1904 return illegal(annos.head.pos);
1905 }
1906 break;
1907 }
1908 }
1909 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1910 selectExprMode();
1911 t = to(F.at(token.pos).Unary(
1912 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1913 nextToken();
1914 }
1915 return toP(t);
1916 }
1917
1918 /**
1919 * If we see an identifier followed by a '<' it could be an unbound
1920 * method reference or a binary expression. To disambiguate, look for a
1921 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1922 */
1923 @SuppressWarnings("fallthrough")
1924 boolean isUnboundMemberRef() {
1925 int pos = 0, depth = 0;
1926 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1927 switch (t.kind) {
1928 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1929 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1930 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1931 case DOUBLE: case BOOLEAN: case CHAR:
1932 case MONKEYS_AT:
1933 break;
1934
1935 case LPAREN:
1936 // skip annotation values
1937 int nesting = 0;
1938 for (; ; pos++) {
1939 TokenKind tk2 = S.token(pos).kind;
1940 switch (tk2) {
1941 case EOF:
1942 return false;
1943 case LPAREN:
1944 nesting++;
3000 accept(SEMI);
3001 return List.of(toP(F.at(pos).Yield(t)));
3002 }
3003
3004 //else intentional fall-through
3005 } else {
3006 if (isNonSealedClassStart(true)) {
3007 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3008 nextToken();
3009 nextToken();
3010 nextToken();
3011 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3012 } else if (isSealedClassStart(true)) {
3013 checkSourceLevel(Feature.SEALED_CLASSES);
3014 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3015 nextToken();
3016 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3017 }
3018 }
3019 }
3020 dc = token.docComment();
3021 if (isRecordStart() && allowRecords) {
3022 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3023 } else {
3024 Token prevToken = token;
3025 JCExpression t = term(EXPR | TYPE);
3026 if (token.kind == COLON && t.hasTag(IDENT)) {
3027 nextToken();
3028 JCStatement stat = parseStatementAsBlock();
3029 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3030 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3031 pos = token.pos;
3032 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3033 F.at(pos);
3034 return localVariableDeclarations(mods, t, dc);
3035 } else {
3036 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3037 t = checkExprStat(t);
3038 accept(SEMI);
3039 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3605 case ABSTRACT : flag = Flags.ABSTRACT; break;
3606 case NATIVE : flag = Flags.NATIVE; break;
3607 case VOLATILE : flag = Flags.VOLATILE; break;
3608 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3609 case STRICTFP : flag = Flags.STRICTFP; break;
3610 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3611 case DEFAULT : flag = Flags.DEFAULT; break;
3612 case ERROR : flag = 0; nextToken(); break;
3613 case IDENTIFIER : {
3614 if (isNonSealedClassStart(false)) {
3615 flag = Flags.NON_SEALED;
3616 nextToken();
3617 nextToken();
3618 break;
3619 }
3620 if (isSealedClassStart(false)) {
3621 checkSourceLevel(Feature.SEALED_CLASSES);
3622 flag = Flags.SEALED;
3623 break;
3624 }
3625 break loop;
3626 }
3627 default: break loop;
3628 }
3629 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3630 lastPos = token.pos;
3631 nextToken();
3632 if (flag == Flags.ANNOTATION) {
3633 if (token.kind != INTERFACE) {
3634 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3635 // if first modifier is an annotation, set pos to annotation's.
3636 if (flags == 0 && annotations.isEmpty())
3637 pos = ann.pos;
3638 annotations.append(ann);
3639 flag = 0;
3640 }
3641 }
3642 flags |= flag;
3643 }
3644 switch (token.kind) {
3868 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3869 return Source.JDK10;
3870 } else if (shouldWarn) {
3871 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3872 }
3873 }
3874 if (name == names.yield) {
3875 if (allowYieldStatement) {
3876 return Source.JDK14;
3877 } else if (shouldWarn) {
3878 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3879 }
3880 }
3881 if (name == names.record) {
3882 if (allowRecords) {
3883 return Source.JDK14;
3884 } else if (shouldWarn) {
3885 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3886 }
3887 }
3888 if (name == names.sealed) {
3889 if (allowSealedTypes) {
3890 return Source.JDK15;
3891 } else if (shouldWarn) {
3892 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3893 }
3894 }
3895 if (name == names.permits) {
3896 if (allowSealedTypes) {
3897 return Source.JDK15;
3898 } else if (shouldWarn) {
3899 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3900 }
3901 }
3902 return null;
3903 }
3904
3905 /** VariableDeclaratorId = Ident BracketsOpt
3906 */
3907 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4989 Token next = S.token(3);
4990 return allowedAfterSealedOrNonSealed(next, local, true);
4991 }
4992 return false;
4993 }
4994
4995 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4996 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4997 Token tokenSub = S.token(lookAheadOffset + 1);
4998 Token tokenSealed = S.token(lookAheadOffset + 2);
4999 if (someToken.endPos == tokenSub.pos &&
5000 tokenSub.endPos == tokenSealed.pos &&
5001 tokenSealed.name() == names.sealed) {
5002 checkSourceLevel(Feature.SEALED_CLASSES);
5003 return true;
5004 }
5005 }
5006 return false;
5007 }
5008
5009 protected boolean isSealedClassStart(boolean local) {
5010 if (token.name() == names.sealed) {
5011 Token next = S.token(1);
5012 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5013 checkSourceLevel(Feature.SEALED_CLASSES);
5014 return true;
5015 }
5016 }
5017 return false;
5018 }
5019
5020 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5021 return local ?
5022 switch (next.kind) {
5023 case MONKEYS_AT -> {
5024 Token afterNext = S.token(2);
5025 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5026 }
5027 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5028 default -> false;
5029 } :
5030 switch (next.kind) {
5031 case MONKEYS_AT -> {
5032 Token afterNext = S.token(2);
5033 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5034 }
5035 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5036 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
5037 default -> false;
5038 };
5039 }
5040
5041 /** MethodDeclaratorRest =
5042 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5043 * VoidMethodDeclaratorRest =
5044 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5045 * ConstructorDeclaratorRest =
5046 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5047 */
5048 protected JCTree methodDeclaratorRest(int pos,
5049 JCModifiers mods,
5050 JCExpression type,
5051 Name name,
5052 List<JCTypeParameter> typarams,
5053 boolean isInterface, boolean isVoid,
5054 boolean isRecord,
5055 Comment dc) {
5056 if (isInterface) {
|
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 = NOLAMBDA : lambdas are not allowed
287 */
288 protected static final int EXPR = 1 << 0;
289 protected static final int TYPE = 1 << 1;
290 protected static final int NOLAMBDA = 1 << 2;
291
292 protected void setMode(int mode) {
293 this.mode = mode;
294 }
1670 token.kind == MONKEYS_AT) {
1671 //error recovery, case like:
1672 //int i = expr.<missing-ident>
1673 //@Deprecated
1674 if (typeArgs != null) illegal();
1675 return toP(t);
1676 }
1677 if (tyannos != null && tyannos.nonEmpty()) {
1678 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1679 }
1680 break;
1681 case ELLIPSIS:
1682 if (this.permitTypeAnnotationsPushBack) {
1683 this.typeAnnotationsPushedBack = annos;
1684 } else if (annos.nonEmpty()) {
1685 // Don't return here -- error recovery attempt
1686 illegal(annos.head.pos);
1687 }
1688 break loop;
1689 case LT:
1690 if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1691 //this is either an unbound method reference whose qualifier
1692 //is a generic type i.e. A<S>::m
1693 int pos1 = token.pos;
1694 accept(LT);
1695 ListBuffer<JCExpression> args = new ListBuffer<>();
1696 args.append(typeArgument());
1697 while (token.kind == COMMA) {
1698 nextToken();
1699 args.append(typeArgument());
1700 }
1701 accept(GT);
1702 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1703 while (token.kind == DOT) {
1704 nextToken();
1705 selectTypeMode();
1706 t = toP(F.at(token.pos).Select(t, ident()));
1707 t = typeApplyOpt(t);
1708 }
1709 t = bracketsOpt(t);
1710 if (token.kind != COLCOL) {
1711 //method reference expected here
1916 return illegal(annos.head.pos);
1917 }
1918 break;
1919 }
1920 }
1921 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1922 selectExprMode();
1923 t = to(F.at(token.pos).Unary(
1924 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1925 nextToken();
1926 }
1927 return toP(t);
1928 }
1929
1930 /**
1931 * If we see an identifier followed by a '<' it could be an unbound
1932 * method reference or a binary expression. To disambiguate, look for a
1933 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1934 */
1935 @SuppressWarnings("fallthrough")
1936 boolean isParameterizedTypePrefix() {
1937 int pos = 0, depth = 0;
1938 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1939 switch (t.kind) {
1940 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1941 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1942 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1943 case DOUBLE: case BOOLEAN: case CHAR:
1944 case MONKEYS_AT:
1945 break;
1946
1947 case LPAREN:
1948 // skip annotation values
1949 int nesting = 0;
1950 for (; ; pos++) {
1951 TokenKind tk2 = S.token(pos).kind;
1952 switch (tk2) {
1953 case EOF:
1954 return false;
1955 case LPAREN:
1956 nesting++;
3012 accept(SEMI);
3013 return List.of(toP(F.at(pos).Yield(t)));
3014 }
3015
3016 //else intentional fall-through
3017 } else {
3018 if (isNonSealedClassStart(true)) {
3019 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3020 nextToken();
3021 nextToken();
3022 nextToken();
3023 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3024 } else if (isSealedClassStart(true)) {
3025 checkSourceLevel(Feature.SEALED_CLASSES);
3026 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3027 nextToken();
3028 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3029 }
3030 }
3031 }
3032 if ((isValueModifier()) && allowValueClasses) {
3033 checkSourceLevel(Feature.VALUE_CLASSES);
3034 dc = token.docComment();
3035 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
3036 }
3037 dc = token.docComment();
3038 if (isRecordStart() && allowRecords) {
3039 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3040 } else {
3041 Token prevToken = token;
3042 JCExpression t = term(EXPR | TYPE);
3043 if (token.kind == COLON && t.hasTag(IDENT)) {
3044 nextToken();
3045 JCStatement stat = parseStatementAsBlock();
3046 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3047 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3048 pos = token.pos;
3049 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3050 F.at(pos);
3051 return localVariableDeclarations(mods, t, dc);
3052 } else {
3053 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3054 t = checkExprStat(t);
3055 accept(SEMI);
3056 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3622 case ABSTRACT : flag = Flags.ABSTRACT; break;
3623 case NATIVE : flag = Flags.NATIVE; break;
3624 case VOLATILE : flag = Flags.VOLATILE; break;
3625 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3626 case STRICTFP : flag = Flags.STRICTFP; break;
3627 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3628 case DEFAULT : flag = Flags.DEFAULT; break;
3629 case ERROR : flag = 0; nextToken(); break;
3630 case IDENTIFIER : {
3631 if (isNonSealedClassStart(false)) {
3632 flag = Flags.NON_SEALED;
3633 nextToken();
3634 nextToken();
3635 break;
3636 }
3637 if (isSealedClassStart(false)) {
3638 checkSourceLevel(Feature.SEALED_CLASSES);
3639 flag = Flags.SEALED;
3640 break;
3641 }
3642 if (isValueModifier()) {
3643 checkSourceLevel(Feature.VALUE_CLASSES);
3644 flag = Flags.VALUE_CLASS;
3645 break;
3646 }
3647 break loop;
3648 }
3649 default: break loop;
3650 }
3651 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3652 lastPos = token.pos;
3653 nextToken();
3654 if (flag == Flags.ANNOTATION) {
3655 if (token.kind != INTERFACE) {
3656 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3657 // if first modifier is an annotation, set pos to annotation's.
3658 if (flags == 0 && annotations.isEmpty())
3659 pos = ann.pos;
3660 annotations.append(ann);
3661 flag = 0;
3662 }
3663 }
3664 flags |= flag;
3665 }
3666 switch (token.kind) {
3890 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3891 return Source.JDK10;
3892 } else if (shouldWarn) {
3893 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3894 }
3895 }
3896 if (name == names.yield) {
3897 if (allowYieldStatement) {
3898 return Source.JDK14;
3899 } else if (shouldWarn) {
3900 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3901 }
3902 }
3903 if (name == names.record) {
3904 if (allowRecords) {
3905 return Source.JDK14;
3906 } else if (shouldWarn) {
3907 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3908 }
3909 }
3910 if (name == names.value) {
3911 if (allowValueClasses) {
3912 return Source.JDK23;
3913 } else if (shouldWarn) {
3914 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3915 }
3916 }
3917 if (name == names.sealed) {
3918 if (allowSealedTypes) {
3919 return Source.JDK15;
3920 } else if (shouldWarn) {
3921 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3922 }
3923 }
3924 if (name == names.permits) {
3925 if (allowSealedTypes) {
3926 return Source.JDK15;
3927 } else if (shouldWarn) {
3928 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3929 }
3930 }
3931 return null;
3932 }
3933
3934 /** VariableDeclaratorId = Ident BracketsOpt
3935 */
3936 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
5018 Token next = S.token(3);
5019 return allowedAfterSealedOrNonSealed(next, local, true);
5020 }
5021 return false;
5022 }
5023
5024 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
5025 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
5026 Token tokenSub = S.token(lookAheadOffset + 1);
5027 Token tokenSealed = S.token(lookAheadOffset + 2);
5028 if (someToken.endPos == tokenSub.pos &&
5029 tokenSub.endPos == tokenSealed.pos &&
5030 tokenSealed.name() == names.sealed) {
5031 checkSourceLevel(Feature.SEALED_CLASSES);
5032 return true;
5033 }
5034 }
5035 return false;
5036 }
5037
5038 protected boolean isValueModifier() {
5039 if (token.kind == IDENTIFIER && token.name() == names.value) {
5040 boolean isValueModifier = false;
5041 Token next = S.token(1);
5042 switch (next.kind) {
5043 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
5044 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
5045 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
5046 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
5047 case CLASS: case INTERFACE: case ENUM:
5048 isValueModifier = true;
5049 break;
5050 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
5051 if (next.name() == names.record || next.name() == names.value
5052 || (mode & EXPR) != 0)
5053 isValueModifier = true;
5054 break;
5055 }
5056 if (isValueModifier) {
5057 checkSourceLevel(Feature.VALUE_CLASSES);
5058 return true;
5059 }
5060 }
5061 return false;
5062 }
5063
5064 protected boolean isSealedClassStart(boolean local) {
5065 if (token.name() == names.sealed) {
5066 Token next = S.token(1);
5067 if (allowedAfterSealedOrNonSealed(next, local, false)) {
5068 checkSourceLevel(Feature.SEALED_CLASSES);
5069 return true;
5070 }
5071 }
5072 return false;
5073 }
5074
5075 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5076 return local ?
5077 switch (next.kind) {
5078 case MONKEYS_AT -> {
5079 Token afterNext = S.token(2);
5080 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5081 }
5082 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5083 default -> false;
5084 } :
5085 switch (next.kind) {
5086 case MONKEYS_AT -> {
5087 Token afterNext = S.token(2);
5088 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5089 }
5090 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5091 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5092 next.name() == names.sealed ||
5093 allowValueClasses && next.name() == names.value;
5094 default -> false;
5095 };
5096 }
5097
5098 /** MethodDeclaratorRest =
5099 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5100 * VoidMethodDeclaratorRest =
5101 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5102 * ConstructorDeclaratorRest =
5103 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5104 */
5105 protected JCTree methodDeclaratorRest(int pos,
5106 JCModifiers mods,
5107 JCExpression type,
5108 Name name,
5109 List<JCTypeParameter> typarams,
5110 boolean isInterface, boolean isVoid,
5111 boolean isRecord,
5112 Comment dc) {
5113 if (isInterface) {
|