< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java

Print this page

  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.parser;
  27 
  28 import java.util.*;
  29 import java.util.function.Function;
  30 import java.util.function.Predicate;
  31 import java.util.stream.Collectors;
  32 
  33 import javax.lang.model.SourceVersion;
  34 
  35 import com.sun.source.tree.CaseTree;
  36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  37 import com.sun.source.tree.ModuleTree.ModuleKind;
  38 
  39 import com.sun.tools.javac.code.*;

  40 import com.sun.tools.javac.code.Source.Feature;
  41 import com.sun.tools.javac.file.PathFileObject;
  42 import com.sun.tools.javac.parser.Tokens.*;

  43 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  44 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  45 import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
  46 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  47 import com.sun.tools.javac.tree.*;
  48 import com.sun.tools.javac.tree.JCTree.*;
  49 import com.sun.tools.javac.util.*;
  50 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  51 import com.sun.tools.javac.util.JCDiagnostic.Error;
  52 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  53 import com.sun.tools.javac.util.List;
  54 

  55 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  56 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  57 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  59 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  60 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  61 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  62 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;

  63 import com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
  64 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  65 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  66 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  67 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  68 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  69 
  70 /**
  71  * The parser maps a token sequence into an abstract syntax tree.
  72  * The parser is a hand-written recursive-descent parser that
  73  * implements the grammar described in the Java Language Specification.
  74  * For efficiency reasons, an operator precedence scheme is used
  75  * for parsing binary operation expressions.
  76  *
  77  *  <p><b>This is NOT part of any supported API.
  78  *  If you write code that depends on this, you do so at your own risk.
  79  *  This code and its internal interfaces are subject to change or
  80  *  deletion without notice.</b>
  81  */
  82 public class JavacParser implements Parser {

 177                      Lexer S,
 178                      boolean keepDocComments,
 179                      boolean keepLineMap,
 180                      boolean parseModuleInfo) {
 181         this.S = S;
 182         nextToken(); // prime the pump
 183         this.F = fac.F;
 184         this.log = fac.log;
 185         this.names = fac.names;
 186         this.source = fac.source;
 187         this.preview = fac.preview;
 188         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 189         this.keepDocComments = keepDocComments;
 190         this.parseModuleInfo = parseModuleInfo;
 191         this.docComments = newDocCommentTable(keepDocComments, fac);
 192         this.keepLineMap = keepLineMap;
 193         this.errorTree = F.Erroneous();
 194         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 195         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 196         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);


 197         updateUnexpectedTopLevelDefinitionStartError(false);
 198     }
 199 
 200     /** Construct a parser from an existing parser, with minimal overhead.
 201      */
 202     @SuppressWarnings("this-escape")
 203     protected JavacParser(JavacParser parser,
 204                           Lexer S) {
 205         this.S = S;
 206         this.token = parser.token;
 207         this.F = parser.F;
 208         this.log = parser.log;
 209         this.names = parser.names;
 210         this.source = parser.source;
 211         this.preview = parser.preview;
 212         this.allowStringFolding = parser.allowStringFolding;
 213         this.keepDocComments = parser.keepDocComments;
 214         this.parseModuleInfo = false;
 215         this.docComments = parser.docComments;
 216         this.errorTree = F.Erroneous();
 217         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 218         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 219         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);


 220         updateUnexpectedTopLevelDefinitionStartError(false);
 221     }
 222 
 223     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 224         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 225     }
 226 
 227     /** Switch: should we fold strings?
 228      */
 229     boolean allowStringFolding;
 230 
 231     /** Switch: should we keep docComments?
 232      */
 233     boolean keepDocComments;
 234 
 235     /** Switch: should we keep line table?
 236      */
 237     boolean keepLineMap;
 238 
 239     /** Switch: is "this" allowed as an identifier?
 240      * This is needed to parse receiver types.
 241      */
 242     boolean allowThisIdent;
 243 
 244     /** Switch: is yield statement allowed in this source level?
 245      */
 246     boolean allowYieldStatement;
 247 
 248     /** Switch: are records allowed in this source level?
 249      */
 250     boolean allowRecords;
 251 




 252     /** Switch: are sealed types allowed in this source level?
 253      */
 254     boolean allowSealedTypes;
 255 
 256     /** The type of the method receiver, as specified by a first "this" parameter.
 257      */
 258     JCVariableDecl receiverParam;
 259 
 260     /** When terms are parsed, the mode determines which is expected:
 261      *     mode = EXPR        : an expression
 262      *     mode = TYPE        : a type
 263      *     mode = NOLAMBDA    : lambdas are not allowed
 264      */
 265     protected static final int EXPR          = 1 << 0;
 266     protected static final int TYPE          = 1 << 1;
 267     protected static final int NOLAMBDA      = 1 << 2;
 268 
 269     protected void setMode(int mode) {
 270         this.mode = mode;
 271     }

1645                             token.kind == MONKEYS_AT) {
1646                             //error recovery, case like:
1647                             //int i = expr.<missing-ident>
1648                             //@Deprecated
1649                             if (typeArgs != null) illegal();
1650                             return toP(t);
1651                         }
1652                         if (tyannos != null && tyannos.nonEmpty()) {
1653                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1654                         }
1655                         break;
1656                     case ELLIPSIS:
1657                         if (this.permitTypeAnnotationsPushBack) {
1658                             this.typeAnnotationsPushedBack = annos;
1659                         } else if (annos.nonEmpty()) {
1660                             // Don't return here -- error recovery attempt
1661                             illegal(annos.head.pos);
1662                         }
1663                         break loop;
1664                     case LT:
1665                         if (!isMode(TYPE) && isUnboundMemberRef()) {
1666                             //this is an unbound method reference whose qualifier
1667                             //is a generic type i.e. A<S>::m
1668                             int pos1 = token.pos;
1669                             accept(LT);
1670                             ListBuffer<JCExpression> args = new ListBuffer<>();
1671                             args.append(typeArgument());
1672                             while (token.kind == COMMA) {
1673                                 nextToken();
1674                                 args.append(typeArgument());
1675                             }
1676                             accept(GT);
1677                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
1678                             while (token.kind == DOT) {
1679                                 nextToken();
1680                                 selectTypeMode();
1681                                 t = toP(F.at(token.pos).Select(t, ident()));
1682                                 t = typeApplyOpt(t);
1683                             }
1684                             t = bracketsOpt(t);
1685                             if (token.kind != COLCOL) {
1686                                 //method reference expected here

1891                         return illegal(annos.head.pos);
1892                 }
1893                 break;
1894             }
1895         }
1896         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1897             selectExprMode();
1898             t = to(F.at(token.pos).Unary(
1899                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1900             nextToken();
1901         }
1902         return toP(t);
1903     }
1904 
1905     /**
1906      * If we see an identifier followed by a '&lt;' it could be an unbound
1907      * method reference or a binary expression. To disambiguate, look for a
1908      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1909      */
1910     @SuppressWarnings("fallthrough")
1911     boolean isUnboundMemberRef() {
1912         int pos = 0, depth = 0;
1913         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1914             switch (t.kind) {
1915                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1916                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1917                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1918                 case DOUBLE: case BOOLEAN: case CHAR:
1919                 case MONKEYS_AT:
1920                     break;
1921 
1922                 case LPAREN:
1923                     // skip annotation values
1924                     int nesting = 0;
1925                     for (; ; pos++) {
1926                         TokenKind tk2 = S.token(pos).kind;
1927                         switch (tk2) {
1928                             case EOF:
1929                                 return false;
1930                             case LPAREN:
1931                                 nesting++;

2986                     accept(SEMI);
2987                     return List.of(toP(F.at(pos).Yield(t)));
2988                 }
2989 
2990                 //else intentional fall-through
2991             } else {
2992                 if (isNonSealedClassStart(true)) {
2993                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2994                     nextToken();
2995                     nextToken();
2996                     nextToken();
2997                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2998                 } else if (isSealedClassStart(true)) {
2999                     checkSourceLevel(Feature.SEALED_CLASSES);
3000                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3001                     nextToken();
3002                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3003                 }
3004             }
3005         }





3006         dc = token.docComment();
3007         if (isRecordStart() && allowRecords) {
3008             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3009         } else {
3010             Token prevToken = token;
3011             JCExpression t = term(EXPR | TYPE);
3012             if (token.kind == COLON && t.hasTag(IDENT)) {
3013                 nextToken();
3014                 JCStatement stat = parseStatementAsBlock();
3015                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3016             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3017                 pos = token.pos;
3018                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3019                 F.at(pos);
3020                 return localVariableDeclarations(mods, t, dc);
3021             } else {
3022                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3023                 t = checkExprStat(t);
3024                 accept(SEMI);
3025                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

3591             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3592             case NATIVE      : flag = Flags.NATIVE; break;
3593             case VOLATILE    : flag = Flags.VOLATILE; break;
3594             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3595             case STRICTFP    : flag = Flags.STRICTFP; break;
3596             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3597             case DEFAULT     : flag = Flags.DEFAULT; break;
3598             case ERROR       : flag = 0; nextToken(); break;
3599             case IDENTIFIER  : {
3600                 if (isNonSealedClassStart(false)) {
3601                     flag = Flags.NON_SEALED;
3602                     nextToken();
3603                     nextToken();
3604                     break;
3605                 }
3606                 if (isSealedClassStart(false)) {
3607                     checkSourceLevel(Feature.SEALED_CLASSES);
3608                     flag = Flags.SEALED;
3609                     break;
3610                 }





3611                 break loop;
3612             }
3613             default: break loop;
3614             }
3615             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3616             lastPos = token.pos;
3617             nextToken();
3618             if (flag == Flags.ANNOTATION) {
3619                 if (token.kind != INTERFACE) {
3620                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3621                     // if first modifier is an annotation, set pos to annotation's.
3622                     if (flags == 0 && annotations.isEmpty())
3623                         pos = ann.pos;
3624                     annotations.append(ann);
3625                     flag = 0;
3626                 }
3627             }
3628             flags |= flag;
3629         }
3630         switch (token.kind) {

3858             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3859                 return Source.JDK10;
3860             } else if (shouldWarn) {
3861                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3862             }
3863         }
3864         if (name == names.yield) {
3865             if (allowYieldStatement) {
3866                 return Source.JDK14;
3867             } else if (shouldWarn) {
3868                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3869             }
3870         }
3871         if (name == names.record) {
3872             if (allowRecords) {
3873                 return Source.JDK14;
3874             } else if (shouldWarn) {
3875                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3876             }
3877         }







3878         if (name == names.sealed) {
3879             if (allowSealedTypes) {
3880                 return Source.JDK15;
3881             } else if (shouldWarn) {
3882                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3883             }
3884         }
3885         if (name == names.permits) {
3886             if (allowSealedTypes) {
3887                 return Source.JDK15;
3888             } else if (shouldWarn) {
3889                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3890             }
3891         }
3892         return null;
3893     }
3894 
3895     /** VariableDeclaratorId = Ident BracketsOpt
3896      */
3897     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

4978             Token next = S.token(3);
4979             return allowedAfterSealedOrNonSealed(next, local, true);
4980         }
4981         return false;
4982     }
4983 
4984     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4985         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4986             Token tokenSub = S.token(lookAheadOffset + 1);
4987             Token tokenSealed = S.token(lookAheadOffset + 2);
4988             if (someToken.endPos == tokenSub.pos &&
4989                     tokenSub.endPos == tokenSealed.pos &&
4990                     tokenSealed.name() == names.sealed) {
4991                 checkSourceLevel(Feature.SEALED_CLASSES);
4992                 return true;
4993             }
4994         }
4995         return false;
4996     }
4997 


























4998     protected boolean isSealedClassStart(boolean local) {
4999         if (token.name() == names.sealed) {
5000             Token next = S.token(1);
5001             if (allowedAfterSealedOrNonSealed(next, local, false)) {
5002                 checkSourceLevel(Feature.SEALED_CLASSES);
5003                 return true;
5004             }
5005         }
5006         return false;
5007     }
5008 
5009     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5010         return local ?
5011             switch (next.kind) {
5012                 case MONKEYS_AT -> {
5013                     Token afterNext = S.token(2);
5014                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5015                 }
5016                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5017                 default -> false;
5018             } :
5019             switch (next.kind) {
5020                 case MONKEYS_AT -> {
5021                     Token afterNext = S.token(2);
5022                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5023                 }
5024                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5025                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;


5026                 default -> false;
5027             };
5028     }
5029 
5030     /** MethodDeclaratorRest =
5031      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5032      *  VoidMethodDeclaratorRest =
5033      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
5034      *  ConstructorDeclaratorRest =
5035      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5036      */
5037     protected JCTree methodDeclaratorRest(int pos,
5038                               JCModifiers mods,
5039                               JCExpression type,
5040                               Name name,
5041                               List<JCTypeParameter> typarams,
5042                               boolean isInterface, boolean isVoid,
5043                               boolean isRecord,
5044                               Comment dc) {
5045         if (isInterface) {

  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.parser;
  27 
  28 import java.util.*;
  29 import java.util.function.Function;
  30 import java.util.function.Predicate;
  31 import java.util.stream.Collectors;
  32 
  33 import javax.lang.model.SourceVersion;
  34 
  35 import com.sun.source.tree.CaseTree;
  36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  37 import com.sun.source.tree.ModuleTree.ModuleKind;
  38 
  39 import com.sun.tools.javac.code.*;
  40 import com.sun.tools.javac.code.FlagsEnum;
  41 import com.sun.tools.javac.code.Source.Feature;
  42 import com.sun.tools.javac.file.PathFileObject;
  43 import com.sun.tools.javac.parser.Tokens.*;
  44 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  45 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  46 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  47 import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
  48 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  49 import com.sun.tools.javac.tree.*;
  50 import com.sun.tools.javac.tree.JCTree.*;
  51 import com.sun.tools.javac.util.*;
  52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  53 import com.sun.tools.javac.util.JCDiagnostic.Error;
  54 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  55 import com.sun.tools.javac.util.List;
  56 
  57 import static com.sun.tools.javac.code.Flags.asFlagSet;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  59 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  61 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  62 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  63 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  64 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  65 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  66 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
  67 import com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
  68 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  70 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  71 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  72 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  73 
  74 /**
  75  * The parser maps a token sequence into an abstract syntax tree.
  76  * The parser is a hand-written recursive-descent parser that
  77  * implements the grammar described in the Java Language Specification.
  78  * For efficiency reasons, an operator precedence scheme is used
  79  * for parsing binary operation expressions.
  80  *
  81  *  <p><b>This is NOT part of any supported API.
  82  *  If you write code that depends on this, you do so at your own risk.
  83  *  This code and its internal interfaces are subject to change or
  84  *  deletion without notice.</b>
  85  */
  86 public class JavacParser implements Parser {

 181                      Lexer S,
 182                      boolean keepDocComments,
 183                      boolean keepLineMap,
 184                      boolean parseModuleInfo) {
 185         this.S = S;
 186         nextToken(); // prime the pump
 187         this.F = fac.F;
 188         this.log = fac.log;
 189         this.names = fac.names;
 190         this.source = fac.source;
 191         this.preview = fac.preview;
 192         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 193         this.keepDocComments = keepDocComments;
 194         this.parseModuleInfo = parseModuleInfo;
 195         this.docComments = newDocCommentTable(keepDocComments, fac);
 196         this.keepLineMap = keepLineMap;
 197         this.errorTree = F.Erroneous();
 198         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 199         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 200         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 201         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 202                 Feature.VALUE_CLASSES.allowedInSource(source);
 203         updateUnexpectedTopLevelDefinitionStartError(false);
 204     }
 205 
 206     /** Construct a parser from an existing parser, with minimal overhead.
 207      */
 208     @SuppressWarnings("this-escape")
 209     protected JavacParser(JavacParser parser,
 210                           Lexer S) {
 211         this.S = S;
 212         this.token = parser.token;
 213         this.F = parser.F;
 214         this.log = parser.log;
 215         this.names = parser.names;
 216         this.source = parser.source;
 217         this.preview = parser.preview;
 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.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 224         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 225         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 226         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 227                 Feature.VALUE_CLASSES.allowedInSource(source);
 228         updateUnexpectedTopLevelDefinitionStartError(false);
 229     }
 230 
 231     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 232         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 233     }
 234 
 235     /** Switch: should we fold strings?
 236      */
 237     boolean allowStringFolding;
 238 
 239     /** Switch: should we keep docComments?
 240      */
 241     boolean keepDocComments;
 242 
 243     /** Switch: should we keep line table?
 244      */
 245     boolean keepLineMap;
 246 
 247     /** Switch: is "this" allowed as an identifier?
 248      * This is needed to parse receiver types.
 249      */
 250     boolean allowThisIdent;
 251 
 252     /** Switch: is yield statement allowed in this source level?
 253      */
 254     boolean allowYieldStatement;
 255 
 256     /** Switch: are records allowed in this source level?
 257      */
 258     boolean allowRecords;
 259 
 260     /** Switch: are value classes allowed in this source level?
 261      */
 262     boolean allowValueClasses;
 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 = 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 NOLAMBDA      = 1 << 2;
 280 
 281     protected void setMode(int mode) {
 282         this.mode = mode;
 283     }

1657                             token.kind == MONKEYS_AT) {
1658                             //error recovery, case like:
1659                             //int i = expr.<missing-ident>
1660                             //@Deprecated
1661                             if (typeArgs != null) illegal();
1662                             return toP(t);
1663                         }
1664                         if (tyannos != null && tyannos.nonEmpty()) {
1665                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1666                         }
1667                         break;
1668                     case ELLIPSIS:
1669                         if (this.permitTypeAnnotationsPushBack) {
1670                             this.typeAnnotationsPushedBack = annos;
1671                         } else if (annos.nonEmpty()) {
1672                             // Don't return here -- error recovery attempt
1673                             illegal(annos.head.pos);
1674                         }
1675                         break loop;
1676                     case LT:
1677                         if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1678                             //this is either an unbound method reference whose qualifier
1679                             //is a generic type i.e. A<S>::m
1680                             int pos1 = token.pos;
1681                             accept(LT);
1682                             ListBuffer<JCExpression> args = new ListBuffer<>();
1683                             args.append(typeArgument());
1684                             while (token.kind == COMMA) {
1685                                 nextToken();
1686                                 args.append(typeArgument());
1687                             }
1688                             accept(GT);
1689                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
1690                             while (token.kind == DOT) {
1691                                 nextToken();
1692                                 selectTypeMode();
1693                                 t = toP(F.at(token.pos).Select(t, ident()));
1694                                 t = typeApplyOpt(t);
1695                             }
1696                             t = bracketsOpt(t);
1697                             if (token.kind != COLCOL) {
1698                                 //method reference expected here

1903                         return illegal(annos.head.pos);
1904                 }
1905                 break;
1906             }
1907         }
1908         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1909             selectExprMode();
1910             t = to(F.at(token.pos).Unary(
1911                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1912             nextToken();
1913         }
1914         return toP(t);
1915     }
1916 
1917     /**
1918      * If we see an identifier followed by a '&lt;' it could be an unbound
1919      * method reference or a binary expression. To disambiguate, look for a
1920      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1921      */
1922     @SuppressWarnings("fallthrough")
1923     boolean isParameterizedTypePrefix() {
1924         int pos = 0, depth = 0;
1925         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1926             switch (t.kind) {
1927                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1928                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1929                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1930                 case DOUBLE: case BOOLEAN: case CHAR:
1931                 case MONKEYS_AT:
1932                     break;
1933 
1934                 case LPAREN:
1935                     // skip annotation values
1936                     int nesting = 0;
1937                     for (; ; pos++) {
1938                         TokenKind tk2 = S.token(pos).kind;
1939                         switch (tk2) {
1940                             case EOF:
1941                                 return false;
1942                             case LPAREN:
1943                                 nesting++;

2998                     accept(SEMI);
2999                     return List.of(toP(F.at(pos).Yield(t)));
3000                 }
3001 
3002                 //else intentional fall-through
3003             } else {
3004                 if (isNonSealedClassStart(true)) {
3005                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3006                     nextToken();
3007                     nextToken();
3008                     nextToken();
3009                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3010                 } else if (isSealedClassStart(true)) {
3011                     checkSourceLevel(Feature.SEALED_CLASSES);
3012                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3013                     nextToken();
3014                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3015                 }
3016             }
3017         }
3018         if ((isValueModifier()) && allowValueClasses) {
3019             checkSourceLevel(Feature.VALUE_CLASSES);
3020             dc = token.docComment();
3021             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
3022         }
3023         dc = token.docComment();
3024         if (isRecordStart() && allowRecords) {
3025             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3026         } else {
3027             Token prevToken = token;
3028             JCExpression t = term(EXPR | TYPE);
3029             if (token.kind == COLON && t.hasTag(IDENT)) {
3030                 nextToken();
3031                 JCStatement stat = parseStatementAsBlock();
3032                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3033             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3034                 pos = token.pos;
3035                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3036                 F.at(pos);
3037                 return localVariableDeclarations(mods, t, dc);
3038             } else {
3039                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3040                 t = checkExprStat(t);
3041                 accept(SEMI);
3042                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

3608             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3609             case NATIVE      : flag = Flags.NATIVE; break;
3610             case VOLATILE    : flag = Flags.VOLATILE; break;
3611             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3612             case STRICTFP    : flag = Flags.STRICTFP; break;
3613             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3614             case DEFAULT     : flag = Flags.DEFAULT; break;
3615             case ERROR       : flag = 0; nextToken(); break;
3616             case IDENTIFIER  : {
3617                 if (isNonSealedClassStart(false)) {
3618                     flag = Flags.NON_SEALED;
3619                     nextToken();
3620                     nextToken();
3621                     break;
3622                 }
3623                 if (isSealedClassStart(false)) {
3624                     checkSourceLevel(Feature.SEALED_CLASSES);
3625                     flag = Flags.SEALED;
3626                     break;
3627                 }
3628                 if (isValueModifier()) {
3629                     checkSourceLevel(Feature.VALUE_CLASSES);
3630                     flag = Flags.VALUE_CLASS;
3631                     break;
3632                 }
3633                 break loop;
3634             }
3635             default: break loop;
3636             }
3637             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3638             lastPos = token.pos;
3639             nextToken();
3640             if (flag == Flags.ANNOTATION) {
3641                 if (token.kind != INTERFACE) {
3642                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3643                     // if first modifier is an annotation, set pos to annotation's.
3644                     if (flags == 0 && annotations.isEmpty())
3645                         pos = ann.pos;
3646                     annotations.append(ann);
3647                     flag = 0;
3648                 }
3649             }
3650             flags |= flag;
3651         }
3652         switch (token.kind) {

3880             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3881                 return Source.JDK10;
3882             } else if (shouldWarn) {
3883                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3884             }
3885         }
3886         if (name == names.yield) {
3887             if (allowYieldStatement) {
3888                 return Source.JDK14;
3889             } else if (shouldWarn) {
3890                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3891             }
3892         }
3893         if (name == names.record) {
3894             if (allowRecords) {
3895                 return Source.JDK14;
3896             } else if (shouldWarn) {
3897                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3898             }
3899         }
3900         if (name == names.value) {
3901             if (allowValueClasses) {
3902                 return Source.JDK23;
3903             } else if (shouldWarn) {
3904                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3905             }
3906         }
3907         if (name == names.sealed) {
3908             if (allowSealedTypes) {
3909                 return Source.JDK15;
3910             } else if (shouldWarn) {
3911                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3912             }
3913         }
3914         if (name == names.permits) {
3915             if (allowSealedTypes) {
3916                 return Source.JDK15;
3917             } else if (shouldWarn) {
3918                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3919             }
3920         }
3921         return null;
3922     }
3923 
3924     /** VariableDeclaratorId = Ident BracketsOpt
3925      */
3926     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

5007             Token next = S.token(3);
5008             return allowedAfterSealedOrNonSealed(next, local, true);
5009         }
5010         return false;
5011     }
5012 
5013     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
5014         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
5015             Token tokenSub = S.token(lookAheadOffset + 1);
5016             Token tokenSealed = S.token(lookAheadOffset + 2);
5017             if (someToken.endPos == tokenSub.pos &&
5018                     tokenSub.endPos == tokenSealed.pos &&
5019                     tokenSealed.name() == names.sealed) {
5020                 checkSourceLevel(Feature.SEALED_CLASSES);
5021                 return true;
5022             }
5023         }
5024         return false;
5025     }
5026 
5027     protected boolean isValueModifier() {
5028         if (token.kind == IDENTIFIER && token.name() == names.value) {
5029             boolean isValueModifier = false;
5030             Token next = S.token(1);
5031             switch (next.kind) {
5032                 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
5033                 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
5034                 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
5035                 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
5036                 case CLASS: case INTERFACE: case ENUM:
5037                     isValueModifier = true;
5038                     break;
5039                 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
5040                     if (next.name() == names.record || next.name() == names.value
5041                             || (mode & EXPR) != 0)
5042                         isValueModifier = true;
5043                     break;
5044             }
5045             if (isValueModifier) {
5046                 checkSourceLevel(Feature.VALUE_CLASSES);
5047                 return true;
5048             }
5049         }
5050         return false;
5051     }
5052 
5053     protected boolean isSealedClassStart(boolean local) {
5054         if (token.name() == names.sealed) {
5055             Token next = S.token(1);
5056             if (allowedAfterSealedOrNonSealed(next, local, false)) {
5057                 checkSourceLevel(Feature.SEALED_CLASSES);
5058                 return true;
5059             }
5060         }
5061         return false;
5062     }
5063 
5064     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5065         return local ?
5066             switch (next.kind) {
5067                 case MONKEYS_AT -> {
5068                     Token afterNext = S.token(2);
5069                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5070                 }
5071                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5072                 default -> false;
5073             } :
5074             switch (next.kind) {
5075                 case MONKEYS_AT -> {
5076                     Token afterNext = S.token(2);
5077                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5078                 }
5079                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5080                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5081                         next.name() == names.sealed ||
5082                         allowValueClasses && next.name() == names.value;
5083                 default -> false;
5084             };
5085     }
5086 
5087     /** MethodDeclaratorRest =
5088      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5089      *  VoidMethodDeclaratorRest =
5090      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
5091      *  ConstructorDeclaratorRest =
5092      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5093      */
5094     protected JCTree methodDeclaratorRest(int pos,
5095                               JCModifiers mods,
5096                               JCExpression type,
5097                               Name name,
5098                               List<JCTypeParameter> typarams,
5099                               boolean isInterface, boolean isVoid,
5100                               boolean isRecord,
5101                               Comment dc) {
5102         if (isInterface) {
< prev index next >