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