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

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


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


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




 267     /** Switch: are sealed types allowed in this source level?
 268      */
 269     boolean allowSealedTypes;
 270 
 271     /** The type of the method receiver, as specified by a first "this" parameter.
 272      */
 273     JCVariableDecl receiverParam;
 274 
 275     /** When terms are parsed, the mode determines which is expected:
 276      *     mode = EXPR        : an expression
 277      *     mode = TYPE        : a type
 278      *     mode = NOPARAMS    : no parameters allowed for type
 279      *     mode = TYPEARG     : type argument
 280      *     mode |= NOLAMBDA   : lambdas are not allowed
 281      */
 282     protected static final int EXPR          = 1 << 0;
 283     protected static final int TYPE          = 1 << 1;
 284     protected static final int NOPARAMS      = 1 << 2;
 285     protected static final int TYPEARG       = 1 << 3;
 286     protected static final int DIAMOND       = 1 << 4;

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 = typeArgumentsOpt(t);
1683                             }
1684                             t = bracketsOpt(t);
1685                             if (token.kind != COLCOL) {
1686                                 //method reference expected here

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

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





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

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





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

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







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

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


























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


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

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

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

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 = typeArgumentsOpt(t);
1695                             }
1696                             t = bracketsOpt(t);
1697                             if (token.kind != COLCOL) {
1698                                 //method reference expected here

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

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

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

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

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