< 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()
 235                 : new MinimalEndPosTable();
 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;

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

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

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





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

3609             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3610             case NATIVE      : flag = Flags.NATIVE; break;
3611             case VOLATILE    : flag = Flags.VOLATILE; break;
3612             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3613             case STRICTFP    : flag = Flags.STRICTFP; break;
3614             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3615             case DEFAULT     : flag = Flags.DEFAULT; break;
3616             case ERROR       : flag = 0; nextToken(); break;
3617             case IDENTIFIER  : {
3618                 if (isNonSealedClassStart(false)) {
3619                     flag = Flags.NON_SEALED;
3620                     nextToken();
3621                     nextToken();
3622                     break;
3623                 }
3624                 if (isSealedClassStart(false)) {
3625                     checkSourceLevel(Feature.SEALED_CLASSES);
3626                     flag = Flags.SEALED;
3627                     break;
3628                 }





3629                 break loop;
3630             }
3631             default: break loop;
3632             }
3633             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3634             lastPos = token.pos;
3635             nextToken();
3636             if (flag == Flags.ANNOTATION) {
3637                 if (token.kind != INTERFACE) {
3638                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3639                     // if first modifier is an annotation, set pos to annotation's.
3640                     if (flags == 0 && annotations.isEmpty())
3641                         pos = ann.pos;
3642                     annotations.append(ann);
3643                     flag = 0;
3644                 }
3645             }
3646             flags |= flag;
3647         }
3648         switch (token.kind) {

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







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

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


























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


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

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

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

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

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

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

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