< 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 {

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


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


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




 263     /** Switch: are sealed types allowed in this source level?
 264      */
 265     boolean allowSealedTypes;
 266 
 267     /** The type of the method receiver, as specified by a first "this" parameter.
 268      */
 269     JCVariableDecl receiverParam;
 270 
 271     /** When terms are parsed, the mode determines which is expected:
 272      *     mode = EXPR        : an expression
 273      *     mode = TYPE        : a type
 274      *     mode = 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;

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

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

3002                     accept(SEMI);
3003                     return List.of(toP(F.at(pos).Yield(t)));
3004                 }
3005 
3006                 //else intentional fall-through
3007             } else {
3008                 if (isNonSealedClassStart(true)) {
3009                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3010                     nextToken();
3011                     nextToken();
3012                     nextToken();
3013                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3014                 } else if (isSealedClassStart(true)) {
3015                     checkSourceLevel(Feature.SEALED_CLASSES);
3016                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3017                     nextToken();
3018                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3019                 }
3020             }
3021         }





3022         dc = token.docComment();
3023         if (isRecordStart() && allowRecords) {
3024             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3025         } else {
3026             Token prevToken = token;
3027             JCExpression t = term(EXPR | TYPE);
3028             if (token.kind == COLON && t.hasTag(IDENT)) {
3029                 nextToken();
3030                 JCStatement stat = parseStatementAsBlock();
3031                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3032             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3033                 pos = token.pos;
3034                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3035                 F.at(pos);
3036                 return localVariableDeclarations(mods, t, dc);
3037             } else {
3038                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3039                 t = checkExprStat(t);
3040                 accept(SEMI);
3041                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

3607             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3608             case NATIVE      : flag = Flags.NATIVE; break;
3609             case VOLATILE    : flag = Flags.VOLATILE; break;
3610             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3611             case STRICTFP    : flag = Flags.STRICTFP; break;
3612             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3613             case DEFAULT     : flag = Flags.DEFAULT; break;
3614             case ERROR       : flag = 0; nextToken(); break;
3615             case IDENTIFIER  : {
3616                 if (isNonSealedClassStart(false)) {
3617                     flag = Flags.NON_SEALED;
3618                     nextToken();
3619                     nextToken();
3620                     break;
3621                 }
3622                 if (isSealedClassStart(false)) {
3623                     checkSourceLevel(Feature.SEALED_CLASSES);
3624                     flag = Flags.SEALED;
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) {

3870             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3871                 return Source.JDK10;
3872             } else if (shouldWarn) {
3873                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3874             }
3875         }
3876         if (name == names.yield) {
3877             if (allowYieldStatement) {
3878                 return Source.JDK14;
3879             } else if (shouldWarn) {
3880                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3881             }
3882         }
3883         if (name == names.record) {
3884             if (allowRecords) {
3885                 return Source.JDK14;
3886             } else if (shouldWarn) {
3887                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3888             }
3889         }







3890         if (name == names.sealed) {
3891             if (allowSealedTypes) {
3892                 return Source.JDK15;
3893             } else if (shouldWarn) {
3894                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3895             }
3896         }
3897         if (name == names.permits) {
3898             if (allowSealedTypes) {
3899                 return Source.JDK15;
3900             } else if (shouldWarn) {
3901                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3902             }
3903         }
3904         return null;
3905     }
3906 
3907     /** VariableDeclaratorId = Ident BracketsOpt
3908      */
3909     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

4990             Token next = S.token(3);
4991             return allowedAfterSealedOrNonSealed(next, local, true);
4992         }
4993         return false;
4994     }
4995 
4996     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4997         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4998             Token tokenSub = S.token(lookAheadOffset + 1);
4999             Token tokenSealed = S.token(lookAheadOffset + 2);
5000             if (someToken.endPos == tokenSub.pos &&
5001                     tokenSub.endPos == tokenSealed.pos &&
5002                     tokenSealed.name() == names.sealed) {
5003                 checkSourceLevel(Feature.SEALED_CLASSES);
5004                 return true;
5005             }
5006         }
5007         return false;
5008     }
5009 


























5010     protected boolean isSealedClassStart(boolean local) {
5011         if (token.name() == names.sealed) {
5012             Token next = S.token(1);
5013             if (allowedAfterSealedOrNonSealed(next, local, false)) {
5014                 checkSourceLevel(Feature.SEALED_CLASSES);
5015                 return true;
5016             }
5017         }
5018         return false;
5019     }
5020 
5021     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5022         return local ?
5023             switch (next.kind) {
5024                 case MONKEYS_AT -> {
5025                     Token afterNext = S.token(2);
5026                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5027                 }
5028                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5029                 default -> false;
5030             } :
5031             switch (next.kind) {
5032                 case MONKEYS_AT -> {
5033                     Token afterNext = S.token(2);
5034                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5035                 }
5036                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5037                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;


5038                 default -> false;
5039             };
5040     }
5041 
5042     /** MethodDeclaratorRest =
5043      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5044      *  VoidMethodDeclaratorRest =
5045      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
5046      *  ConstructorDeclaratorRest =
5047      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5048      */
5049     protected JCTree methodDeclaratorRest(int pos,
5050                               JCModifiers mods,
5051                               JCExpression type,
5052                               Name name,
5053                               List<JCTypeParameter> typarams,
5054                               boolean isInterface, boolean isVoid,
5055                               boolean isRecord,
5056                               Comment dc) {
5057         if (isInterface) {

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

 185                      boolean keepLineMap,
 186                      boolean keepEndPositions,
 187                      boolean parseModuleInfo) {
 188         this.S = S;
 189         nextToken(); // prime the pump
 190         this.F = fac.F;
 191         this.log = fac.log;
 192         this.names = fac.names;
 193         this.source = fac.source;
 194         this.preview = fac.preview;
 195         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 196         this.keepDocComments = keepDocComments;
 197         this.parseModuleInfo = parseModuleInfo;
 198         this.docComments = newDocCommentTable(keepDocComments, fac);
 199         this.keepLineMap = keepLineMap;
 200         this.errorTree = F.Erroneous();
 201         this.endPosTable = newEndPosTable(keepEndPositions);
 202         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 203         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 204         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 205         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 206                 Feature.VALUE_CLASSES.allowedInSource(source);
 207         updateUnexpectedTopLevelDefinitionStartError(false);
 208     }
 209 
 210     /** Construct a parser from an existing parser, with minimal overhead.
 211      */
 212     @SuppressWarnings("this-escape")
 213     protected JavacParser(JavacParser parser,
 214                           Lexer S) {
 215         this.S = S;
 216         this.token = parser.token;
 217         this.F = parser.F;
 218         this.log = parser.log;
 219         this.names = parser.names;
 220         this.source = parser.source;
 221         this.preview = parser.preview;
 222         this.allowStringFolding = parser.allowStringFolding;
 223         this.keepDocComments = parser.keepDocComments;
 224         this.parseModuleInfo = false;
 225         this.docComments = parser.docComments;
 226         this.errorTree = F.Erroneous();
 227         this.endPosTable = newEndPosTable(false);
 228         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 229         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 230         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
 231         this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 232                 Feature.VALUE_CLASSES.allowedInSource(source);
 233         updateUnexpectedTopLevelDefinitionStartError(false);
 234     }
 235 
 236     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
 237         return  keepEndPositions
 238                 ? new SimpleEndPosTable()
 239                 : new MinimalEndPosTable();
 240     }
 241 
 242     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 243         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 244     }
 245 
 246     /** Switch: should we fold strings?
 247      */
 248     boolean allowStringFolding;
 249 
 250     /** Switch: should we keep docComments?
 251      */
 252     boolean keepDocComments;
 253 
 254     /** Switch: should we keep line table?
 255      */
 256     boolean keepLineMap;
 257 
 258     /** Switch: is "this" allowed as an identifier?
 259      * This is needed to parse receiver types.
 260      */
 261     boolean allowThisIdent;
 262 
 263     /** Switch: is yield statement allowed in this source level?
 264      */
 265     boolean allowYieldStatement;
 266 
 267     /** Switch: are records allowed in this source level?
 268      */
 269     boolean allowRecords;
 270 
 271     /** Switch: are value classes allowed in this source level?
 272      */
 273     boolean allowValueClasses;
 274 
 275     /** Switch: are sealed types allowed in this source level?
 276      */
 277     boolean allowSealedTypes;
 278 
 279     /** The type of the method receiver, as specified by a first "this" parameter.
 280      */
 281     JCVariableDecl receiverParam;
 282 
 283     /** When terms are parsed, the mode determines which is expected:
 284      *     mode = EXPR        : an expression
 285      *     mode = TYPE        : a type
 286      *     mode = 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;

1672                             token.kind == MONKEYS_AT) {
1673                             //error recovery, case like:
1674                             //int i = expr.<missing-ident>
1675                             //@Deprecated
1676                             if (typeArgs != null) illegal();
1677                             return toP(t);
1678                         }
1679                         if (tyannos != null && tyannos.nonEmpty()) {
1680                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1681                         }
1682                         break;
1683                     case ELLIPSIS:
1684                         if (this.permitTypeAnnotationsPushBack) {
1685                             this.typeAnnotationsPushedBack = annos;
1686                         } else if (annos.nonEmpty()) {
1687                             // Don't return here -- error recovery attempt
1688                             illegal(annos.head.pos);
1689                         }
1690                         break loop;
1691                     case LT:
1692                         if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1693                             //this is either an unbound method reference whose qualifier
1694                             //is a generic type i.e. A<S>::m
1695                             int pos1 = token.pos;
1696                             accept(LT);
1697                             ListBuffer<JCExpression> args = new ListBuffer<>();
1698                             args.append(typeArgument());
1699                             while (token.kind == COMMA) {
1700                                 nextToken();
1701                                 args.append(typeArgument());
1702                             }
1703                             accept(GT);
1704                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
1705                             while (token.kind == DOT) {
1706                                 nextToken();
1707                                 selectTypeMode();
1708                                 t = toP(F.at(token.pos).Select(t, ident()));
1709                                 t = typeArgumentsOpt(t);
1710                             }
1711                             t = bracketsOpt(t);
1712                             if (token.kind != COLCOL) {
1713                                 //method reference expected here

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

3014                     accept(SEMI);
3015                     return List.of(toP(F.at(pos).Yield(t)));
3016                 }
3017 
3018                 //else intentional fall-through
3019             } else {
3020                 if (isNonSealedClassStart(true)) {
3021                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3022                     nextToken();
3023                     nextToken();
3024                     nextToken();
3025                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3026                 } else if (isSealedClassStart(true)) {
3027                     checkSourceLevel(Feature.SEALED_CLASSES);
3028                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
3029                     nextToken();
3030                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
3031                 }
3032             }
3033         }
3034         if ((isValueModifier()) && allowValueClasses) {
3035             checkSourceLevel(Feature.VALUE_CLASSES);
3036             dc = token.docComment();
3037             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
3038         }
3039         dc = token.docComment();
3040         if (isRecordStart() && allowRecords) {
3041             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3042         } else {
3043             Token prevToken = token;
3044             JCExpression t = term(EXPR | TYPE);
3045             if (token.kind == COLON && t.hasTag(IDENT)) {
3046                 nextToken();
3047                 JCStatement stat = parseStatementAsBlock();
3048                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3049             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3050                 pos = token.pos;
3051                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3052                 F.at(pos);
3053                 return localVariableDeclarations(mods, t, dc);
3054             } else {
3055                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3056                 t = checkExprStat(t);
3057                 accept(SEMI);
3058                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

3624             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3625             case NATIVE      : flag = Flags.NATIVE; break;
3626             case VOLATILE    : flag = Flags.VOLATILE; break;
3627             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3628             case STRICTFP    : flag = Flags.STRICTFP; break;
3629             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3630             case DEFAULT     : flag = Flags.DEFAULT; break;
3631             case ERROR       : flag = 0; nextToken(); break;
3632             case IDENTIFIER  : {
3633                 if (isNonSealedClassStart(false)) {
3634                     flag = Flags.NON_SEALED;
3635                     nextToken();
3636                     nextToken();
3637                     break;
3638                 }
3639                 if (isSealedClassStart(false)) {
3640                     checkSourceLevel(Feature.SEALED_CLASSES);
3641                     flag = Flags.SEALED;
3642                     break;
3643                 }
3644                 if (isValueModifier()) {
3645                     checkSourceLevel(Feature.VALUE_CLASSES);
3646                     flag = Flags.VALUE_CLASS;
3647                     break;
3648                 }
3649                 break loop;
3650             }
3651             default: break loop;
3652             }
3653             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3654             lastPos = token.pos;
3655             nextToken();
3656             if (flag == Flags.ANNOTATION) {
3657                 if (token.kind != INTERFACE) {
3658                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3659                     // if first modifier is an annotation, set pos to annotation's.
3660                     if (flags == 0 && annotations.isEmpty())
3661                         pos = ann.pos;
3662                     annotations.append(ann);
3663                     flag = 0;
3664                 }
3665             }
3666             flags |= flag;
3667         }
3668         switch (token.kind) {

3892             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3893                 return Source.JDK10;
3894             } else if (shouldWarn) {
3895                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3896             }
3897         }
3898         if (name == names.yield) {
3899             if (allowYieldStatement) {
3900                 return Source.JDK14;
3901             } else if (shouldWarn) {
3902                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3903             }
3904         }
3905         if (name == names.record) {
3906             if (allowRecords) {
3907                 return Source.JDK14;
3908             } else if (shouldWarn) {
3909                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3910             }
3911         }
3912         if (name == names.value) {
3913             if (allowValueClasses) {
3914                 return Source.JDK23;
3915             } else if (shouldWarn) {
3916                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3917             }
3918         }
3919         if (name == names.sealed) {
3920             if (allowSealedTypes) {
3921                 return Source.JDK15;
3922             } else if (shouldWarn) {
3923                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3924             }
3925         }
3926         if (name == names.permits) {
3927             if (allowSealedTypes) {
3928                 return Source.JDK15;
3929             } else if (shouldWarn) {
3930                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3931             }
3932         }
3933         return null;
3934     }
3935 
3936     /** VariableDeclaratorId = Ident BracketsOpt
3937      */
3938     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

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