< prev index next >

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

Print this page

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

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

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

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

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

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


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


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




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

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

1896                         return illegal(annos.head.pos);
1897                 }
1898                 break;
1899             }
1900         }
1901         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1902             selectExprMode();
1903             t = to(F.at(token.pos).Unary(
1904                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1905             nextToken();
1906         }
1907         return toP(t);
1908     }
1909 
1910     /**
1911      * If we see an identifier followed by a '&lt;' it could be an unbound
1912      * method reference or a binary expression. To disambiguate, look for a
1913      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1914      */
1915     @SuppressWarnings("fallthrough")
1916     boolean isUnboundMemberRef() {
1917         int pos = 0, depth = 0;
1918         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1919             switch (t.kind) {
1920                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1921                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1922                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1923                 case DOUBLE: case BOOLEAN: case CHAR:
1924                 case MONKEYS_AT:
1925                     break;
1926 
1927                 case LPAREN:
1928                     // skip annotation values
1929                     int nesting = 0;
1930                     for (; ; pos++) {
1931                         TokenKind tk2 = S.token(pos).kind;
1932                         switch (tk2) {
1933                             case EOF:
1934                                 return false;
1935                             case LPAREN:
1936                                 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         dc = token.docComment();
3013         if (isRecordStart() && allowRecords) {
3014             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3015         } else {
3016             Token prevToken = token;
3017             JCExpression t = term(EXPR | TYPE);
3018             if (token.kind == COLON && t.hasTag(IDENT)) {
3019                 nextToken();
3020                 JCStatement stat = parseStatementAsBlock();
3021                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3022             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3023                 pos = token.pos;
3024                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3025                 F.at(pos);
3026                 return localVariableDeclarations(mods, t, dc);
3027             } else {
3028                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3029                 t = checkExprStat(t);
3030                 accept(SEMI);
3031                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

3597             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3598             case NATIVE      : flag = Flags.NATIVE; break;
3599             case VOLATILE    : flag = Flags.VOLATILE; break;
3600             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3601             case STRICTFP    : flag = Flags.STRICTFP; break;
3602             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3603             case DEFAULT     : flag = Flags.DEFAULT; break;
3604             case ERROR       : flag = 0; nextToken(); break;
3605             case IDENTIFIER  : {
3606                 if (isNonSealedClassStart(false)) {
3607                     flag = Flags.NON_SEALED;
3608                     nextToken();
3609                     nextToken();
3610                     break;
3611                 }
3612                 if (isSealedClassStart(false)) {
3613                     checkSourceLevel(Feature.SEALED_CLASSES);
3614                     flag = Flags.SEALED;
3615                     break;
3616                 }





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

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







3880         if (name == names.sealed) {
3881             if (allowSealedTypes) {
3882                 return Source.JDK15;
3883             } else if (shouldWarn) {
3884                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3885             }
3886         }
3887         if (name == names.permits) {
3888             if (allowSealedTypes) {
3889                 return Source.JDK15;
3890             } else if (shouldWarn) {
3891                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3892             }
3893         }
3894         return null;
3895     }
3896 
3897     /** VariableDeclaratorId = Ident BracketsOpt
3898      */
3899     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.FlagsEnum;
  41 import com.sun.tools.javac.code.Source.Feature;
  42 import com.sun.tools.javac.file.PathFileObject;
  43 import com.sun.tools.javac.parser.Tokens.*;
  44 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  45 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  46 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  47 import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
  48 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  49 import com.sun.tools.javac.tree.*;
  50 import com.sun.tools.javac.tree.JCTree.*;
  51 import com.sun.tools.javac.util.*;
  52 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  53 import com.sun.tools.javac.util.JCDiagnostic.Error;
  54 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  55 import com.sun.tools.javac.util.List;
  56 
  57 import static com.sun.tools.javac.code.Flags.asFlagSet;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  59 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  61 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  62 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  63 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  64 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  65 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  66 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
  67 import com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
  68 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  70 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  71 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  72 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  73 
  74 /**
  75  * The parser maps a token sequence into an abstract syntax tree.
  76  * The parser is a hand-written recursive-descent parser that
  77  * implements the grammar described in the Java Language Specification.
  78  * For efficiency reasons, an operator precedence scheme is used
  79  * for parsing binary operation expressions.
  80  *
  81  *  <p><b>This is NOT part of any supported API.
  82  *  If you write code that depends on this, you do so at your own risk.
  83  *  This code and its internal interfaces are subject to change or
  84  *  deletion without notice.</b>
  85  */
  86 public class JavacParser implements Parser {

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

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

1908                         return illegal(annos.head.pos);
1909                 }
1910                 break;
1911             }
1912         }
1913         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1914             selectExprMode();
1915             t = to(F.at(token.pos).Unary(
1916                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1917             nextToken();
1918         }
1919         return toP(t);
1920     }
1921 
1922     /**
1923      * If we see an identifier followed by a '&lt;' it could be an unbound
1924      * method reference or a binary expression. To disambiguate, look for a
1925      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1926      */
1927     @SuppressWarnings("fallthrough")
1928     boolean isParameterizedTypePrefix() {
1929         int pos = 0, depth = 0;
1930         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1931             switch (t.kind) {
1932                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1933                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1934                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1935                 case DOUBLE: case BOOLEAN: case CHAR:
1936                 case MONKEYS_AT:
1937                     break;
1938 
1939                 case LPAREN:
1940                     // skip annotation values
1941                     int nesting = 0;
1942                     for (; ; pos++) {
1943                         TokenKind tk2 = S.token(pos).kind;
1944                         switch (tk2) {
1945                             case EOF:
1946                                 return false;
1947                             case LPAREN:
1948                                 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         if ((isValueModifier()) && allowValueClasses) {
3025             checkSourceLevel(Feature.VALUE_CLASSES);
3026             dc = token.docComment();
3027             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
3028         }
3029         dc = token.docComment();
3030         if (isRecordStart() && allowRecords) {
3031             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
3032         } else {
3033             Token prevToken = token;
3034             JCExpression t = term(EXPR | TYPE);
3035             if (token.kind == COLON && t.hasTag(IDENT)) {
3036                 nextToken();
3037                 JCStatement stat = parseStatementAsBlock();
3038                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3039             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3040                 pos = token.pos;
3041                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3042                 F.at(pos);
3043                 return localVariableDeclarations(mods, t, dc);
3044             } else {
3045                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3046                 t = checkExprStat(t);
3047                 accept(SEMI);
3048                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

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

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