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

 182                      boolean keepEndPositions,
 183                      boolean parseModuleInfo) {
 184         this.S = S;
 185         nextToken(); // prime the pump
 186         this.F = fac.F;
 187         this.log = fac.log;
 188         this.names = fac.names;
 189         this.source = fac.source;
 190         this.preview = fac.preview;
 191         this.deferredLintHandler = fac.deferredLintHandler;
 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.endPosTable = newEndPosTable(keepEndPositions);
 199         this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
 200         this.allowRecords = Feature.RECORDS.allowedInSource(source);
 201         this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);


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


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




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

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

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

2972                     accept(SEMI);
2973                     return List.of(toP(F.at(pos).Yield(t)));
2974                 }
2975 
2976                 //else intentional fall-through
2977             } else {
2978                 if (isNonSealedClassStart(true)) {
2979                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2980                     nextToken();
2981                     nextToken();
2982                     nextToken();
2983                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2984                 } else if (isSealedClassStart(true)) {
2985                     checkSourceLevel(Feature.SEALED_CLASSES);
2986                     log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2987                     nextToken();
2988                     return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2989                 }
2990             }
2991         }





2992         dc = token.docComment();
2993         if (isRecordStart() && allowRecords) {
2994             return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2995         } else {
2996             Token prevToken = token;
2997             JCExpression t = term(EXPR | TYPE);
2998             if (token.kind == COLON && t.hasTag(IDENT)) {
2999                 nextToken();
3000                 JCStatement stat = parseStatementAsBlock();
3001                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
3002             } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3003                 pos = token.pos;
3004                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3005                 F.at(pos);
3006                 return localVariableDeclarations(mods, t, dc);
3007             } else {
3008                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
3009                 t = checkExprStat(t);
3010                 accept(SEMI);
3011                 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                 break loop;
3598             }
3599             default: break loop;
3600             }
3601             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3602             lastPos = token.pos;
3603             nextToken();
3604             if (flag == Flags.ANNOTATION) {
3605                 if (token.kind != INTERFACE) {
3606                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3607                     // if first modifier is an annotation, set pos to annotation's.
3608                     if (flags == 0 && annotations.isEmpty())
3609                         pos = ann.pos;
3610                     annotations.append(ann);
3611                     flag = 0;
3612                 }
3613             }
3614             flags |= flag;
3615         }
3616         switch (token.kind) {

3845             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3846                 return Source.JDK10;
3847             } else if (shouldWarn) {
3848                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3849             }
3850         }
3851         if (name == names.yield) {
3852             if (allowYieldStatement) {
3853                 return Source.JDK14;
3854             } else if (shouldWarn) {
3855                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3856             }
3857         }
3858         if (name == names.record) {
3859             if (allowRecords) {
3860                 return Source.JDK14;
3861             } else if (shouldWarn) {
3862                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3863             }
3864         }







3865         if (name == names.sealed) {
3866             if (allowSealedTypes) {
3867                 return Source.JDK15;
3868             } else if (shouldWarn) {
3869                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3870             }
3871         }
3872         if (name == names.permits) {
3873             if (allowSealedTypes) {
3874                 return Source.JDK15;
3875             } else if (shouldWarn) {
3876                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3877             }
3878         }
3879         return null;
3880     }
3881 
3882     /** VariableDeclaratorId = Ident BracketsOpt
3883      */
3884     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {

4969             Token next = S.token(3);
4970             return allowedAfterSealedOrNonSealed(next, local, true);
4971         }
4972         return false;
4973     }
4974 
4975     protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4976         if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4977             Token tokenSub = S.token(lookAheadOffset + 1);
4978             Token tokenSealed = S.token(lookAheadOffset + 2);
4979             if (someToken.endPos == tokenSub.pos &&
4980                     tokenSub.endPos == tokenSealed.pos &&
4981                     tokenSealed.name() == names.sealed) {
4982                 checkSourceLevel(Feature.SEALED_CLASSES);
4983                 return true;
4984             }
4985         }
4986         return false;
4987     }
4988 


























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


5017                 default -> false;
5018             };
5019     }
5020 
5021     /** MethodDeclaratorRest =
5022      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
5023      *  VoidMethodDeclaratorRest =
5024      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
5025      *  ConstructorDeclaratorRest =
5026      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
5027      */
5028     protected JCTree methodDeclaratorRest(int pos,
5029                               JCModifiers mods,
5030                               JCExpression type,
5031                               Name name,
5032                               List<JCTypeParameter> typarams,
5033                               boolean isInterface, boolean isVoid,
5034                               boolean isRecord,
5035                               Comment dc) {
5036         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 com.sun.tools.javac.parser.VirtualParser.VirtualScanner;
  67 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  68 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
  70 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
  71 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
  72 
  73 /**
  74  * The parser maps a token sequence into an abstract syntax tree.
  75  * The parser is a hand-written recursive-descent parser that
  76  * implements the grammar described in the Java Language Specification.
  77  * For efficiency reasons, an operator precedence scheme is used
  78  * for parsing binary operation expressions.
  79  *
  80  *  <p><b>This is NOT part of any supported API.
  81  *  If you write code that depends on this, you do so at your own risk.
  82  *  This code and its internal interfaces are subject to change or
  83  *  deletion without notice.</b>
  84  */
  85 public class JavacParser implements Parser {

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

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

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

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

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

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

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