20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.parser;
27
28 import java.util.*;
29 import java.util.function.Function;
30 import java.util.function.Predicate;
31 import java.util.stream.Collectors;
32
33 import javax.lang.model.SourceVersion;
34
35 import com.sun.source.tree.CaseTree;
36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
37 import com.sun.source.tree.ModuleTree.ModuleKind;
38
39 import com.sun.tools.javac.code.*;
40 import com.sun.tools.javac.code.Source.Feature;
41 import com.sun.tools.javac.file.PathFileObject;
42 import com.sun.tools.javac.parser.Tokens.*;
43 import com.sun.tools.javac.resources.CompilerProperties.Errors;
44 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
45 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
46 import com.sun.tools.javac.tree.*;
47 import com.sun.tools.javac.tree.JCTree.*;
48 import com.sun.tools.javac.util.*;
49 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
50 import com.sun.tools.javac.util.JCDiagnostic.Error;
51 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
52 import com.sun.tools.javac.util.List;
53
54 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
55 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
56 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
62 import static com.sun.tools.javac.tree.JCTree.Tag.*;
63 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
64 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
65 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
66 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
67
68 /**
69 * The parser maps a token sequence into an abstract syntax tree.
70 * The parser is a hand-written recursive-descent parser that
71 * implements the grammar described in the Java Language Specification.
72 * For efficiency reasons, an operator precedence scheme is used
73 * for parsing binary operation expressions.
74 *
75 * <p><b>This is NOT part of any supported API.
76 * If you write code that depends on this, you do so at your own risk.
77 * This code and its internal interfaces are subject to change or
78 * deletion without notice.</b>
79 */
80 public class JavacParser implements Parser {
81
181 boolean keepEndPositions,
182 boolean parseModuleInfo) {
183 this.S = S;
184 nextToken(); // prime the pump
185 this.F = fac.F;
186 this.log = fac.log;
187 this.names = fac.names;
188 this.source = fac.source;
189 this.preview = fac.preview;
190 this.deferredLintHandler = fac.deferredLintHandler;
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 }
202
203 /** Construct a parser from an existing parser, with minimal overhead.
204 */
205 @SuppressWarnings("this-escape")
206 protected JavacParser(JavacParser parser,
207 Lexer S) {
208 this.S = S;
209 this.token = parser.token;
210 this.F = parser.F;
211 this.log = parser.log;
212 this.names = parser.names;
213 this.source = parser.source;
214 this.preview = parser.preview;
215 this.deferredLintHandler = parser.deferredLintHandler;
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 }
226
227 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
228 return keepEndPositions
229 ? new SimpleEndPosTable(this)
230 : new EmptyEndPosTable(this);
231 }
232
233 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
234 return keepDocComments ? new LazyDocCommentTable(fac) : null;
235 }
236
237 /** Switch: should we fold strings?
238 */
239 boolean allowStringFolding;
240
241 /** Switch: should we keep docComments?
242 */
243 boolean keepDocComments;
244
245 /** Switch: should we keep line table?
246 */
247 boolean keepLineMap;
248
249 /** Switch: is "this" allowed as an identifier?
250 * This is needed to parse receiver types.
251 */
252 boolean allowThisIdent;
253
254 /** Switch: is yield statement allowed in this source level?
255 */
256 boolean allowYieldStatement;
257
258 /** Switch: are records allowed in this source level?
259 */
260 boolean allowRecords;
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 = NOPARAMS : no parameters allowed for type
274 * mode = TYPEARG : type argument
275 * mode |= NOLAMBDA : lambdas are not allowed
276 */
277 protected static final int EXPR = 1 << 0;
278 protected static final int TYPE = 1 << 1;
279 protected static final int NOPARAMS = 1 << 2;
280 protected static final int TYPEARG = 1 << 3;
281 protected static final int DIAMOND = 1 << 4;
1623 token.kind == MONKEYS_AT) {
1624 //error recovery, case like:
1625 //int i = expr.<missing-ident>
1626 //@Deprecated
1627 if (typeArgs != null) illegal();
1628 return toP(t);
1629 }
1630 if (tyannos != null && tyannos.nonEmpty()) {
1631 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1632 }
1633 break;
1634 case ELLIPSIS:
1635 if (this.permitTypeAnnotationsPushBack) {
1636 this.typeAnnotationsPushedBack = annos;
1637 } else if (annos.nonEmpty()) {
1638 // Don't return here -- error recovery attempt
1639 illegal(annos.head.pos);
1640 }
1641 break loop;
1642 case LT:
1643 if (!isMode(TYPE) && isUnboundMemberRef()) {
1644 //this is an unbound method reference whose qualifier
1645 //is a generic type i.e. A<S>::m
1646 int pos1 = token.pos;
1647 accept(LT);
1648 ListBuffer<JCExpression> args = new ListBuffer<>();
1649 args.append(typeArgument());
1650 while (token.kind == COMMA) {
1651 nextToken();
1652 args.append(typeArgument());
1653 }
1654 accept(GT);
1655 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1656 while (token.kind == DOT) {
1657 nextToken();
1658 selectTypeMode();
1659 t = toP(F.at(token.pos).Select(t, ident()));
1660 t = typeArgumentsOpt(t);
1661 }
1662 t = bracketsOpt(t);
1663 if (token.kind != COLCOL) {
1664 //method reference expected here
1866 return illegal(annos.head.pos);
1867 }
1868 break;
1869 }
1870 }
1871 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1872 selectExprMode();
1873 t = to(F.at(token.pos).Unary(
1874 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1875 nextToken();
1876 }
1877 return toP(t);
1878 }
1879
1880 /**
1881 * If we see an identifier followed by a '<' it could be an unbound
1882 * method reference or a binary expression. To disambiguate, look for a
1883 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1884 */
1885 @SuppressWarnings("fallthrough")
1886 boolean isUnboundMemberRef() {
1887 int pos = 0, depth = 0;
1888 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1889 switch (t.kind) {
1890 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1891 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1892 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1893 case DOUBLE: case BOOLEAN: case CHAR:
1894 case MONKEYS_AT:
1895 break;
1896
1897 case LPAREN:
1898 // skip annotation values
1899 int nesting = 0;
1900 for (; ; pos++) {
1901 TokenKind tk2 = S.token(pos).kind;
1902 switch (tk2) {
1903 case EOF:
1904 return false;
1905 case LPAREN:
1906 nesting++;
2963 accept(SEMI);
2964 return List.of(toP(F.at(pos).Yield(t)));
2965 }
2966
2967 //else intentional fall-through
2968 } else {
2969 if (isNonSealedClassStart(true)) {
2970 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2971 nextToken();
2972 nextToken();
2973 nextToken();
2974 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2975 } else if (isSealedClassStart(true)) {
2976 checkSourceLevel(Feature.SEALED_CLASSES);
2977 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2978 nextToken();
2979 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2980 }
2981 }
2982 }
2983 dc = token.docComment();
2984 if (isRecordStart() && allowRecords) {
2985 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2986 } else {
2987 Token prevToken = token;
2988 JCExpression t = term(EXPR | TYPE);
2989 if (token.kind == COLON && t.hasTag(IDENT)) {
2990 nextToken();
2991 JCStatement stat = parseStatementAsBlock();
2992 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2993 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
2994 pos = token.pos;
2995 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2996 F.at(pos);
2997 return localVariableDeclarations(mods, t, dc);
2998 } else {
2999 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3000 t = checkExprStat(t);
3001 accept(SEMI);
3002 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3560 case ABSTRACT : flag = Flags.ABSTRACT; break;
3561 case NATIVE : flag = Flags.NATIVE; break;
3562 case VOLATILE : flag = Flags.VOLATILE; break;
3563 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3564 case STRICTFP : flag = Flags.STRICTFP; break;
3565 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3566 case DEFAULT : flag = Flags.DEFAULT; break;
3567 case ERROR : flag = 0; nextToken(); break;
3568 case IDENTIFIER : {
3569 if (isNonSealedClassStart(false)) {
3570 flag = Flags.NON_SEALED;
3571 nextToken();
3572 nextToken();
3573 break;
3574 }
3575 if (isSealedClassStart(false)) {
3576 checkSourceLevel(Feature.SEALED_CLASSES);
3577 flag = Flags.SEALED;
3578 break;
3579 }
3580 break loop;
3581 }
3582 default: break loop;
3583 }
3584 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3585 lastPos = token.pos;
3586 nextToken();
3587 if (flag == Flags.ANNOTATION) {
3588 if (token.kind != INTERFACE) {
3589 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3590 // if first modifier is an annotation, set pos to annotation's.
3591 if (flags == 0 && annotations.isEmpty())
3592 pos = ann.pos;
3593 annotations.append(ann);
3594 flag = 0;
3595 }
3596 }
3597 flags |= flag;
3598 }
3599 switch (token.kind) {
3828 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3829 return Source.JDK10;
3830 } else if (shouldWarn) {
3831 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3832 }
3833 }
3834 if (name == names.yield) {
3835 if (allowYieldStatement) {
3836 return Source.JDK14;
3837 } else if (shouldWarn) {
3838 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3839 }
3840 }
3841 if (name == names.record) {
3842 if (allowRecords) {
3843 return Source.JDK14;
3844 } else if (shouldWarn) {
3845 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3846 }
3847 }
3848 if (name == names.sealed) {
3849 if (allowSealedTypes) {
3850 return Source.JDK15;
3851 } else if (shouldWarn) {
3852 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3853 }
3854 }
3855 if (name == names.permits) {
3856 if (allowSealedTypes) {
3857 return Source.JDK15;
3858 } else if (shouldWarn) {
3859 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3860 }
3861 }
3862 return null;
3863 }
3864
3865 /** VariableDeclaratorId = Ident BracketsOpt
3866 */
3867 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4918 Token next = S.token(3);
4919 return allowedAfterSealedOrNonSealed(next, local, true);
4920 }
4921 return false;
4922 }
4923
4924 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4925 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4926 Token tokenSub = S.token(lookAheadOffset + 1);
4927 Token tokenSealed = S.token(lookAheadOffset + 2);
4928 if (someToken.endPos == tokenSub.pos &&
4929 tokenSub.endPos == tokenSealed.pos &&
4930 tokenSealed.name() == names.sealed) {
4931 checkSourceLevel(Feature.SEALED_CLASSES);
4932 return true;
4933 }
4934 }
4935 return false;
4936 }
4937
4938 protected boolean isSealedClassStart(boolean local) {
4939 if (token.name() == names.sealed) {
4940 Token next = S.token(1);
4941 if (allowedAfterSealedOrNonSealed(next, local, false)) {
4942 checkSourceLevel(Feature.SEALED_CLASSES);
4943 return true;
4944 }
4945 }
4946 return false;
4947 }
4948
4949 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4950 return local ?
4951 switch (next.kind) {
4952 case MONKEYS_AT -> {
4953 Token afterNext = S.token(2);
4954 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4955 }
4956 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4957 default -> false;
4958 } :
4959 switch (next.kind) {
4960 case MONKEYS_AT -> {
4961 Token afterNext = S.token(2);
4962 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4963 }
4964 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4965 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
4966 default -> false;
4967 };
4968 }
4969
4970 /** MethodDeclaratorRest =
4971 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4972 * VoidMethodDeclaratorRest =
4973 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
4974 * ConstructorDeclaratorRest =
4975 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4976 */
4977 protected JCTree methodDeclaratorRest(int pos,
4978 JCModifiers mods,
4979 JCExpression type,
4980 Name name,
4981 List<JCTypeParameter> typarams,
4982 boolean isInterface, boolean isVoid,
4983 boolean isRecord,
4984 Comment dc) {
4985 if (isInterface) {
|
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.parser;
27
28 import java.util.*;
29 import java.util.function.Function;
30 import java.util.function.Predicate;
31 import java.util.stream.Collectors;
32
33 import javax.lang.model.SourceVersion;
34
35 import com.sun.source.tree.CaseTree;
36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
37 import com.sun.source.tree.ModuleTree.ModuleKind;
38
39 import com.sun.tools.javac.code.*;
40 import com.sun.tools.javac.code.Flags.Flag;
41 import com.sun.tools.javac.code.Source.Feature;
42 import com.sun.tools.javac.file.PathFileObject;
43 import com.sun.tools.javac.parser.Tokens.*;
44 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
45 import com.sun.tools.javac.resources.CompilerProperties.Errors;
46 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
47 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
48 import com.sun.tools.javac.tree.*;
49 import com.sun.tools.javac.tree.JCTree.*;
50 import com.sun.tools.javac.util.*;
51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
52 import com.sun.tools.javac.util.JCDiagnostic.Error;
53 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
54 import com.sun.tools.javac.util.List;
55
56 import static com.sun.tools.javac.code.Flags.asFlagSet;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
62 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
63 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
64 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
65 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
66 import static com.sun.tools.javac.tree.JCTree.Tag.*;
67 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
68 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
70 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
71
72 /**
73 * The parser maps a token sequence into an abstract syntax tree.
74 * The parser is a hand-written recursive-descent parser that
75 * implements the grammar described in the Java Language Specification.
76 * For efficiency reasons, an operator precedence scheme is used
77 * for parsing binary operation expressions.
78 *
79 * <p><b>This is NOT part of any supported API.
80 * If you write code that depends on this, you do so at your own risk.
81 * This code and its internal interfaces are subject to change or
82 * deletion without notice.</b>
83 */
84 public class JavacParser implements Parser {
85
185 boolean keepEndPositions,
186 boolean parseModuleInfo) {
187 this.S = S;
188 nextToken(); // prime the pump
189 this.F = fac.F;
190 this.log = fac.log;
191 this.names = fac.names;
192 this.source = fac.source;
193 this.preview = fac.preview;
194 this.deferredLintHandler = fac.deferredLintHandler;
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 }
208
209 /** Construct a parser from an existing parser, with minimal overhead.
210 */
211 @SuppressWarnings("this-escape")
212 protected JavacParser(JavacParser parser,
213 Lexer S) {
214 this.S = S;
215 this.token = parser.token;
216 this.F = parser.F;
217 this.log = parser.log;
218 this.names = parser.names;
219 this.source = parser.source;
220 this.preview = parser.preview;
221 this.deferredLintHandler = parser.deferredLintHandler;
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 }
234
235 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
236 return keepEndPositions
237 ? new SimpleEndPosTable(this)
238 : new EmptyEndPosTable(this);
239 }
240
241 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
242 return keepDocComments ? new LazyDocCommentTable(fac) : null;
243 }
244
245 /** Switch: should we fold strings?
246 */
247 boolean allowStringFolding;
248
249 /** Switch: should we keep docComments?
250 */
251 boolean keepDocComments;
252
253 /** Switch: should we keep line table?
254 */
255 boolean keepLineMap;
256
257 /** Switch: is "this" allowed as an identifier?
258 * This is needed to parse receiver types.
259 */
260 boolean allowThisIdent;
261
262 /** Switch: is yield statement allowed in this source level?
263 */
264 boolean allowYieldStatement;
265
266 /** Switch: are records allowed in this source level?
267 */
268 boolean allowRecords;
269
270 /** Switch: are value classes allowed in this source level?
271 */
272 boolean allowValueClasses;
273
274 /** Switch: are sealed types allowed in this source level?
275 */
276 boolean allowSealedTypes;
277
278 /** The type of the method receiver, as specified by a first "this" parameter.
279 */
280 JCVariableDecl receiverParam;
281
282 /** When terms are parsed, the mode determines which is expected:
283 * mode = EXPR : an expression
284 * mode = TYPE : a type
285 * mode = NOPARAMS : no parameters allowed for type
286 * mode = TYPEARG : type argument
287 * mode |= NOLAMBDA : lambdas are not allowed
288 */
289 protected static final int EXPR = 1 << 0;
290 protected static final int TYPE = 1 << 1;
291 protected static final int NOPARAMS = 1 << 2;
292 protected static final int TYPEARG = 1 << 3;
293 protected static final int DIAMOND = 1 << 4;
1635 token.kind == MONKEYS_AT) {
1636 //error recovery, case like:
1637 //int i = expr.<missing-ident>
1638 //@Deprecated
1639 if (typeArgs != null) illegal();
1640 return toP(t);
1641 }
1642 if (tyannos != null && tyannos.nonEmpty()) {
1643 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1644 }
1645 break;
1646 case ELLIPSIS:
1647 if (this.permitTypeAnnotationsPushBack) {
1648 this.typeAnnotationsPushedBack = annos;
1649 } else if (annos.nonEmpty()) {
1650 // Don't return here -- error recovery attempt
1651 illegal(annos.head.pos);
1652 }
1653 break loop;
1654 case LT:
1655 if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1656 //this is either an unbound method reference whose qualifier
1657 //is a generic type i.e. A<S>::m
1658 int pos1 = token.pos;
1659 accept(LT);
1660 ListBuffer<JCExpression> args = new ListBuffer<>();
1661 args.append(typeArgument());
1662 while (token.kind == COMMA) {
1663 nextToken();
1664 args.append(typeArgument());
1665 }
1666 accept(GT);
1667 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1668 while (token.kind == DOT) {
1669 nextToken();
1670 selectTypeMode();
1671 t = toP(F.at(token.pos).Select(t, ident()));
1672 t = typeArgumentsOpt(t);
1673 }
1674 t = bracketsOpt(t);
1675 if (token.kind != COLCOL) {
1676 //method reference expected here
1878 return illegal(annos.head.pos);
1879 }
1880 break;
1881 }
1882 }
1883 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1884 selectExprMode();
1885 t = to(F.at(token.pos).Unary(
1886 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1887 nextToken();
1888 }
1889 return toP(t);
1890 }
1891
1892 /**
1893 * If we see an identifier followed by a '<' it could be an unbound
1894 * method reference or a binary expression. To disambiguate, look for a
1895 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1896 */
1897 @SuppressWarnings("fallthrough")
1898 boolean isParameterizedTypePrefix() {
1899 int pos = 0, depth = 0;
1900 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1901 switch (t.kind) {
1902 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1903 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1904 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1905 case DOUBLE: case BOOLEAN: case CHAR:
1906 case MONKEYS_AT:
1907 break;
1908
1909 case LPAREN:
1910 // skip annotation values
1911 int nesting = 0;
1912 for (; ; pos++) {
1913 TokenKind tk2 = S.token(pos).kind;
1914 switch (tk2) {
1915 case EOF:
1916 return false;
1917 case LPAREN:
1918 nesting++;
2975 accept(SEMI);
2976 return List.of(toP(F.at(pos).Yield(t)));
2977 }
2978
2979 //else intentional fall-through
2980 } else {
2981 if (isNonSealedClassStart(true)) {
2982 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2983 nextToken();
2984 nextToken();
2985 nextToken();
2986 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2987 } else if (isSealedClassStart(true)) {
2988 checkSourceLevel(Feature.SEALED_CLASSES);
2989 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2990 nextToken();
2991 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2992 }
2993 }
2994 }
2995 if ((isValueModifier()) && allowValueClasses) {
2996 checkSourceLevel(Feature.VALUE_CLASSES);
2997 dc = token.docComment();
2998 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2999 }
3000 dc = token.docComment();
3001 if (isRecordStart() && allowRecords) {
3002 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3003 } else {
3004 Token prevToken = token;
3005 JCExpression t = term(EXPR | TYPE);
3006 if (token.kind == COLON && t.hasTag(IDENT)) {
3007 nextToken();
3008 JCStatement stat = parseStatementAsBlock();
3009 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3010 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3011 pos = token.pos;
3012 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3013 F.at(pos);
3014 return localVariableDeclarations(mods, t, dc);
3015 } else {
3016 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3017 t = checkExprStat(t);
3018 accept(SEMI);
3019 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3577 case ABSTRACT : flag = Flags.ABSTRACT; break;
3578 case NATIVE : flag = Flags.NATIVE; break;
3579 case VOLATILE : flag = Flags.VOLATILE; break;
3580 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3581 case STRICTFP : flag = Flags.STRICTFP; break;
3582 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3583 case DEFAULT : flag = Flags.DEFAULT; break;
3584 case ERROR : flag = 0; nextToken(); break;
3585 case IDENTIFIER : {
3586 if (isNonSealedClassStart(false)) {
3587 flag = Flags.NON_SEALED;
3588 nextToken();
3589 nextToken();
3590 break;
3591 }
3592 if (isSealedClassStart(false)) {
3593 checkSourceLevel(Feature.SEALED_CLASSES);
3594 flag = Flags.SEALED;
3595 break;
3596 }
3597 if (isValueModifier()) {
3598 checkSourceLevel(Feature.VALUE_CLASSES);
3599 flag = Flags.VALUE_CLASS;
3600 break;
3601 }
3602 break loop;
3603 }
3604 default: break loop;
3605 }
3606 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3607 lastPos = token.pos;
3608 nextToken();
3609 if (flag == Flags.ANNOTATION) {
3610 if (token.kind != INTERFACE) {
3611 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3612 // if first modifier is an annotation, set pos to annotation's.
3613 if (flags == 0 && annotations.isEmpty())
3614 pos = ann.pos;
3615 annotations.append(ann);
3616 flag = 0;
3617 }
3618 }
3619 flags |= flag;
3620 }
3621 switch (token.kind) {
3850 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3851 return Source.JDK10;
3852 } else if (shouldWarn) {
3853 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3854 }
3855 }
3856 if (name == names.yield) {
3857 if (allowYieldStatement) {
3858 return Source.JDK14;
3859 } else if (shouldWarn) {
3860 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3861 }
3862 }
3863 if (name == names.record) {
3864 if (allowRecords) {
3865 return Source.JDK14;
3866 } else if (shouldWarn) {
3867 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3868 }
3869 }
3870 if (name == names.value) {
3871 if (allowValueClasses) {
3872 return Source.JDK23;
3873 } else if (shouldWarn) {
3874 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3875 }
3876 }
3877 if (name == names.sealed) {
3878 if (allowSealedTypes) {
3879 return Source.JDK15;
3880 } else if (shouldWarn) {
3881 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3882 }
3883 }
3884 if (name == names.permits) {
3885 if (allowSealedTypes) {
3886 return Source.JDK15;
3887 } else if (shouldWarn) {
3888 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3889 }
3890 }
3891 return null;
3892 }
3893
3894 /** VariableDeclaratorId = Ident BracketsOpt
3895 */
3896 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4947 Token next = S.token(3);
4948 return allowedAfterSealedOrNonSealed(next, local, true);
4949 }
4950 return false;
4951 }
4952
4953 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4954 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4955 Token tokenSub = S.token(lookAheadOffset + 1);
4956 Token tokenSealed = S.token(lookAheadOffset + 2);
4957 if (someToken.endPos == tokenSub.pos &&
4958 tokenSub.endPos == tokenSealed.pos &&
4959 tokenSealed.name() == names.sealed) {
4960 checkSourceLevel(Feature.SEALED_CLASSES);
4961 return true;
4962 }
4963 }
4964 return false;
4965 }
4966
4967 protected boolean isValueModifier() {
4968 if (token.kind == IDENTIFIER && token.name() == names.value) {
4969 boolean isValueModifier = false;
4970 Token next = S.token(1);
4971 switch (next.kind) {
4972 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
4973 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
4974 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
4975 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
4976 case CLASS: case INTERFACE: case ENUM:
4977 isValueModifier = true;
4978 break;
4979 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
4980 if (next.name() == names.record || next.name() == names.value
4981 || (mode & EXPR) != 0)
4982 isValueModifier = true;
4983 break;
4984 }
4985 if (isValueModifier) {
4986 checkSourceLevel(Feature.VALUE_CLASSES);
4987 return true;
4988 }
4989 }
4990 return false;
4991 }
4992
4993 protected boolean isSealedClassStart(boolean local) {
4994 if (token.name() == names.sealed) {
4995 Token next = S.token(1);
4996 if (allowedAfterSealedOrNonSealed(next, local, false)) {
4997 checkSourceLevel(Feature.SEALED_CLASSES);
4998 return true;
4999 }
5000 }
5001 return false;
5002 }
5003
5004 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5005 return local ?
5006 switch (next.kind) {
5007 case MONKEYS_AT -> {
5008 Token afterNext = S.token(2);
5009 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5010 }
5011 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5012 default -> false;
5013 } :
5014 switch (next.kind) {
5015 case MONKEYS_AT -> {
5016 Token afterNext = S.token(2);
5017 yield afterNext.kind != INTERFACE || currentIsNonSealed;
5018 }
5019 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5020 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5021 next.name() == names.sealed ||
5022 allowValueClasses && next.name() == names.value;
5023 default -> false;
5024 };
5025 }
5026
5027 /** MethodDeclaratorRest =
5028 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5029 * VoidMethodDeclaratorRest =
5030 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
5031 * ConstructorDeclaratorRest =
5032 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5033 */
5034 protected JCTree methodDeclaratorRest(int pos,
5035 JCModifiers mods,
5036 JCExpression type,
5037 Name name,
5038 List<JCTypeParameter> typarams,
5039 boolean isInterface, boolean isVoid,
5040 boolean isRecord,
5041 Comment dc) {
5042 if (isInterface) {
|