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