< 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.Warnings;
  46 import com.sun.tools.javac.tree.*;
  47 import com.sun.tools.javac.tree.JCTree.*;
  48 import com.sun.tools.javac.util.*;
  49 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  50 import com.sun.tools.javac.util.JCDiagnostic.Error;
  51 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  52 import com.sun.tools.javac.util.List;
  53 

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

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

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


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


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




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

1623                             token.kind == MONKEYS_AT) {
1624                             //error recovery, case like:
1625                             //int i = expr.<missing-ident>
1626                             //@Deprecated
1627                             if (typeArgs != null) illegal();
1628                             return toP(t);
1629                         }
1630                         if (tyannos != null && tyannos.nonEmpty()) {
1631                             t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1632                         }
1633                         break;
1634                     case ELLIPSIS:
1635                         if (this.permitTypeAnnotationsPushBack) {
1636                             this.typeAnnotationsPushedBack = annos;
1637                         } else if (annos.nonEmpty()) {
1638                             // Don't return here -- error recovery attempt
1639                             illegal(annos.head.pos);
1640                         }
1641                         break loop;
1642                     case LT:
1643                         if (!isMode(TYPE) && isUnboundMemberRef()) {
1644                             //this is an unbound method reference whose qualifier
1645                             //is a generic type i.e. A<S>::m
1646                             int pos1 = token.pos;
1647                             accept(LT);
1648                             ListBuffer<JCExpression> args = new ListBuffer<>();
1649                             args.append(typeArgument());
1650                             while (token.kind == COMMA) {
1651                                 nextToken();
1652                                 args.append(typeArgument());
1653                             }
1654                             accept(GT);
1655                             t = toP(F.at(pos1).TypeApply(t, args.toList()));
1656                             while (token.kind == DOT) {
1657                                 nextToken();
1658                                 selectTypeMode();
1659                                 t = toP(F.at(token.pos).Select(t, ident()));
1660                                 t = typeArgumentsOpt(t);
1661                             }
1662                             t = bracketsOpt(t);
1663                             if (token.kind != COLCOL) {
1664                                 //method reference expected here

1866                         return illegal(annos.head.pos);
1867                 }
1868                 break;
1869             }
1870         }
1871         while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1872             selectExprMode();
1873             t = to(F.at(token.pos).Unary(
1874                   token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1875             nextToken();
1876         }
1877         return toP(t);
1878     }
1879 
1880     /**
1881      * If we see an identifier followed by a '&lt;' it could be an unbound
1882      * method reference or a binary expression. To disambiguate, look for a
1883      * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
1884      */
1885     @SuppressWarnings("fallthrough")
1886     boolean isUnboundMemberRef() {
1887         int pos = 0, depth = 0;
1888         outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1889             switch (t.kind) {
1890                 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1891                 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1892                 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1893                 case DOUBLE: case BOOLEAN: case CHAR:
1894                 case MONKEYS_AT:
1895                     break;
1896 
1897                 case LPAREN:
1898                     // skip annotation values
1899                     int nesting = 0;
1900                     for (; ; pos++) {
1901                         TokenKind tk2 = S.token(pos).kind;
1902                         switch (tk2) {
1903                             case EOF:
1904                                 return false;
1905                             case LPAREN:
1906                                 nesting++;

2963                     accept(SEMI);
2964                     return List.of(toP(F.at(pos).Yield(t)));
2965                 }
2966 
2967                 //else intentional fall-through
2968             } else {
2969                 if (isNonSealedClassStart(true)) {
2970                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2971                     nextToken();
2972                     nextToken();
2973                     nextToken();
2974                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2975                 } else if (isSealedClassStart(true)) {
2976                     checkSourceLevel(Feature.SEALED_CLASSES);
2977                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2978                     nextToken();
2979                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2980                 }
2981             }
2982         }





2983         dc = token.docComment();
2984         if (isRecordStart() && allowRecords) {
2985             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2986         } else {
2987             Token prevToken = token;
2988             JCExpression t = term(EXPR | TYPE);
2989             if (token.kind == COLON && t.hasTag(IDENT)) {
2990                 nextToken();
2991                 JCStatement stat = parseStatementAsBlock();
2992                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2993             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
2994                 pos = token.pos;
2995                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2996                 F.at(pos);
2997                 return localVariableDeclarations(mods, t, dc);
2998             } else {
2999                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3000                 t = checkExprStat(t);
3001                 accept(SEMI);
3002                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));

3560             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3561             case NATIVE      : flag = Flags.NATIVE; break;
3562             case VOLATILE    : flag = Flags.VOLATILE; break;
3563             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3564             case STRICTFP    : flag = Flags.STRICTFP; break;
3565             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3566             case DEFAULT     : flag = Flags.DEFAULT; break;
3567             case ERROR       : flag = 0; nextToken(); break;
3568             case IDENTIFIER  : {
3569                 if (isNonSealedClassStart(false)) {
3570                     flag = Flags.NON_SEALED;
3571                     nextToken();
3572                     nextToken();
3573                     break;
3574                 }
3575                 if (isSealedClassStart(false)) {
3576                     checkSourceLevel(Feature.SEALED_CLASSES);
3577                     flag = Flags.SEALED;
3578                     break;
3579                 }





3580                 break loop;
3581             }
3582             default: break loop;
3583             }
3584             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3585             lastPos = token.pos;
3586             nextToken();
3587             if (flag == Flags.ANNOTATION) {
3588                 if (token.kind != INTERFACE) {
3589                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3590                     // if first modifier is an annotation, set pos to annotation's.
3591                     if (flags == 0 && annotations.isEmpty())
3592                         pos = ann.pos;
3593                     annotations.append(ann);
3594                     flag = 0;
3595                 }
3596             }
3597             flags |= flag;
3598         }
3599         switch (token.kind) {

3828             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3829                 return Source.JDK10;
3830             } else if (shouldWarn) {
3831                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3832             }
3833         }
3834         if (name == names.yield) {
3835             if (allowYieldStatement) {
3836                 return Source.JDK14;
3837             } else if (shouldWarn) {
3838                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3839             }
3840         }
3841         if (name == names.record) {
3842             if (allowRecords) {
3843                 return Source.JDK14;
3844             } else if (shouldWarn) {
3845                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3846             }
3847         }







3848         if (name == names.sealed) {
3849             if (allowSealedTypes) {
3850                 return Source.JDK15;
3851             } else if (shouldWarn) {
3852                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3853             }
3854         }
3855         if (name == names.permits) {
3856             if (allowSealedTypes) {
3857                 return Source.JDK15;
3858             } else if (shouldWarn) {
3859                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3860             }
3861         }
3862         return null;
3863     }
3864 
3865     /** VariableDeclaratorId = Ident BracketsOpt
3866      */
3867     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

4918             Token next = S.token(3);
4919             return allowedAfterSealedOrNonSealed(next, local, true);
4920         }
4921         return false;
4922     }
4923 
4924     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4925         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4926             Token tokenSub = S.token(lookAheadOffset + 1);
4927             Token tokenSealed = S.token(lookAheadOffset + 2);
4928             if (someToken.endPos == tokenSub.pos &&
4929                     tokenSub.endPos == tokenSealed.pos &&
4930                     tokenSealed.name() == names.sealed) {
4931                 checkSourceLevel(Feature.SEALED_CLASSES);
4932                 return true;
4933             }
4934         }
4935         return false;
4936     }
4937 


























4938     protected boolean isSealedClassStart(boolean local) {
4939         if (token.name() == names.sealed) {
4940             Token next = S.token(1);
4941             if (allowedAfterSealedOrNonSealed(next, local, false)) {
4942                 checkSourceLevel(Feature.SEALED_CLASSES);
4943                 return true;
4944             }
4945         }
4946         return false;
4947     }
4948 
4949     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4950         return local ?
4951             switch (next.kind) {
4952                 case MONKEYS_AT -> {
4953                     Token afterNext = S.token(2);
4954                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
4955                 }
4956                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4957                 default -> false;
4958             } :
4959             switch (next.kind) {
4960                 case MONKEYS_AT -> {
4961                     Token afterNext = S.token(2);
4962                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
4963                 }
4964                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4965                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;


4966                 default -> false;
4967             };
4968     }
4969 
4970     /** MethodDeclaratorRest =
4971      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4972      *  VoidMethodDeclaratorRest =
4973      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
4974      *  ConstructorDeclaratorRest =
4975      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4976      */
4977     protected JCTree methodDeclaratorRest(int pos,
4978                               JCModifiers mods,
4979                               JCExpression type,
4980                               Name name,
4981                               List<JCTypeParameter> typarams,
4982                               boolean isInterface, boolean isVoid,
4983                               boolean isRecord,
4984                               Comment dc) {
4985         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.Warnings;
  48 import com.sun.tools.javac.tree.*;
  49 import com.sun.tools.javac.tree.JCTree.*;
  50 import com.sun.tools.javac.util.*;
  51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  52 import com.sun.tools.javac.util.JCDiagnostic.Error;
  53 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  54 import com.sun.tools.javac.util.List;
  55 
  56 import static com.sun.tools.javac.code.Flags.asFlagSet;
  57 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  59 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  61 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  62 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  63 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  64 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  65 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
  66 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  67 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  68 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  70 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  71 
  72 /**
  73  * The parser maps a token sequence into an abstract syntax tree.
  74  * The parser is a hand-written recursive-descent parser that
  75  * implements the grammar described in the Java Language Specification.
  76  * For efficiency reasons, an operator precedence scheme is used
  77  * for parsing binary operation expressions.
  78  *
  79  *  <p><b>This is NOT part of any supported API.
  80  *  If you write code that depends on this, you do so at your own risk.
  81  *  This code and its internal interfaces are subject to change or
  82  *  deletion without notice.</b>
  83  */
  84 public class JavacParser implements Parser {
  85 

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

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

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

2975                     accept(SEMI);
2976                     return List.of(toP(F.at(pos).Yield(t)));
2977                 }
2978 
2979                 //else intentional fall-through
2980             } else {
2981                 if (isNonSealedClassStart(true)) {
2982                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2983                     nextToken();
2984                     nextToken();
2985                     nextToken();
2986                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2987                 } else if (isSealedClassStart(true)) {
2988                     checkSourceLevel(Feature.SEALED_CLASSES);
2989                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2990                     nextToken();
2991                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2992                 }
2993             }
2994         }
2995         if ((isValueModifier()) && allowValueClasses) {
2996             checkSourceLevel(Feature.VALUE_CLASSES);
2997             dc = token.docComment();
2998             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
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));

3577             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3578             case NATIVE      : flag = Flags.NATIVE; break;
3579             case VOLATILE    : flag = Flags.VOLATILE; break;
3580             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3581             case STRICTFP    : flag = Flags.STRICTFP; break;
3582             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3583             case DEFAULT     : flag = Flags.DEFAULT; break;
3584             case ERROR       : flag = 0; nextToken(); break;
3585             case IDENTIFIER  : {
3586                 if (isNonSealedClassStart(false)) {
3587                     flag = Flags.NON_SEALED;
3588                     nextToken();
3589                     nextToken();
3590                     break;
3591                 }
3592                 if (isSealedClassStart(false)) {
3593                     checkSourceLevel(Feature.SEALED_CLASSES);
3594                     flag = Flags.SEALED;
3595                     break;
3596                 }
3597                 if (isValueModifier()) {
3598                     checkSourceLevel(Feature.VALUE_CLASSES);
3599                     flag = Flags.VALUE_CLASS;
3600                     break;
3601                 }
3602                 break loop;
3603             }
3604             default: break loop;
3605             }
3606             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3607             lastPos = token.pos;
3608             nextToken();
3609             if (flag == Flags.ANNOTATION) {
3610                 if (token.kind != INTERFACE) {
3611                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3612                     // if first modifier is an annotation, set pos to annotation's.
3613                     if (flags == 0 && annotations.isEmpty())
3614                         pos = ann.pos;
3615                     annotations.append(ann);
3616                     flag = 0;
3617                 }
3618             }
3619             flags |= flag;
3620         }
3621         switch (token.kind) {

3850             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3851                 return Source.JDK10;
3852             } else if (shouldWarn) {
3853                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3854             }
3855         }
3856         if (name == names.yield) {
3857             if (allowYieldStatement) {
3858                 return Source.JDK14;
3859             } else if (shouldWarn) {
3860                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3861             }
3862         }
3863         if (name == names.record) {
3864             if (allowRecords) {
3865                 return Source.JDK14;
3866             } else if (shouldWarn) {
3867                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3868             }
3869         }
3870         if (name == names.value) {
3871             if (allowValueClasses) {
3872                 return Source.JDK23;
3873             } else if (shouldWarn) {
3874                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3875             }
3876         }
3877         if (name == names.sealed) {
3878             if (allowSealedTypes) {
3879                 return Source.JDK15;
3880             } else if (shouldWarn) {
3881                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3882             }
3883         }
3884         if (name == names.permits) {
3885             if (allowSealedTypes) {
3886                 return Source.JDK15;
3887             } else if (shouldWarn) {
3888                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3889             }
3890         }
3891         return null;
3892     }
3893 
3894     /** VariableDeclaratorId = Ident BracketsOpt
3895      */
3896     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

4947             Token next = S.token(3);
4948             return allowedAfterSealedOrNonSealed(next, local, true);
4949         }
4950         return false;
4951     }
4952 
4953     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4954         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4955             Token tokenSub = S.token(lookAheadOffset + 1);
4956             Token tokenSealed = S.token(lookAheadOffset + 2);
4957             if (someToken.endPos == tokenSub.pos &&
4958                     tokenSub.endPos == tokenSealed.pos &&
4959                     tokenSealed.name() == names.sealed) {
4960                 checkSourceLevel(Feature.SEALED_CLASSES);
4961                 return true;
4962             }
4963         }
4964         return false;
4965     }
4966 
4967     protected boolean isValueModifier() {
4968         if (token.kind == IDENTIFIER && token.name() == names.value) {
4969             boolean isValueModifier = false;
4970             Token next = S.token(1);
4971             switch (next.kind) {
4972                 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
4973                 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
4974                 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
4975                 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
4976                 case CLASS: case INTERFACE: case ENUM:
4977                     isValueModifier = true;
4978                     break;
4979                 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
4980                     if (next.name() == names.record || next.name() == names.value
4981                             || (mode & EXPR) != 0)
4982                         isValueModifier = true;
4983                     break;
4984             }
4985             if (isValueModifier) {
4986                 checkSourceLevel(Feature.VALUE_CLASSES);
4987                 return true;
4988             }
4989         }
4990         return false;
4991     }
4992 
4993     protected boolean isSealedClassStart(boolean local) {
4994         if (token.name() == names.sealed) {
4995             Token next = S.token(1);
4996             if (allowedAfterSealedOrNonSealed(next, local, false)) {
4997                 checkSourceLevel(Feature.SEALED_CLASSES);
4998                 return true;
4999             }
5000         }
5001         return false;
5002     }
5003 
5004     private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
5005         return local ?
5006             switch (next.kind) {
5007                 case MONKEYS_AT -> {
5008                     Token afterNext = S.token(2);
5009                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5010                 }
5011                 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5012                 default -> false;
5013             } :
5014             switch (next.kind) {
5015                 case MONKEYS_AT -> {
5016                     Token afterNext = S.token(2);
5017                     yield afterNext.kind != INTERFACE || currentIsNonSealed;
5018                 }
5019                 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
5020                 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
5021                         next.name() == names.sealed ||
5022                         allowValueClasses && next.name() == names.value;
5023                 default -> false;
5024             };
5025     }
5026 
5027     /** MethodDeclaratorRest =
5028      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5029      *  VoidMethodDeclaratorRest =
5030      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
5031      *  ConstructorDeclaratorRest =
5032      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5033      */
5034     protected JCTree methodDeclaratorRest(int pos,
5035                               JCModifiers mods,
5036                               JCExpression type,
5037                               Name name,
5038                               List<JCTypeParameter> typarams,
5039                               boolean isInterface, boolean isVoid,
5040                               boolean isRecord,
5041                               Comment dc) {
5042         if (isInterface) {
< prev index next >