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

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


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


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




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

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

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

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





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

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





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

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







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

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


























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


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

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

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

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

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

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

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

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