< prev index next >

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

Print this page




  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.stream.Collectors;
  31 
  32 import com.sun.source.tree.CaseTree.CaseKind;
  33 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  34 import com.sun.source.tree.ModuleTree.ModuleKind;
  35 
  36 import com.sun.tools.javac.code.*;
  37 import com.sun.tools.javac.code.Source.Feature;
  38 import com.sun.tools.javac.parser.Tokens.*;
  39 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  40 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  41 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  42 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  43 import com.sun.tools.javac.tree.*;
  44 import com.sun.tools.javac.tree.JCTree.*;
  45 import com.sun.tools.javac.util.*;
  46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  47 import com.sun.tools.javac.util.JCDiagnostic.Error;
  48 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  49 import com.sun.tools.javac.util.List;
  50 
  51 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  52 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  53 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  54 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  55 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  56 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  57 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  58 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  59 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  60 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  61 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;


  84 
  85     /** The scanner used for lexical analysis.
  86      */
  87     protected Lexer S;
  88 
  89     /** The factory to be used for abstract syntax tree construction.
  90      */
  91     protected TreeMaker F;
  92 
  93     /** The log to be used for error diagnostics.
  94      */
  95     private Log log;
  96 
  97     /** The Source language setting. */
  98     private Source source;
  99 
 100     /** The Preview language setting. */
 101     private Preview preview;
 102 
 103     /** The name table. */
 104     private Names names;
 105 
 106     /** End position mappings container */
 107     protected final AbstractEndPosTable endPosTable;
 108 


 109     // Because of javac's limited lookahead, some contexts are ambiguous in
 110     // the presence of type annotations even though they are not ambiguous
 111     // in the absence of type annotations.  Consider this code:
 112     //   void m(String [] m) { }
 113     //   void m(String ... m) { }
 114     // After parsing "String", javac calls bracketsOpt which immediately
 115     // returns if the next character is not '['.  Similarly, javac can see
 116     // if the next token is ... and in that case parse an ellipsis.  But in
 117     // the presence of type annotations:
 118     //   void m(String @A [] m) { }
 119     //   void m(String @A ... m) { }
 120     // no finite lookahead is enough to determine whether to read array
 121     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
 122     // bracketsOpt first reads all the leading annotations and only then
 123     // discovers that it needs to fail.  bracketsOpt needs a way to push
 124     // back the extra annotations that it read.  (But, bracketsOpt should
 125     // not *always* be allowed to push back extra annotations that it finds
 126     // -- in most contexts, any such extra annotation is an error.
 127     //
 128     // The following two variables permit type annotations that have


 167                      boolean keepDocComments,
 168                      boolean keepLineMap,
 169                      boolean keepEndPositions,
 170                      boolean parseModuleInfo) {
 171         this.S = S;
 172         nextToken(); // prime the pump
 173         this.F = fac.F;
 174         this.log = fac.log;
 175         this.names = fac.names;
 176         this.source = fac.source;
 177         this.preview = fac.preview;
 178         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 179         this.keepDocComments = keepDocComments;
 180         this.parseModuleInfo = parseModuleInfo;
 181         docComments = newDocCommentTable(keepDocComments, fac);
 182         this.keepLineMap = keepLineMap;
 183         this.errorTree = F.Erroneous();
 184         endPosTable = newEndPosTable(keepEndPositions);
 185         this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
 186                 Feature.SWITCH_EXPRESSION.allowedInSource(source);

 187     }
 188 
 189     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
 190         return  keepEndPositions
 191                 ? new SimpleEndPosTable(this)
 192                 : new EmptyEndPosTable(this);
 193     }
 194 
 195     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 196         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 197     }
 198 
 199     /** Switch: should we fold strings?
 200      */
 201     boolean allowStringFolding;
 202 
 203     /** Switch: should we keep docComments?
 204      */
 205     boolean keepDocComments;
 206 


 876             return t;
 877         }
 878     }
 879 
 880     /** Expression2   = Expression3 [Expression2Rest]
 881      *  Type2         = Type3
 882      *  TypeNoParams2 = TypeNoParams3
 883      */
 884     JCExpression term2() {
 885         JCExpression t = term3();
 886         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
 887             selectExprMode();
 888             return term2Rest(t, TreeInfo.orPrec);
 889         } else {
 890             return t;
 891         }
 892     }
 893 
 894     /*  Expression2Rest = {infixop Expression3}
 895      *                  | Expression3 instanceof Type

 896      *  infixop         = "||"
 897      *                  | "&&"
 898      *                  | "|"
 899      *                  | "^"
 900      *                  | "&"
 901      *                  | "==" | "!="
 902      *                  | "<" | ">" | "<=" | ">="
 903      *                  | "<<" | ">>" | ">>>"
 904      *                  | "+" | "-"
 905      *                  | "*" | "/" | "%"
 906      */
 907     JCExpression term2Rest(JCExpression t, int minprec) {
 908         JCExpression[] odStack = newOdStack();
 909         Token[] opStack = newOpStack();
 910 
 911         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
 912         int top = 0;
 913         odStack[0] = t;
 914         int startPos = token.pos;
 915         Token topOp = Tokens.DUMMY;
 916         while (prec(token.kind) >= minprec) {
 917             opStack[top] = topOp;
 918             top++;
 919             topOp = token;
 920             nextToken();
 921             odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();











 922             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
 923                 odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
 924                                         odStack[top]);
 925                 top--;
 926                 topOp = opStack[top];
 927             }
 928         }
 929         Assert.check(top == 0);
 930         t = odStack[0];
 931 
 932         if (t.hasTag(JCTree.Tag.PLUS)) {
 933             t = foldStrings(t);
 934         }
 935 
 936         odStackSupply.add(odStack);
 937         opStackSupply.add(opStack);
 938         return t;
 939     }
 940     //where
 941         /** Construct a binary or type test node.
 942          */
 943         private JCExpression makeOp(int pos,
 944                                     TokenKind topOp,
 945                                     JCExpression od1,
 946                                     JCExpression od2)
 947         {
 948             if (topOp == INSTANCEOF) {
 949                 return F.at(pos).TypeTest(od1, od2);
 950             } else {
 951                 return F.at(pos).Binary(optag(topOp), od1, od2);
 952             }
 953         }
 954         /** If tree is a concatenation of string literals, replace it
 955          *  by a single literal representing the concatenated string.
 956          */
 957         protected JCExpression foldStrings(JCExpression tree) {
 958             if (!allowStringFolding)
 959                 return tree;
 960             ListBuffer<JCExpression> opStack = new ListBuffer<>();
 961             ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
 962             boolean needsFolding = false;
 963             JCExpression curr = tree;
 964             while (true) {
 965                 if (curr.hasTag(JCTree.Tag.PLUS)) {
 966                     JCBinary op = (JCBinary)curr;
 967                     needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
 968                     curr = op.lhs;
 969                 } else {
 970                     needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
 971                     break; //last one!
 972                 }
 973             }


2383 
2384             if (elems != null) {
2385                 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2386             }
2387 
2388             return na;
2389         }
2390     }
2391 
2392     /** ClassCreatorRest = Arguments [ClassBody]
2393      */
2394     JCNewClass classCreatorRest(int newpos,
2395                                   JCExpression encl,
2396                                   List<JCExpression> typeArgs,
2397                                   JCExpression t)
2398     {
2399         List<JCExpression> args = arguments();
2400         JCClassDecl body = null;
2401         if (token.kind == LBRACE) {
2402             int pos = token.pos;
2403             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2404             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2405             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2406         }
2407         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2408     }
2409 
2410     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2411      */
2412     JCExpression arrayInitializer(int newpos, JCExpression t) {
2413         List<JCExpression> elems = arrayInitializerElements(newpos, t);
2414         return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2415     }
2416 
2417     List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2418         accept(LBRACE);
2419         ListBuffer<JCExpression> elems = new ListBuffer<>();
2420         if (token.kind == COMMA) {
2421             nextToken();
2422         } else if (token.kind != RBRACE) {
2423             elems.append(variableInitializer());


2518                 error = Errors.ClassNotAllowed;
2519                 break;
2520             case VARDEF:
2521                 error = Errors.VariableNotAllowed;
2522                 break;
2523             }
2524             if (error != null) {
2525                 log.error(DiagnosticFlag.SYNTAX, first, error);
2526                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
2527                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
2528             }
2529             return first;
2530         }
2531     }
2532 
2533     /**This method parses a statement appearing inside a block.
2534      */
2535     @SuppressWarnings("fallthrough")
2536     List<JCStatement> blockStatement() {
2537         //todo: skip to anchor on error(?)

2538         int pos = token.pos;
2539         switch (token.kind) {
2540         case RBRACE: case CASE: case DEFAULT: case EOF:
2541             return List.nil();
2542         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
2543         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
2544         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
2545         case ASSERT:
2546             return List.of(parseSimpleStatement());
2547         case MONKEYS_AT:
2548         case FINAL: {
2549             Comment dc = token.comment(CommentStyle.JAVADOC);
2550             JCModifiers mods = modifiersOpt();
2551             if (token.kind == INTERFACE ||
2552                 token.kind == CLASS ||
2553                 token.kind == ENUM) {
2554                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
2555             } else {
2556                 JCExpression t = parseType(true);
2557                 return localVariableDeclarations(mods, t);
2558             }
2559         }
2560         case ABSTRACT: case STRICTFP: {
2561             Comment dc = token.comment(CommentStyle.JAVADOC);
2562             JCModifiers mods = modifiersOpt();
2563             return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
2564         }
2565         case INTERFACE:
2566         case CLASS:
2567             Comment dc = token.comment(CommentStyle.JAVADOC);
2568             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2569         case ENUM:
2570             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
2571             dc = token.comment(CommentStyle.JAVADOC);
2572             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2573         case IDENTIFIER:
2574             if (token.name() == names.yield && allowYieldStatement) {
2575                 Token next = S.token(1);
2576                 boolean isYieldStatement;
2577                 switch (next.kind) {
2578                     case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
2579                     case INTLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
2580                     case NULL: case IDENTIFIER: case TRUE: case FALSE:
2581                     case NEW: case SWITCH: case THIS: case SUPER:
2582                         isYieldStatement = true;
2583                         break;
2584                     case PLUSPLUS: case SUBSUB:
2585                         isYieldStatement = S.token(2).kind != SEMI;
2586                         break;
2587                     case LPAREN:
2588                         int lookahead = 2;
2589                         int balance = 1;
2590                         boolean hasComma = false;
2591                         Token l;
2592                         while ((l = S.token(lookahead)).kind != EOF && balance != 0) {


2599                         }
2600                         isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
2601                         break;
2602                     case SEMI: //error recovery - this is not a valid statement:
2603                         isYieldStatement = true;
2604                         break;
2605                     default:
2606                         isYieldStatement = false;
2607                         break;
2608                 }
2609 
2610                 if (isYieldStatement) {
2611                     nextToken();
2612                     JCExpression t = term(EXPR);
2613                     accept(SEMI);
2614                     return List.of(toP(F.at(pos).Yield(t)));
2615                 }
2616 
2617                 //else intentional fall-through
2618             }
2619         default:







2620             Token prevToken = token;
2621             JCExpression t = term(EXPR | TYPE);
2622             if (token.kind == COLON && t.hasTag(IDENT)) {
2623                 nextToken();
2624                 JCStatement stat = parseStatementAsBlock();
2625                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2626             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
2627                 pos = token.pos;
2628                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2629                 F.at(pos);
2630                 return localVariableDeclarations(mods, t);
2631             } else {
2632                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2633                 t = checkExprStat(t);
2634                 accept(SEMI);
2635                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
2636                 return List.of(expr);
2637             }
2638         }
2639     }


3045         }
3046         int lastPos;
3047     loop:
3048         while (true) {
3049             long flag;
3050             switch (token.kind) {
3051             case PRIVATE     : flag = Flags.PRIVATE; break;
3052             case PROTECTED   : flag = Flags.PROTECTED; break;
3053             case PUBLIC      : flag = Flags.PUBLIC; break;
3054             case STATIC      : flag = Flags.STATIC; break;
3055             case TRANSIENT   : flag = Flags.TRANSIENT; break;
3056             case FINAL       : flag = Flags.FINAL; break;
3057             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3058             case NATIVE      : flag = Flags.NATIVE; break;
3059             case VOLATILE    : flag = Flags.VOLATILE; break;
3060             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3061             case STRICTFP    : flag = Flags.STRICTFP; break;
3062             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3063             case DEFAULT     : checkSourceLevel(Feature.DEFAULT_METHODS); flag = Flags.DEFAULT; break;
3064             case ERROR       : flag = 0; nextToken(); break;

















3065             default: break loop;
3066             }
3067             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3068             lastPos = token.pos;
3069             nextToken();
3070             if (flag == Flags.ANNOTATION) {
3071                 if (token.kind != INTERFACE) {
3072                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3073                     // if first modifier is an annotation, set pos to annotation's.
3074                     if (flags == 0 && annotations.isEmpty())
3075                         pos = ann.pos;
3076                     annotations.append(ann);
3077                     flag = 0;
3078                 }
3079             }
3080             flags |= flag;
3081         }
3082         switch (token.kind) {
3083         case ENUM: flags |= Flags.ENUM; break;
3084         case INTERFACE: flags |= Flags.INTERFACE; break;


3289     }
3290 
3291     boolean isRestrictedTypeName(Name name, int pos, boolean shouldWarn) {
3292         if (name == names.var) {
3293             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3294                 return true;
3295             } else if (shouldWarn) {
3296                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3297             }
3298         }
3299         if (name == names.yield) {
3300             if (allowYieldStatement) {
3301                 return true;
3302             } else if (shouldWarn) {
3303                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK13));
3304             }
3305         }
3306         return false;
3307     }
3308 




3309     /** VariableDeclaratorId = Ident BracketsOpt
3310      */
3311     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
3312         return variableDeclaratorId(mods, type, false);
3313     }
3314     //where
3315     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
3316         int pos = token.pos;
3317         Name name;
3318         if (lambdaParameter && token.kind == UNDERSCORE) {
3319             log.error(pos, Errors.UnderscoreAsIdentifierInLambda);
3320             name = token.name();
3321             nextToken();
3322         } else {
3323             if (allowThisIdent ||
3324                 !lambdaParameter ||
3325                 LAX_IDENTIFIER.accepts(token.kind) ||
3326                 mods.flags != Flags.PARAMETER ||
3327                 mods.annotations.nonEmpty()) {
3328                 JCExpression pn = qualident(false);


3610                 pid = to(F.at(pos1).Select(pid, names.asterisk));
3611                 nextToken();
3612                 break;
3613             } else {
3614                 pid = toP(F.at(pos1).Select(pid, ident()));
3615             }
3616         } while (token.kind == DOT);
3617         accept(SEMI);
3618         return toP(F.at(pos).Import(pid, importStatic));
3619     }
3620 
3621     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
3622      *                  | ";"
3623      */
3624     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
3625         int pos = token.pos;
3626         if (mods == null && token.kind == SEMI) {
3627             nextToken();
3628             return toP(F.at(pos).Skip());
3629         } else {
3630             return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
3631         }
3632     }
3633 
3634     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
3635      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
3636      *  @param mods     Any modifiers starting the class or interface declaration
3637      *  @param dc       The documentation comment for the class, or null.
3638      */
3639     protected JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
3640         if (token.kind == CLASS) {
3641             return classDeclaration(mods, dc);


3642         } else if (token.kind == INTERFACE) {
3643             return interfaceDeclaration(mods, dc);
3644         } else if (token.kind == ENUM) {
3645             return enumDeclaration(mods, dc);
3646         } else {
3647             int pos = token.pos;
3648             List<JCTree> errs;
3649             if (LAX_IDENTIFIER.accepts(token.kind)) {
3650                 errs = List.of(mods, toP(F.at(pos).Ident(ident())));
3651                 setErrorEndPos(token.pos);
3652             } else {
3653                 errs = List.of(mods);
3654             }
3655             final JCErroneous erroneousTree;
3656             if (parseModuleInfo) {
3657                 erroneousTree = syntaxError(pos, errs, Errors.ExpectedModuleOrOpen);
3658             } else {
3659                 erroneousTree = syntaxError(pos, errs, Errors.Expected3(CLASS, INTERFACE, ENUM));
3660             }
3661             return toP(F.Exec(erroneousTree));
3662         }
3663     }
3664 
3665     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
3666      *                     [IMPLEMENTS TypeList] ClassBody
3667      *  @param mods    The modifiers starting the class declaration
3668      *  @param dc       The documentation comment for the class, or null.
3669      */
3670     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
3671         int pos = token.pos;
3672         accept(CLASS);
3673         Name name = typeName();
3674 
3675         List<JCTypeParameter> typarams = typeParametersOpt();
3676 
3677         JCExpression extending = null;
3678         if (token.kind == EXTENDS) {
3679             nextToken();
3680             extending = parseType();
3681         }
3682         List<JCExpression> implementing = List.nil();
3683         if (token.kind == IMPLEMENTS) {
3684             nextToken();
3685             implementing = typeList();
3686         }
3687         List<JCTree> defs = classOrInterfaceBody(name, false);








3688         JCClassDecl result = toP(F.at(pos).ClassDef(
3689             mods, name, typarams, extending, implementing, defs));





















































3690         attach(result, dc);
3691         return result;
3692     }
3693 
3694     Name typeName() {
3695         int pos = token.pos;
3696         Name name = ident();
3697         if (isRestrictedTypeName(name, pos, true)) {
3698             reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, name == names.var ? Source.JDK10 : Source.JDK13));
3699         }




3700         return name;
3701     }
3702 


































3703     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
3704      *                         [EXTENDS TypeList] InterfaceBody
3705      *  @param mods    The modifiers starting the interface declaration
3706      *  @param dc       The documentation comment for the interface, or null.
3707      */
3708     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
3709         int pos = token.pos;
3710         accept(INTERFACE);
3711 
3712         Name name = typeName();
3713 
3714         List<JCTypeParameter> typarams = typeParametersOpt();
3715 
3716         List<JCExpression> extending = List.nil();
3717         if (token.kind == EXTENDS) {
3718             nextToken();
3719             extending = typeList();
3720         }
3721         List<JCTree> defs = classOrInterfaceBody(name, true);









3722         JCClassDecl result = toP(F.at(pos).ClassDef(
3723             mods, name, typarams, null, extending, defs));
3724         attach(result, dc);
3725         return result;
3726     }
3727 
3728     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
3729      *  @param mods    The modifiers starting the enum declaration
3730      *  @param dc       The documentation comment for the enum, or null.
3731      */
3732     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
3733         int pos = token.pos;
3734         accept(ENUM);
3735 
3736         Name name = typeName();
3737 
3738         List<JCExpression> implementing = List.nil();
3739         if (token.kind == IMPLEMENTS) {
3740             nextToken();
3741             implementing = typeList();
3742         }
3743 


3756     List<JCTree> enumBody(Name enumName) {
3757         accept(LBRACE);
3758         ListBuffer<JCTree> defs = new ListBuffer<>();
3759         if (token.kind == COMMA) {
3760             nextToken();
3761         } else if (token.kind != RBRACE && token.kind != SEMI) {
3762             defs.append(enumeratorDeclaration(enumName));
3763             while (token.kind == COMMA) {
3764                 nextToken();
3765                 if (token.kind == RBRACE || token.kind == SEMI) break;
3766                 defs.append(enumeratorDeclaration(enumName));
3767             }
3768             if (token.kind != SEMI && token.kind != RBRACE) {
3769                 defs.append(syntaxError(token.pos, Errors.Expected3(COMMA, RBRACE, SEMI)));
3770                 nextToken();
3771             }
3772         }
3773         if (token.kind == SEMI) {
3774             nextToken();
3775             while (token.kind != RBRACE && token.kind != EOF) {
3776                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
3777                                                                 false));
3778                 if (token.pos <= endPosTable.errorEndPos) {
3779                     // error recovery
3780                    skip(false, true, true, false);
3781                 }
3782             }
3783         }
3784         accept(RBRACE);
3785         return defs.toList();
3786     }
3787 
3788     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
3789      */
3790     JCTree enumeratorDeclaration(Name enumName) {
3791         Comment dc = token.comment(CommentStyle.JAVADOC);
3792         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
3793         if (token.deprecatedFlag()) {
3794             flags |= Flags.DEPRECATED;
3795         }
3796         int pos = token.pos;
3797         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
3798         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
3799         List<JCExpression> typeArgs = typeArgumentsOpt();
3800         int identPos = token.pos;
3801         Name name = ident();
3802         int createPos = token.pos;
3803         List<JCExpression> args = (token.kind == LPAREN)
3804             ? arguments() : List.nil();
3805         JCClassDecl body = null;
3806         if (token.kind == LBRACE) {
3807             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM);
3808             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
3809             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
3810         }
3811         if (args.isEmpty() && body == null)
3812             createPos = identPos;
3813         JCIdent ident = F.at(identPos).Ident(enumName);
3814         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
3815         if (createPos != identPos)
3816             storeEnd(create, S.prevToken().endPos);
3817         ident = F.at(identPos).Ident(enumName);
3818         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
3819         attach(result, dc);
3820         return result;
3821     }
3822 
3823     /** TypeList = Type {"," Type}
3824      */
3825     List<JCExpression> typeList() {
3826         ListBuffer<JCExpression> ts = new ListBuffer<>();
3827         ts.append(parseType());
3828         while (token.kind == COMMA) {
3829             nextToken();
3830             ts.append(parseType());
3831         }
3832         return ts.toList();
3833     }
3834 
3835     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
3836      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
3837      */
3838     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
3839         accept(LBRACE);
3840         if (token.pos <= endPosTable.errorEndPos) {
3841             // error recovery
3842             skip(false, true, false, false);
3843             if (token.kind == LBRACE)
3844                 nextToken();
3845         }
3846         ListBuffer<JCTree> defs = new ListBuffer<>();
3847         while (token.kind != RBRACE && token.kind != EOF) {
3848             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
3849             if (token.pos <= endPosTable.errorEndPos) {
3850                // error recovery
3851                skip(false, true, true, false);
3852            }
3853         }
3854         accept(RBRACE);
3855         return defs.toList();
3856     }
3857 
3858     /** ClassBodyDeclaration =
3859      *      ";"
3860      *    | [STATIC] Block
3861      *    | ModifiersOpt
3862      *      ( Type Ident
3863      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
3864      *      | VOID Ident VoidMethodDeclaratorRest
3865      *      | TypeParameters [Annotations]
3866      *        ( Type Ident MethodDeclaratorRest
3867      *        | VOID Ident VoidMethodDeclaratorRest
3868      *        )
3869      *      | Ident ConstructorDeclaratorRest
3870      *      | TypeParameters Ident ConstructorDeclaratorRest
3871      *      | ClassOrInterfaceOrEnumDeclaration
3872      *      )
3873      *  InterfaceBodyDeclaration =
3874      *      ";"
3875      *    | ModifiersOpt
3876      *      ( Type Ident
3877      *        ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
3878      *      | VOID Ident MethodDeclaratorRest
3879      *      | TypeParameters [Annotations]
3880      *        ( Type Ident MethodDeclaratorRest
3881      *        | VOID Ident VoidMethodDeclaratorRest
3882      *        )
3883      *      | ClassOrInterfaceOrEnumDeclaration
3884      *      )
3885      *
3886      */
3887     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
3888         if (token.kind == SEMI) {
3889             nextToken();
3890             return List.nil();
3891         } else {
3892             Comment dc = token.comment(CommentStyle.JAVADOC);
3893             int pos = token.pos;
3894             JCModifiers mods = modifiersOpt();



3895             if (token.kind == CLASS ||

3896                 token.kind == INTERFACE ||
3897                 token.kind == ENUM) {
3898                 return List.of(classOrInterfaceOrEnumDeclaration(mods, dc));
3899             } else if (token.kind == LBRACE &&
3900                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
3901                        mods.annotations.isEmpty()) {
3902                 if (isInterface) {
3903                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
3904                 }
3905                 return List.of(block(pos, mods.flags));
3906             } else {
3907                 pos = token.pos;
3908                 List<JCTypeParameter> typarams = typeParametersOpt();
3909                 // if there are type parameters but no modifiers, save the start
3910                 // position of the method in the modifiers.
3911                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
3912                     mods.pos = pos;
3913                     storeEnd(mods, pos);
3914                 }
3915                 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
3916 
3917                 if (annosAfterParams.nonEmpty()) {
3918                     checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS);
3919                     mods.annotations = mods.annotations.appendList(annosAfterParams);
3920                     if (mods.pos == Position.NOPOS)
3921                         mods.pos = mods.annotations.head.pos;
3922                 }
3923 
3924                 Token tk = token;
3925                 pos = token.pos;
3926                 JCExpression type;
3927                 boolean isVoid = token.kind == VOID;
3928                 if (isVoid) {
3929                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
3930                     nextToken();
3931                 } else {
3932                     // method returns types are un-annotated types
3933                     type = unannotatedType(false);
3934                 }
3935                 if (token.kind == LPAREN && !isInterface && type.hasTag(IDENT)) {

3936                     if (isInterface || tk.name() != className)
3937                         log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
3938                     else if (annosAfterParams.nonEmpty())
3939                         illegal(annosAfterParams.head.pos);
3940                     return List.of(methodDeclaratorRest(
3941                         pos, mods, null, names.init, typarams,
3942                         isInterface, true, dc));
3943                 } else {
3944                     pos = token.pos;
3945                     Name name = ident();
3946                     if (token.kind == LPAREN) {
3947                         return List.of(methodDeclaratorRest(
3948                             pos, mods, type, name, typarams,
3949                             isInterface, isVoid, dc));
3950                     } else if (!isVoid && typarams.isEmpty()) {
3951                         List<JCTree> defs =
3952                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
3953                                                     new ListBuffer<JCTree>(), false).toList();
3954                         accept(SEMI);
3955                         storeEnd(defs.last(), S.prevToken().endPos);
3956                         return defs;





3957                     } else {
3958                         pos = token.pos;
3959                         List<JCTree> err;
3960                         if (isVoid || typarams.nonEmpty()) {
3961                             JCMethodDecl m =
3962                                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
3963                                                             List.nil(), List.nil(), null, null));
3964                             attach(m, dc);
3965                             err = List.of(m);
3966                         } else {
3967                             err = List.nil();
3968                         }
3969                         return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
3970                     }
3971                 }
3972             }
3973         }
3974     }
3975 




3976     /** MethodDeclaratorRest =
3977      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
3978      *  VoidMethodDeclaratorRest =
3979      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
3980      *  ConstructorDeclaratorRest =
3981      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
3982      */
3983     protected JCTree methodDeclaratorRest(int pos,
3984                               JCModifiers mods,
3985                               JCExpression type,
3986                               Name name,
3987                               List<JCTypeParameter> typarams,
3988                               boolean isInterface, boolean isVoid,

3989                               Comment dc) {
3990         if (isInterface) {
3991             if ((mods.flags & Flags.STATIC) != 0) {
3992                 checkSourceLevel(Feature.STATIC_INTERFACE_METHODS);
3993             }
3994             if ((mods.flags & Flags.PRIVATE) != 0) {
3995                 checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
3996             }
3997         }
3998         JCVariableDecl prevReceiverParam = this.receiverParam;
3999         try {
4000             this.receiverParam = null;
4001             // Parsing formalParameters sets the receiverParam, if present
4002             List<JCVariableDecl> params = formalParameters();
4003             if (!isVoid) type = bracketsOpt(type);
4004             List<JCExpression> thrown = List.nil();
4005             if (token.kind == THROWS) {
4006                 nextToken();
4007                 thrown = qualidentList(true);




4008             }
4009             JCBlock body = null;
4010             JCExpression defaultValue;
4011             if (token.kind == LBRACE) {
4012                 body = block();
4013                 defaultValue = null;
4014             } else {
4015                 if (token.kind == DEFAULT) {
4016                     accept(DEFAULT);
4017                     defaultValue = annotationValue();
4018                 } else {
4019                     defaultValue = null;
4020                 }
4021                 accept(SEMI);
4022                 if (token.pos <= endPosTable.errorEndPos) {
4023                     // error recovery
4024                     skip(false, true, false, false);
4025                     if (token.kind == LBRACE) {
4026                         body = block();
4027                     }
4028                 }
4029             }
4030 
4031             JCMethodDecl result =
4032                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
4033                                             receiverParam, params, thrown,
4034                                             body, defaultValue));
4035             attach(result, dc);
4036             return result;
4037         } finally {
4038             this.receiverParam = prevReceiverParam;
4039         }
4040     }
4041 
4042     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
4043      */
4044     List<JCExpression> qualidentList(boolean allowAnnos) {
4045         ListBuffer<JCExpression> ts = new ListBuffer<>();
4046 
4047         List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
4048         JCExpression qi = qualident(allowAnnos);
4049         if (!typeAnnos.isEmpty()) {
4050             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);




  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.stream.Collectors;
  31 
  32 import com.sun.source.tree.CaseTree.CaseKind;
  33 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  34 import com.sun.source.tree.ModuleTree.ModuleKind;
  35 
  36 import com.sun.tools.javac.code.*;
  37 import com.sun.tools.javac.code.Source.Feature;
  38 import com.sun.tools.javac.parser.Tokens.*;
  39 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
  40 import com.sun.tools.javac.resources.CompilerProperties.Errors;

  41 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  42 import com.sun.tools.javac.tree.*;
  43 import com.sun.tools.javac.tree.JCTree.*;
  44 import com.sun.tools.javac.util.*;
  45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  46 import com.sun.tools.javac.util.JCDiagnostic.Error;
  47 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  48 import com.sun.tools.javac.util.List;
  49 
  50 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
  51 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
  52 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
  53 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
  54 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
  55 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
  56 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
  57 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
  58 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  59 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
  60 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;


  83 
  84     /** The scanner used for lexical analysis.
  85      */
  86     protected Lexer S;
  87 
  88     /** The factory to be used for abstract syntax tree construction.
  89      */
  90     protected TreeMaker F;
  91 
  92     /** The log to be used for error diagnostics.
  93      */
  94     private Log log;
  95 
  96     /** The Source language setting. */
  97     private Source source;
  98 
  99     /** The Preview language setting. */
 100     private Preview preview;
 101 
 102     /** The name table. */
 103     protected Names names;
 104 
 105     /** End position mappings container */
 106     protected final AbstractEndPosTable endPosTable;
 107 
 108     private final boolean debug;
 109 
 110     // Because of javac's limited lookahead, some contexts are ambiguous in
 111     // the presence of type annotations even though they are not ambiguous
 112     // in the absence of type annotations.  Consider this code:
 113     //   void m(String [] m) { }
 114     //   void m(String ... m) { }
 115     // After parsing "String", javac calls bracketsOpt which immediately
 116     // returns if the next character is not '['.  Similarly, javac can see
 117     // if the next token is ... and in that case parse an ellipsis.  But in
 118     // the presence of type annotations:
 119     //   void m(String @A [] m) { }
 120     //   void m(String @A ... m) { }
 121     // no finite lookahead is enough to determine whether to read array
 122     // levels or an ellipsis.  Furthermore, if you call bracketsOpt, then
 123     // bracketsOpt first reads all the leading annotations and only then
 124     // discovers that it needs to fail.  bracketsOpt needs a way to push
 125     // back the extra annotations that it read.  (But, bracketsOpt should
 126     // not *always* be allowed to push back extra annotations that it finds
 127     // -- in most contexts, any such extra annotation is an error.
 128     //
 129     // The following two variables permit type annotations that have


 168                      boolean keepDocComments,
 169                      boolean keepLineMap,
 170                      boolean keepEndPositions,
 171                      boolean parseModuleInfo) {
 172         this.S = S;
 173         nextToken(); // prime the pump
 174         this.F = fac.F;
 175         this.log = fac.log;
 176         this.names = fac.names;
 177         this.source = fac.source;
 178         this.preview = fac.preview;
 179         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
 180         this.keepDocComments = keepDocComments;
 181         this.parseModuleInfo = parseModuleInfo;
 182         docComments = newDocCommentTable(keepDocComments, fac);
 183         this.keepLineMap = keepLineMap;
 184         this.errorTree = F.Erroneous();
 185         endPosTable = newEndPosTable(keepEndPositions);
 186         this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
 187                 Feature.SWITCH_EXPRESSION.allowedInSource(source);
 188         debug = fac.options.isSet("debug");
 189     }
 190 
 191     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
 192         return  keepEndPositions
 193                 ? new SimpleEndPosTable(this)
 194                 : new EmptyEndPosTable(this);
 195     }
 196 
 197     protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
 198         return keepDocComments ? new LazyDocCommentTable(fac) : null;
 199     }
 200 
 201     /** Switch: should we fold strings?
 202      */
 203     boolean allowStringFolding;
 204 
 205     /** Switch: should we keep docComments?
 206      */
 207     boolean keepDocComments;
 208 


 878             return t;
 879         }
 880     }
 881 
 882     /** Expression2   = Expression3 [Expression2Rest]
 883      *  Type2         = Type3
 884      *  TypeNoParams2 = TypeNoParams3
 885      */
 886     JCExpression term2() {
 887         JCExpression t = term3();
 888         if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
 889             selectExprMode();
 890             return term2Rest(t, TreeInfo.orPrec);
 891         } else {
 892             return t;
 893         }
 894     }
 895 
 896     /*  Expression2Rest = {infixop Expression3}
 897      *                  | Expression3 instanceof Type
 898      *                  | Expression3 instanceof Pattern
 899      *  infixop         = "||"
 900      *                  | "&&"
 901      *                  | "|"
 902      *                  | "^"
 903      *                  | "&"
 904      *                  | "==" | "!="
 905      *                  | "<" | ">" | "<=" | ">="
 906      *                  | "<<" | ">>" | ">>>"
 907      *                  | "+" | "-"
 908      *                  | "*" | "/" | "%"
 909      */
 910     JCExpression term2Rest(JCExpression t, int minprec) {
 911         JCExpression[] odStack = newOdStack();
 912         Token[] opStack = newOpStack();
 913 
 914         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
 915         int top = 0;
 916         odStack[0] = t;
 917         int startPos = token.pos;
 918         Token topOp = Tokens.DUMMY;
 919         while (prec(token.kind) >= minprec) {
 920             opStack[top] = topOp;
 921 
 922             if (token.kind == INSTANCEOF) {
 923                 int pos = token.pos;
 924                 nextToken();
 925                 JCTree pattern = parseType();
 926                 if (token.kind == IDENTIFIER) {
 927                     pattern = toP(F.at(token.pos).BindingPattern(ident(), pattern));
 928                 }
 929                 odStack[top] = F.at(pos).TypeTest(odStack[top], pattern);
 930             } else {
 931                 topOp = token;
 932                 nextToken();
 933                 top++;
 934                 odStack[top] = term3();
 935             }
 936             while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
 937                 odStack[top - 1] = F.at(topOp.pos).Binary(optag(topOp.kind), odStack[top - 1], odStack[top]);

 938                 top--;
 939                 topOp = opStack[top];
 940             }
 941         }
 942         Assert.check(top == 0);
 943         t = odStack[0];
 944 
 945         if (t.hasTag(JCTree.Tag.PLUS)) {
 946             t = foldStrings(t);
 947         }
 948 
 949         odStackSupply.add(odStack);
 950         opStackSupply.add(opStack);
 951         return t;
 952     }
 953     //where













 954         /** If tree is a concatenation of string literals, replace it
 955          *  by a single literal representing the concatenated string.
 956          */
 957         protected JCExpression foldStrings(JCExpression tree) {
 958             if (!allowStringFolding)
 959                 return tree;
 960             ListBuffer<JCExpression> opStack = new ListBuffer<>();
 961             ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
 962             boolean needsFolding = false;
 963             JCExpression curr = tree;
 964             while (true) {
 965                 if (curr.hasTag(JCTree.Tag.PLUS)) {
 966                     JCBinary op = (JCBinary)curr;
 967                     needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
 968                     curr = op.lhs;
 969                 } else {
 970                     needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
 971                     break; //last one!
 972                 }
 973             }


2383 
2384             if (elems != null) {
2385                 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2386             }
2387 
2388             return na;
2389         }
2390     }
2391 
2392     /** ClassCreatorRest = Arguments [ClassBody]
2393      */
2394     JCNewClass classCreatorRest(int newpos,
2395                                   JCExpression encl,
2396                                   List<JCExpression> typeArgs,
2397                                   JCExpression t)
2398     {
2399         List<JCExpression> args = arguments();
2400         JCClassDecl body = null;
2401         if (token.kind == LBRACE) {
2402             int pos = token.pos;
2403             List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2404             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2405             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2406         }
2407         return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2408     }
2409 
2410     /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2411      */
2412     JCExpression arrayInitializer(int newpos, JCExpression t) {
2413         List<JCExpression> elems = arrayInitializerElements(newpos, t);
2414         return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2415     }
2416 
2417     List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2418         accept(LBRACE);
2419         ListBuffer<JCExpression> elems = new ListBuffer<>();
2420         if (token.kind == COMMA) {
2421             nextToken();
2422         } else if (token.kind != RBRACE) {
2423             elems.append(variableInitializer());


2518                 error = Errors.ClassNotAllowed;
2519                 break;
2520             case VARDEF:
2521                 error = Errors.VariableNotAllowed;
2522                 break;
2523             }
2524             if (error != null) {
2525                 log.error(DiagnosticFlag.SYNTAX, first, error);
2526                 List<JCBlock> blist = List.of(F.at(first.pos).Block(0, stats));
2527                 return toP(F.at(pos).Exec(F.at(first.pos).Erroneous(blist)));
2528             }
2529             return first;
2530         }
2531     }
2532 
2533     /**This method parses a statement appearing inside a block.
2534      */
2535     @SuppressWarnings("fallthrough")
2536     List<JCStatement> blockStatement() {
2537         //todo: skip to anchor on error(?)
2538         Comment dc;
2539         int pos = token.pos;
2540         switch (token.kind) {
2541         case RBRACE: case CASE: case DEFAULT: case EOF:
2542             return List.nil();
2543         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
2544         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
2545         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
2546         case ASSERT:
2547             return List.of(parseSimpleStatement());
2548         case MONKEYS_AT:
2549         case FINAL: {
2550             dc = token.comment(CommentStyle.JAVADOC);
2551             JCModifiers mods = modifiersOpt();
2552             if (token.kind == INTERFACE ||
2553                 token.kind == CLASS ||
2554                 token.kind == ENUM) {
2555                 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2556             } else {
2557                 JCExpression t = parseType(true);
2558                 return localVariableDeclarations(mods, t);
2559             }
2560         }
2561         case ABSTRACT: case STRICTFP: {
2562             dc = token.comment(CommentStyle.JAVADOC);
2563             JCModifiers mods = modifiersOpt();
2564             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
2565         }
2566         case INTERFACE:
2567         case CLASS:
2568             dc = token.comment(CommentStyle.JAVADOC);
2569             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2570         case ENUM:
2571             log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
2572             dc = token.comment(CommentStyle.JAVADOC);
2573             return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2574         case IDENTIFIER:
2575             if (token.name() == names.yield && allowYieldStatement) {
2576                 Token next = S.token(1);
2577                 boolean isYieldStatement;
2578                 switch (next.kind) {
2579                     case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
2580                     case INTLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
2581                     case NULL: case IDENTIFIER: case TRUE: case FALSE:
2582                     case NEW: case SWITCH: case THIS: case SUPER:
2583                         isYieldStatement = true;
2584                         break;
2585                     case PLUSPLUS: case SUBSUB:
2586                         isYieldStatement = S.token(2).kind != SEMI;
2587                         break;
2588                     case LPAREN:
2589                         int lookahead = 2;
2590                         int balance = 1;
2591                         boolean hasComma = false;
2592                         Token l;
2593                         while ((l = S.token(lookahead)).kind != EOF && balance != 0) {


2600                         }
2601                         isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
2602                         break;
2603                     case SEMI: //error recovery - this is not a valid statement:
2604                         isYieldStatement = true;
2605                         break;
2606                     default:
2607                         isYieldStatement = false;
2608                         break;
2609                 }
2610 
2611                 if (isYieldStatement) {
2612                     nextToken();
2613                     JCExpression t = term(EXPR);
2614                     accept(SEMI);
2615                     return List.of(toP(F.at(pos).Yield(t)));
2616                 }
2617 
2618                 //else intentional fall-through
2619             }
2620         }
2621         if (isRecordToken() &&
2622             (peekToken(TokenKind.IDENTIFIER, TokenKind.LPAREN) ||
2623              peekToken(TokenKind.IDENTIFIER, TokenKind.LT))) {
2624             JCModifiers mods = modifiersOpt();
2625             dc = token.comment(CommentStyle.JAVADOC);
2626             return List.of(recordDeclaration(mods, dc));
2627         } else {
2628             Token prevToken = token;
2629             JCExpression t = term(EXPR | TYPE);
2630             if (token.kind == COLON && t.hasTag(IDENT)) {
2631                 nextToken();
2632                 JCStatement stat = parseStatementAsBlock();
2633                 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2634             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
2635                 pos = token.pos;
2636                 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2637                 F.at(pos);
2638                 return localVariableDeclarations(mods, t);
2639             } else {
2640                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2641                 t = checkExprStat(t);
2642                 accept(SEMI);
2643                 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
2644                 return List.of(expr);
2645             }
2646         }
2647     }


3053         }
3054         int lastPos;
3055     loop:
3056         while (true) {
3057             long flag;
3058             switch (token.kind) {
3059             case PRIVATE     : flag = Flags.PRIVATE; break;
3060             case PROTECTED   : flag = Flags.PROTECTED; break;
3061             case PUBLIC      : flag = Flags.PUBLIC; break;
3062             case STATIC      : flag = Flags.STATIC; break;
3063             case TRANSIENT   : flag = Flags.TRANSIENT; break;
3064             case FINAL       : flag = Flags.FINAL; break;
3065             case ABSTRACT    : flag = Flags.ABSTRACT; break;
3066             case NATIVE      : flag = Flags.NATIVE; break;
3067             case VOLATILE    : flag = Flags.VOLATILE; break;
3068             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3069             case STRICTFP    : flag = Flags.STRICTFP; break;
3070             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
3071             case DEFAULT     : checkSourceLevel(Feature.DEFAULT_METHODS); flag = Flags.DEFAULT; break;
3072             case ERROR       : flag = 0; nextToken(); break;
3073             case IDENTIFIER  : {
3074                 if (token.name() == names.non && peekToken(0, TokenKind.SUB, TokenKind.IDENTIFIER)) {
3075                     Token tokenSub = S.token(1);
3076                     Token tokenSealed = S.token(2);
3077                     if (token.endPos == tokenSub.pos && tokenSub.endPos == tokenSealed.pos && tokenSealed.name() == names.sealed) {
3078                         flag = Flags.NON_SEALED;
3079                         nextToken();
3080                         nextToken();
3081                         break;
3082                     }
3083                 }
3084                 if (token.name() == names.sealed) {
3085                     flag = Flags.SEALED;
3086                     break;
3087                 }
3088                 break loop;
3089             }
3090             default: break loop;
3091             }
3092             if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3093             lastPos = token.pos;
3094             nextToken();
3095             if (flag == Flags.ANNOTATION) {
3096                 if (token.kind != INTERFACE) {
3097                     JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3098                     // if first modifier is an annotation, set pos to annotation's.
3099                     if (flags == 0 && annotations.isEmpty())
3100                         pos = ann.pos;
3101                     annotations.append(ann);
3102                     flag = 0;
3103                 }
3104             }
3105             flags |= flag;
3106         }
3107         switch (token.kind) {
3108         case ENUM: flags |= Flags.ENUM; break;
3109         case INTERFACE: flags |= Flags.INTERFACE; break;


3314     }
3315 
3316     boolean isRestrictedTypeName(Name name, int pos, boolean shouldWarn) {
3317         if (name == names.var) {
3318             if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3319                 return true;
3320             } else if (shouldWarn) {
3321                 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3322             }
3323         }
3324         if (name == names.yield) {
3325             if (allowYieldStatement) {
3326                 return true;
3327             } else if (shouldWarn) {
3328                 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK13));
3329             }
3330         }
3331         return false;
3332     }
3333 
3334     boolean isRestrictedRecordTypeName(Name name) {
3335         return Feature.RECORDS.allowedInSource(source) && name == names.record;
3336     }
3337 
3338     /** VariableDeclaratorId = Ident BracketsOpt
3339      */
3340     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
3341         return variableDeclaratorId(mods, type, false);
3342     }
3343     //where
3344     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean lambdaParameter) {
3345         int pos = token.pos;
3346         Name name;
3347         if (lambdaParameter && token.kind == UNDERSCORE) {
3348             log.error(pos, Errors.UnderscoreAsIdentifierInLambda);
3349             name = token.name();
3350             nextToken();
3351         } else {
3352             if (allowThisIdent ||
3353                 !lambdaParameter ||
3354                 LAX_IDENTIFIER.accepts(token.kind) ||
3355                 mods.flags != Flags.PARAMETER ||
3356                 mods.annotations.nonEmpty()) {
3357                 JCExpression pn = qualident(false);


3639                 pid = to(F.at(pos1).Select(pid, names.asterisk));
3640                 nextToken();
3641                 break;
3642             } else {
3643                 pid = toP(F.at(pos1).Select(pid, ident()));
3644             }
3645         } while (token.kind == DOT);
3646         accept(SEMI);
3647         return toP(F.at(pos).Import(pid, importStatic));
3648     }
3649 
3650     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
3651      *                  | ";"
3652      */
3653     JCTree typeDeclaration(JCModifiers mods, Comment docComment) {
3654         int pos = token.pos;
3655         if (mods == null && token.kind == SEMI) {
3656             nextToken();
3657             return toP(F.at(pos).Skip());
3658         } else {
3659             return classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
3660         }
3661     }
3662 
3663     /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
3664      *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
3665      *  @param mods     Any modifiers starting the class or interface declaration
3666      *  @param dc       The documentation comment for the class, or null.
3667      */
3668     protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) {
3669         if (token.kind == CLASS) {
3670             return classDeclaration(mods, dc);
3671         } if (isRecordToken()) {
3672             return recordDeclaration(mods, dc);
3673         } else if (token.kind == INTERFACE) {
3674             return interfaceDeclaration(mods, dc);
3675         } else if (token.kind == ENUM) {
3676             return enumDeclaration(mods, dc);
3677         } else {
3678             int pos = token.pos;
3679             List<JCTree> errs;
3680             if (LAX_IDENTIFIER.accepts(token.kind)) {
3681                 errs = List.of(mods, toP(F.at(pos).Ident(ident())));
3682                 setErrorEndPos(token.pos);
3683             } else {
3684                 errs = List.of(mods);
3685             }
3686             final JCErroneous erroneousTree;
3687             if (parseModuleInfo) {
3688                 erroneousTree = syntaxError(pos, errs, Errors.ExpectedModuleOrOpen);
3689             } else {
3690                 erroneousTree = syntaxError(pos, errs, Errors.Expected4(CLASS, INTERFACE, ENUM, RECORD));
3691             }
3692             return toP(F.Exec(erroneousTree));
3693         }
3694     }
3695 
3696     /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
3697      *                     [IMPLEMENTS TypeList] ClassBody
3698      *  @param mods    The modifiers starting the class declaration
3699      *  @param dc       The documentation comment for the class, or null.
3700      */
3701     protected JCClassDecl classDeclaration(JCModifiers mods, Comment dc) {
3702         int pos = token.pos;
3703         accept(CLASS);
3704         Name name = typeName();
3705 
3706         List<JCTypeParameter> typarams = typeParametersOpt();
3707 
3708         JCExpression extending = null;
3709         if (token.kind == EXTENDS) {
3710             nextToken();
3711             extending = parseType();
3712         }
3713         List<JCExpression> implementing = List.nil();
3714         if (token.kind == IMPLEMENTS) {
3715             nextToken();
3716             implementing = typeList();
3717         }
3718         List<JCExpression> permitting = List.nil();
3719         if (token.kind == IDENTIFIER && token.name() == names.permits) {
3720             if ((mods.flags & Flags.SEALED) == 0) {
3721                 log.error(token.pos, Errors.PermitsInNoSealedClass);
3722             }
3723             nextToken();
3724             permitting = typeList();
3725         }
3726         List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
3727         JCClassDecl result = toP(F.at(pos).ClassDef(
3728             mods, name, typarams, extending, implementing, permitting, defs));
3729         attach(result, dc);
3730         return result;
3731     }
3732 
3733     protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) {
3734         int pos = token.pos;
3735         if ((mods.flags & Flags.ABSTRACT) != 0) {
3736             log.error(mods.pos, Errors.RecordCantBeAbstract);
3737         }
3738         nextToken();
3739         mods.flags |= Flags.RECORD | Flags.STATIC | Flags.FINAL;
3740         Name name = typeName();
3741 
3742         List<JCTypeParameter> typarams = typeParametersOpt();
3743 
3744         List<JCVariableDecl> headerFields =
3745                 headerFields();
3746 
3747         List<JCExpression> implementing = List.nil();
3748         if (token.kind == IMPLEMENTS) {
3749             nextToken();
3750             implementing = typeList();
3751         }
3752         List<JCTree> defs = List.nil();
3753         defs = classInterfaceOrRecordBody(name, false, true);
3754         java.util.List<JCVariableDecl> fields = new ArrayList<>();
3755         Set<Name> seenNames = new HashSet<>();
3756         for (JCVariableDecl field : headerFields) {
3757             if (seenNames.add(field.name)) {
3758                 fields.add(field);
3759             } else {
3760                 log.error(field.pos(), Errors.RecordCantDeclareDuplicateFields);
3761             }
3762         }
3763         for (JCTree def : defs) {
3764             if (def.hasTag(METHODDEF)) {
3765                 JCMethodDecl methDef = (JCMethodDecl) def;
3766                 if (methDef.name == names.init && methDef.params.isEmpty()) {
3767                     if ((methDef.mods.flags & Flags.PUBLIC) == 0) {
3768                         log.error(methDef, Errors.MethodMustBePublic(names.init));
3769                     }
3770                     ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>();
3771                     for (JCVariableDecl param : fields) {
3772                         tmpParams.add(F.at(param).VarDef(F.Modifiers(Flags.PARAMETER), param.name, param.vartype, null));
3773                     }
3774                     methDef.params = tmpParams.toList();
3775                 }
3776             }
3777         }
3778         for (int i = fields.size() - 1; i >= 0; i--) {
3779             defs = defs.prepend(fields.get(i));
3780         }
3781         JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs));
3782         attach(result, dc);
3783         return result;
3784     }
3785 
3786     Name typeName() {
3787         int pos = token.pos;
3788         Name name = ident();
3789         if (isRestrictedTypeName(name, pos, true)) {
3790             reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, name == names.var ? Source.JDK10 : Source.JDK13));
3791         }
3792 
3793         if (isRestrictedRecordTypeName(name)) {
3794             reportSyntaxError(pos, Errors.RecordNotAllowed(name));
3795         }
3796         return name;
3797     }
3798 
3799     List<JCVariableDecl> headerFields() {
3800         ListBuffer<JCVariableDecl> fields = new ListBuffer<>();
3801         if (token.kind == LPAREN) {
3802             nextToken();
3803             // check for empty record
3804             if (token.kind == RPAREN) {
3805                 nextToken();
3806                 return List.nil();
3807             }
3808             fields.add(headerField());
3809             while (token.kind == COMMA) {
3810                 nextToken();
3811                 fields.add(headerField());
3812             }
3813             accept(RPAREN);
3814         } else {
3815             accept(LPAREN);
3816         }
3817         return fields.toList();
3818     }
3819 
3820     JCVariableDecl headerField() {
3821         JCModifiers mods = modifiersOpt();
3822         if (mods.flags != 0) {
3823             log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers);
3824         }
3825         mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.MANDATED;
3826         JCExpression type = parseType();
3827         int pos = token.pos;
3828         Name id = ident();
3829         List<Pair<Accessors.Kind, Name>> accessors = List.of(new Pair<>(Accessors.Kind.GET, id));
3830         return toP(F.at(pos).VarDef(mods, id, type, null, accessors));
3831     }
3832 
3833     /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
3834      *                         [EXTENDS TypeList] InterfaceBody
3835      *  @param mods    The modifiers starting the interface declaration
3836      *  @param dc       The documentation comment for the interface, or null.
3837      */
3838     protected JCClassDecl interfaceDeclaration(JCModifiers mods, Comment dc) {
3839         int pos = token.pos;
3840         accept(INTERFACE);
3841 
3842         Name name = typeName();
3843 
3844         List<JCTypeParameter> typarams = typeParametersOpt();
3845 
3846         List<JCExpression> extending = List.nil();
3847         if (token.kind == EXTENDS) {
3848             nextToken();
3849             extending = typeList();
3850         }
3851         List<JCExpression> permitting = List.nil();
3852         if (token.kind == IDENTIFIER && token.name() == names.permits) {
3853             if ((mods.flags & Flags.SEALED) == 0) {
3854                 log.error(token.pos, Errors.PermitsInNoSealedClass);
3855             }
3856             nextToken();
3857             permitting = typeList();
3858         }
3859         List<JCTree> defs;
3860         defs = classInterfaceOrRecordBody(name, true, false);
3861         JCClassDecl result = toP(F.at(pos).ClassDef(
3862             mods, name, typarams, null, extending, permitting, defs));
3863         attach(result, dc);
3864         return result;
3865     }
3866 
3867     /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
3868      *  @param mods    The modifiers starting the enum declaration
3869      *  @param dc       The documentation comment for the enum, or null.
3870      */
3871     protected JCClassDecl enumDeclaration(JCModifiers mods, Comment dc) {
3872         int pos = token.pos;
3873         accept(ENUM);
3874 
3875         Name name = typeName();
3876 
3877         List<JCExpression> implementing = List.nil();
3878         if (token.kind == IMPLEMENTS) {
3879             nextToken();
3880             implementing = typeList();
3881         }
3882 


3895     List<JCTree> enumBody(Name enumName) {
3896         accept(LBRACE);
3897         ListBuffer<JCTree> defs = new ListBuffer<>();
3898         if (token.kind == COMMA) {
3899             nextToken();
3900         } else if (token.kind != RBRACE && token.kind != SEMI) {
3901             defs.append(enumeratorDeclaration(enumName));
3902             while (token.kind == COMMA) {
3903                 nextToken();
3904                 if (token.kind == RBRACE || token.kind == SEMI) break;
3905                 defs.append(enumeratorDeclaration(enumName));
3906             }
3907             if (token.kind != SEMI && token.kind != RBRACE) {
3908                 defs.append(syntaxError(token.pos, Errors.Expected3(COMMA, RBRACE, SEMI)));
3909                 nextToken();
3910             }
3911         }
3912         if (token.kind == SEMI) {
3913             nextToken();
3914             while (token.kind != RBRACE && token.kind != EOF) {
3915                 defs.appendList(classOrInterfaceOrRecordBodyDeclaration(enumName,
3916                                                                 false, false));
3917                 if (token.pos <= endPosTable.errorEndPos) {
3918                     // error recovery
3919                    skip(false, true, true, false);
3920                 }
3921             }
3922         }
3923         accept(RBRACE);
3924         return defs.toList();
3925     }
3926 
3927     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
3928      */
3929     JCTree enumeratorDeclaration(Name enumName) {
3930         Comment dc = token.comment(CommentStyle.JAVADOC);
3931         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
3932         if (token.deprecatedFlag()) {
3933             flags |= Flags.DEPRECATED;
3934         }
3935         int pos = token.pos;
3936         List<JCAnnotation> annotations = annotationsOpt(Tag.ANNOTATION);
3937         JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
3938         List<JCExpression> typeArgs = typeArgumentsOpt();
3939         int identPos = token.pos;
3940         Name name = ident();
3941         int createPos = token.pos;
3942         List<JCExpression> args = (token.kind == LPAREN)
3943             ? arguments() : List.nil();
3944         JCClassDecl body = null;
3945         if (token.kind == LBRACE) {
3946             JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM);
3947             List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
3948             body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
3949         }
3950         if (args.isEmpty() && body == null)
3951             createPos = identPos;
3952         JCIdent ident = F.at(identPos).Ident(enumName);
3953         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
3954         if (createPos != identPos)
3955             storeEnd(create, S.prevToken().endPos);
3956         ident = F.at(identPos).Ident(enumName);
3957         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
3958         attach(result, dc);
3959         return result;
3960     }
3961 
3962     /** TypeList = Type {"," Type}
3963      */
3964     List<JCExpression> typeList() {
3965         ListBuffer<JCExpression> ts = new ListBuffer<>();
3966         ts.append(parseType());
3967         while (token.kind == COMMA) {
3968             nextToken();
3969             ts.append(parseType());
3970         }
3971         return ts.toList();
3972     }
3973 
3974     /** ClassBody     = "{" {ClassBodyDeclaration} "}"
3975      *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
3976      */
3977     List<JCTree> classInterfaceOrRecordBody(Name className, boolean isInterface, boolean isRecord) {
3978         accept(LBRACE);
3979         if (token.pos <= endPosTable.errorEndPos) {
3980             // error recovery
3981             skip(false, true, false, false);
3982             if (token.kind == LBRACE)
3983                 nextToken();
3984         }
3985         ListBuffer<JCTree> defs = new ListBuffer<>();
3986         while (token.kind != RBRACE && token.kind != EOF) {
3987             defs.appendList(classOrInterfaceOrRecordBodyDeclaration(className, isInterface, isRecord));
3988             if (token.pos <= endPosTable.errorEndPos) {
3989                // error recovery
3990                skip(false, true, true, false);
3991            }
3992         }
3993         accept(RBRACE);
3994         return defs.toList();
3995     }
3996 
3997     /** ClassBodyDeclaration =
3998      *      ";"
3999      *    | [STATIC] Block
4000      *    | ModifiersOpt
4001      *      ( Type Ident
4002      *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
4003      *      | VOID Ident VoidMethodDeclaratorRest
4004      *      | TypeParameters [Annotations]
4005      *        ( Type Ident MethodDeclaratorRest
4006      *        | VOID Ident VoidMethodDeclaratorRest
4007      *        )
4008      *      | Ident ConstructorDeclaratorRest
4009      *      | TypeParameters Ident ConstructorDeclaratorRest
4010      *      | ClassOrInterfaceOrEnumDeclaration
4011      *      )
4012      *  InterfaceBodyDeclaration =
4013      *      ";"
4014      *    | ModifiersOpt
4015      *      ( Type Ident
4016      *        ( ConstantDeclaratorsRest ";" | MethodDeclaratorRest )
4017      *      | VOID Ident MethodDeclaratorRest
4018      *      | TypeParameters [Annotations]
4019      *        ( Type Ident MethodDeclaratorRest
4020      *        | VOID Ident VoidMethodDeclaratorRest
4021      *        )
4022      *      | ClassOrInterfaceOrEnumDeclaration
4023      *      )
4024      *
4025      */
4026     protected List<JCTree> classOrInterfaceOrRecordBodyDeclaration(Name className, boolean isInterface, boolean isRecord) {
4027         if (token.kind == SEMI) {
4028             nextToken();
4029             return List.nil();
4030         } else {
4031             Comment dc = token.comment(CommentStyle.JAVADOC);
4032             int pos = token.pos;
4033             JCModifiers mods = modifiersOpt();
4034             if (debug) {
4035                 System.out.println("read flags " + Flags.toString(mods.flags));
4036             }
4037             if (token.kind == CLASS ||
4038                 isRecordToken() ||
4039                 token.kind == INTERFACE ||
4040                 token.kind == ENUM) {
4041                 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc));
4042             } else if (token.kind == LBRACE &&
4043                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
4044                        mods.annotations.isEmpty()) {
4045                 if (isInterface) {
4046                     log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
4047                 }
4048                 return List.of(block(pos, mods.flags));
4049             } else {
4050                 pos = token.pos;
4051                 List<JCTypeParameter> typarams = typeParametersOpt();
4052                 // if there are type parameters but no modifiers, save the start
4053                 // position of the method in the modifiers.
4054                 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
4055                     mods.pos = pos;
4056                     storeEnd(mods, pos);
4057                 }
4058                 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
4059 
4060                 if (annosAfterParams.nonEmpty()) {
4061                     checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS);
4062                     mods.annotations = mods.annotations.appendList(annosAfterParams);
4063                     if (mods.pos == Position.NOPOS)
4064                         mods.pos = mods.annotations.head.pos;
4065                 }
4066 
4067                 Token tk = token;
4068                 pos = token.pos;
4069                 JCExpression type;
4070                 boolean isVoid = token.kind == VOID;
4071                 if (isVoid) {
4072                     type = to(F.at(pos).TypeIdent(TypeTag.VOID));
4073                     nextToken();
4074                 } else {
4075                     // method returns types are un-annotated types
4076                     type = unannotatedType(false);
4077                 }
4078                 if ((token.kind == LPAREN && !isInterface ||
4079                         isRecord && token.kind == LBRACE) && type.hasTag(IDENT)) {
4080                     if (isInterface || tk.name() != className)
4081                         log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq);
4082                     else if (annosAfterParams.nonEmpty())
4083                         illegal(annosAfterParams.head.pos);
4084                     return List.of(methodDeclaratorRest(
4085                         pos, mods, null, names.init, typarams,
4086                         isInterface, true, isRecord, dc));
4087                 } else {
4088                     pos = token.pos;
4089                     Name name = ident();
4090                     if (token.kind == LPAREN) {
4091                         return List.of(methodDeclaratorRest(
4092                             pos, mods, type, name, typarams,
4093                             isInterface, isVoid, false, dc));
4094                     } else if (!isVoid && typarams.isEmpty()) {
4095                         if (!isRecord || (isRecord && (mods.flags & Flags.STATIC) != 0)) {
4096                             List<JCTree> defs =
4097                                     variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
4098                                             new ListBuffer<JCTree>(), false).toList();
4099                             accept(SEMI);
4100                             storeEnd(defs.last(), S.prevToken().endPos);
4101                             return defs;
4102                         } else {
4103                             nextToken();
4104                             return List.of(syntaxError(pos, null, Errors.RecordFieldsMustBeInHeader));
4105                         }
4106                     } else {
4107                         pos = token.pos;
4108                         List<JCTree> err;
4109                         if (isVoid || typarams.nonEmpty()) {
4110                             JCMethodDecl m =
4111                                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
4112                                                             List.nil(), List.nil(), null, null));
4113                             attach(m, dc);
4114                             err = List.of(m);
4115                         } else {
4116                             err = List.nil();
4117                         }
4118                         return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
4119                     }
4120                 }
4121             }
4122         }
4123     }
4124 
4125     boolean isRecordToken() {
4126         return token.kind == IDENTIFIER && token.name() == names.record;
4127     }
4128 
4129     /** MethodDeclaratorRest =
4130      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4131      *  VoidMethodDeclaratorRest =
4132      *      FormalParameters [THROWS TypeList] ( MethodBody | ";")
4133      *  ConstructorDeclaratorRest =
4134      *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4135      */
4136     protected JCTree methodDeclaratorRest(int pos,
4137                               JCModifiers mods,
4138                               JCExpression type,
4139                               Name name,
4140                               List<JCTypeParameter> typarams,
4141                               boolean isInterface, boolean isVoid,
4142                               boolean isRecord,
4143                               Comment dc) {
4144         if (isInterface) {
4145             if ((mods.flags & Flags.STATIC) != 0) {
4146                 checkSourceLevel(Feature.STATIC_INTERFACE_METHODS);
4147             }
4148             if ((mods.flags & Flags.PRIVATE) != 0) {
4149                 checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS);
4150             }
4151         }
4152         JCVariableDecl prevReceiverParam = this.receiverParam;
4153         try {
4154             this.receiverParam = null;
4155             // Parsing formalParameters sets the receiverParam, if present
4156             List<JCVariableDecl> params = List.nil();

4157             List<JCExpression> thrown = List.nil();
4158             if (!isRecord || name != names.init || token.kind == LPAREN) {
4159                 params = formalParameters();
4160                 if (!isVoid) type = bracketsOpt(type);
4161                 if (token.kind == THROWS) {
4162                     nextToken();
4163                     thrown = qualidentList(true);
4164                 }
4165             }
4166             JCBlock body = null;
4167             JCExpression defaultValue;
4168             if (token.kind == LBRACE) {
4169                 body = block();
4170                 defaultValue = null;
4171             } else {
4172                 if (token.kind == DEFAULT) {
4173                     accept(DEFAULT);
4174                     defaultValue = annotationValue();
4175                 } else {
4176                     defaultValue = null;
4177                 }
4178                 accept(SEMI);
4179                 if (token.pos <= endPosTable.errorEndPos) {
4180                     // error recovery
4181                     skip(false, true, false, false);
4182                     if (token.kind == LBRACE) {
4183                         body = block();
4184                     }
4185                 }
4186             }

4187             JCMethodDecl result =
4188                     toP(F.at(pos).MethodDef(mods, name, type, typarams,
4189                                             receiverParam, params, thrown,
4190                                             body, defaultValue));
4191             attach(result, dc);
4192             return result;
4193         } finally {
4194             this.receiverParam = prevReceiverParam;
4195         }
4196     }
4197 
4198     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
4199      */
4200     List<JCExpression> qualidentList(boolean allowAnnos) {
4201         ListBuffer<JCExpression> ts = new ListBuffer<>();
4202 
4203         List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
4204         JCExpression qi = qualident(allowAnnos);
4205         if (!typeAnnos.isEmpty()) {
4206             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);


< prev index next >