< prev index next >

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

Print this page

        

*** 99,109 **** /** The Preview language setting. */ private Preview preview; /** The name table. */ ! private Names names; /** End position mappings container */ protected final AbstractEndPosTable endPosTable; // Because of javac's limited lookahead, some contexts are ambiguous in --- 99,109 ---- /** The Preview language setting. */ private Preview preview; /** The name table. */ ! protected Names names; /** End position mappings container */ protected final AbstractEndPosTable endPosTable; // Because of javac's limited lookahead, some contexts are ambiguous in
*** 2371,2381 **** { List<JCExpression> args = arguments(); JCClassDecl body = null; if (token.kind == LBRACE) { int pos = token.pos; ! List<JCTree> defs = classOrInterfaceBody(names.empty, false); JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); body = toP(F.at(pos).AnonymousClassDef(mods, defs)); } return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); } --- 2371,2381 ---- { List<JCExpression> args = arguments(); JCClassDecl body = null; if (token.kind == LBRACE) { int pos = token.pos; ! List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false); JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); body = toP(F.at(pos).AnonymousClassDef(mods, defs)); } return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); }
*** 2505,2514 **** --- 2505,2515 ---- /**This method parses a statement appearing inside a block. */ List<JCStatement> blockStatement() { //todo: skip to anchor on error(?) + Comment dc; int pos = token.pos; switch (token.kind) { case RBRACE: case CASE: case DEFAULT: case EOF: return List.nil(); case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
*** 2516,2550 **** case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: case ASSERT: return List.of(parseSimpleStatement()); case MONKEYS_AT: case FINAL: { ! Comment dc = token.comment(CommentStyle.JAVADOC); JCModifiers mods = modifiersOpt(); if (token.kind == INTERFACE || token.kind == CLASS || token.kind == ENUM) { ! return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); } else { JCExpression t = parseType(true); return localVariableDeclarations(mods, t); } } case ABSTRACT: case STRICTFP: { ! Comment dc = token.comment(CommentStyle.JAVADOC); JCModifiers mods = modifiersOpt(); ! return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); } case INTERFACE: case CLASS: ! Comment dc = token.comment(CommentStyle.JAVADOC); ! return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); case ENUM: log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum); dc = token.comment(CommentStyle.JAVADOC); ! return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); ! default: Token prevToken = token; JCExpression t = term(EXPR | TYPE); if (token.kind == COLON && t.hasTag(IDENT)) { nextToken(); JCStatement stat = parseStatementAsBlock(); --- 2517,2556 ---- case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: case ASSERT: return List.of(parseSimpleStatement()); case MONKEYS_AT: case FINAL: { ! dc = token.comment(CommentStyle.JAVADOC); JCModifiers mods = modifiersOpt(); if (token.kind == INTERFACE || token.kind == CLASS || token.kind == ENUM) { ! return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc)); } else { JCExpression t = parseType(true); return localVariableDeclarations(mods, t); } } case ABSTRACT: case STRICTFP: { ! dc = token.comment(CommentStyle.JAVADOC); JCModifiers mods = modifiersOpt(); ! return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc)); } case INTERFACE: case CLASS: ! dc = token.comment(CommentStyle.JAVADOC); ! return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); case ENUM: log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum); dc = token.comment(CommentStyle.JAVADOC); ! return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); ! } ! if (isRecordDeclaration()) { ! JCModifiers mods = modifiersOpt(); ! dc = token.comment(CommentStyle.JAVADOC); ! return List.of(recordDeclaration(mods, dc)); ! } else { Token prevToken = token; JCExpression t = term(EXPR | TYPE); if (token.kind == COLON && t.hasTag(IDENT)) { nextToken(); JCStatement stat = parseStatementAsBlock();
*** 3223,3232 **** --- 3229,3242 ---- } } return false; } + boolean isRestrictedRecordTypeName(Name name) { + return Feature.RECORDS.allowedInSource(source) && name == names.record; + } + /** VariableDeclaratorId = Ident BracketsOpt */ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { return variableDeclaratorId(mods, type, false); }
*** 3544,3565 **** int pos = token.pos; if (mods == null && token.kind == SEMI) { nextToken(); return toP(F.at(pos).Skip()); } else { ! return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment); } } /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) * @param mods Any modifiers starting the class or interface declaration * @param dc The documentation comment for the class, or null. */ ! protected JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) { if (token.kind == CLASS) { return classDeclaration(mods, dc); } else if (token.kind == INTERFACE) { return interfaceDeclaration(mods, dc); } else if (token.kind == ENUM) { return enumDeclaration(mods, dc); } else { --- 3554,3577 ---- int pos = token.pos; if (mods == null && token.kind == SEMI) { nextToken(); return toP(F.at(pos).Skip()); } else { ! return classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment); } } /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) * @param mods Any modifiers starting the class or interface declaration * @param dc The documentation comment for the class, or null. */ ! protected JCStatement classOrRecordOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) { if (token.kind == CLASS) { return classDeclaration(mods, dc); + } if (isRecordDeclaration()) { + return recordDeclaration(mods, dc); } else if (token.kind == INTERFACE) { return interfaceDeclaration(mods, dc); } else if (token.kind == ENUM) { return enumDeclaration(mods, dc); } else {
*** 3573,3583 **** } final JCErroneous erroneousTree; if (parseModuleInfo) { erroneousTree = syntaxError(pos, errs, Errors.ExpectedModuleOrOpen); } else { ! erroneousTree = syntaxError(pos, errs, Errors.Expected3(CLASS, INTERFACE, ENUM)); } return toP(F.Exec(erroneousTree)); } } --- 3585,3595 ---- } final JCErroneous erroneousTree; if (parseModuleInfo) { erroneousTree = syntaxError(pos, errs, Errors.ExpectedModuleOrOpen); } else { ! erroneousTree = syntaxError(pos, errs, Errors.Expected4(CLASS, INTERFACE, ENUM, RECORD)); } return toP(F.Exec(erroneousTree)); } }
*** 3601,3626 **** List<JCExpression> implementing = List.nil(); if (token.kind == IMPLEMENTS) { nextToken(); implementing = typeList(); } ! List<JCTree> defs = classOrInterfaceBody(name, false); JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, extending, implementing, defs)); attach(result, dc); return result; } Name typeName() { int pos = token.pos; Name name = ident(); if (isRestrictedLocalVarTypeName(name, pos, true)) { reportSyntaxError(pos, Errors.VarNotAllowed); } return name; } /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt * [EXTENDS TypeList] InterfaceBody * @param mods The modifiers starting the interface declaration * @param dc The documentation comment for the interface, or null. */ --- 3613,3717 ---- List<JCExpression> implementing = List.nil(); if (token.kind == IMPLEMENTS) { nextToken(); implementing = typeList(); } ! List<JCTree> defs = classInterfaceOrRecordBody(name, false, false); JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, extending, implementing, defs)); attach(result, dc); return result; } + protected JCClassDecl recordDeclaration(JCModifiers mods, Comment dc) { + int pos = token.pos; + if ((mods.flags & Flags.ABSTRACT) != 0) { + log.error(mods.pos, Errors.RecordCantBeAbstract); + } + nextToken(); + mods.flags |= Flags.RECORD | Flags.STATIC | Flags.FINAL; + Name name = typeName(); + + List<JCTypeParameter> typarams = typeParametersOpt(); + + Map<Name, JCVariableDecl> optHeaderFields = headerFields(mods); + + List<JCExpression> implementing = List.nil(); + if (token.kind == IMPLEMENTS) { + nextToken(); + implementing = typeList(); + } + List<JCTree> defs = List.nil(); + if (token.kind == LBRACE) { + defs = classInterfaceOrRecordBody(name, false, true); + } else { + accept(SEMI); + } + java.util.List<JCVariableDecl> fields = new ArrayList<>(); + for (JCVariableDecl field : optHeaderFields.values()) { + fields.add(field); + } + for (JCTree def : defs) { + if (def.hasTag(METHODDEF)) { + JCMethodDecl methDef = (JCMethodDecl) def; + if (methDef.name == names.init && methDef.params.isEmpty()) { + ListBuffer<JCVariableDecl> tmpParams = new ListBuffer<>(); + for (JCVariableDecl param : fields) { + tmpParams.add(F.at(param).VarDef(F.Modifiers(Flags.PARAMETER), param.name, param.vartype, null)); + } + methDef.params = tmpParams.toList(); + } + } + } + for (int i = fields.size() - 1; i >= 0; i--) { + defs = defs.prepend(fields.get(i)); + } + JCClassDecl result = toP(F.at(pos).ClassDef(mods, name, typarams, null, implementing, defs)); + attach(result, dc); + return result; + } + Name typeName() { int pos = token.pos; Name name = ident(); if (isRestrictedLocalVarTypeName(name, pos, true)) { reportSyntaxError(pos, Errors.VarNotAllowed); } + + if (isRestrictedRecordTypeName(name)) { + reportSyntaxError(pos, Errors.RecordNotAllowed(name)); + } return name; } + Map<Name, JCVariableDecl> headerFields(JCModifiers recordClassMods) { + accept(LPAREN); + Map<Name, JCVariableDecl> fields = new LinkedHashMap<>(); + while (token.kind != RPAREN) { + JCModifiers mods = modifiersOpt(); + if (mods.flags != 0) { + log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers); + } + mods.flags |= Flags.RECORD | Flags.FINAL; + mods.flags |= (recordClassMods.flags & Flags.ABSTRACT) != 0 ? Flags.PROTECTED : 0; + JCExpression type = parseType(); + int pos = token.pos; + Name id = ident(); + if (!fields.containsKey(id)) { + List<Pair<Accessors.Kind, Name>> accessors = List.of(new Pair<>(Accessors.Kind.GET, id)); + fields.put(id, toP(F.at(pos).VarDef(mods, id, type, null, accessors))); + } else { + log.error(pos, Errors.RecordCantDeclareDuplicateFields); + } + if (token.kind == COMMA) { + nextToken(); + } + } + accept(RPAREN); + return fields; + } + /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt * [EXTENDS TypeList] InterfaceBody * @param mods The modifiers starting the interface declaration * @param dc The documentation comment for the interface, or null. */
*** 3635,3645 **** List<JCExpression> extending = List.nil(); if (token.kind == EXTENDS) { nextToken(); extending = typeList(); } ! List<JCTree> defs = classOrInterfaceBody(name, true); JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, null, extending, defs)); attach(result, dc); return result; } --- 3726,3742 ---- List<JCExpression> extending = List.nil(); if (token.kind == EXTENDS) { nextToken(); extending = typeList(); } ! List<JCTree> defs; ! if (token.kind == LBRACE) { ! defs = classInterfaceOrRecordBody(name, true, false); ! } else { ! accept(SEMI); ! defs = List.nil(); ! } JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, null, extending, defs)); attach(result, dc); return result; }
*** 3722,3732 **** List<JCExpression> args = (token.kind == LPAREN) ? arguments() : List.nil(); JCClassDecl body = null; if (token.kind == LBRACE) { JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM); ! List<JCTree> defs = classOrInterfaceBody(names.empty, false); body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); } if (args.isEmpty() && body == null) createPos = identPos; JCIdent ident = F.at(identPos).Ident(enumName); --- 3819,3829 ---- List<JCExpression> args = (token.kind == LPAREN) ? arguments() : List.nil(); JCClassDecl body = null; if (token.kind == LBRACE) { JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM); ! List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false); body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); } if (args.isEmpty() && body == null) createPos = identPos; JCIdent ident = F.at(identPos).Ident(enumName);
*** 3752,3772 **** } /** ClassBody = "{" {ClassBodyDeclaration} "}" * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" */ ! List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { accept(LBRACE); if (token.pos <= endPosTable.errorEndPos) { // error recovery skip(false, true, false, false); if (token.kind == LBRACE) nextToken(); } ListBuffer<JCTree> defs = new ListBuffer<>(); while (token.kind != RBRACE && token.kind != EOF) { ! defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); if (token.pos <= endPosTable.errorEndPos) { // error recovery skip(false, true, true, false); } } --- 3849,3873 ---- } /** ClassBody = "{" {ClassBodyDeclaration} "}" * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" */ ! List<JCTree> classInterfaceOrRecordBody(Name className, boolean isInterface, boolean isRecord) { accept(LBRACE); if (token.pos <= endPosTable.errorEndPos) { // error recovery skip(false, true, false, false); if (token.kind == LBRACE) nextToken(); } ListBuffer<JCTree> defs = new ListBuffer<>(); while (token.kind != RBRACE && token.kind != EOF) { ! if (!isRecord) { ! defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); ! } else { ! defs.appendList(recordBodyDeclaration(className)); ! } if (token.pos <= endPosTable.errorEndPos) { // error recovery skip(false, true, true, false); } }
*** 3810,3822 **** } else { Comment dc = token.comment(CommentStyle.JAVADOC); int pos = token.pos; JCModifiers mods = modifiersOpt(); if (token.kind == CLASS || token.kind == INTERFACE || token.kind == ENUM) { ! return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); } else if (token.kind == LBRACE && (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && mods.annotations.isEmpty()) { if (isInterface) { log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed); --- 3911,3924 ---- } else { Comment dc = token.comment(CommentStyle.JAVADOC); int pos = token.pos; JCModifiers mods = modifiersOpt(); if (token.kind == CLASS || + isRecordDeclaration() || token.kind == INTERFACE || token.kind == ENUM) { ! return List.of(classOrRecordOrInterfaceOrEnumDeclaration(mods, dc)); } else if (token.kind == LBRACE && (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && mods.annotations.isEmpty()) { if (isInterface) { log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.InitializerNotAllowed);
*** 3856,3873 **** log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq); else if (annosAfterParams.nonEmpty()) illegal(annosAfterParams.head.pos); return List.of(methodDeclaratorRest( pos, mods, null, names.init, typarams, ! isInterface, true, dc)); } else { pos = token.pos; Name name = ident(); if (token.kind == LPAREN) { return List.of(methodDeclaratorRest( pos, mods, type, name, typarams, ! isInterface, isVoid, dc)); } else if (!isVoid && typarams.isEmpty()) { List<JCTree> defs = variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, new ListBuffer<JCTree>(), false).toList(); accept(SEMI); --- 3958,3975 ---- log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidMethDeclRetTypeReq); else if (annosAfterParams.nonEmpty()) illegal(annosAfterParams.head.pos); return List.of(methodDeclaratorRest( pos, mods, null, names.init, typarams, ! isInterface, true, false, dc)); } else { pos = token.pos; Name name = ident(); if (token.kind == LPAREN) { return List.of(methodDeclaratorRest( pos, mods, type, name, typarams, ! isInterface, isVoid, false, dc)); } else if (!isVoid && typarams.isEmpty()) { List<JCTree> defs = variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, new ListBuffer<JCTree>(), false).toList(); accept(SEMI);
*** 3890,3899 **** --- 3992,4082 ---- } } } } + boolean isRecordDeclaration() { + return token.kind == IDENTIFIER && token.name() == names.record && + (peekToken(TokenKind.IDENTIFIER, TokenKind.LPAREN) || + peekToken(TokenKind.IDENTIFIER, TokenKind.LT)); + } + + protected List<JCTree> recordBodyDeclaration(Name className) { + Comment dc = token.comment(CommentStyle.JAVADOC); + JCModifiers mods = modifiersOpt(); + return methodOrFieldMemberDecl(className, mods, false, dc); + } + + private List<JCTree> methodOrFieldMemberDecl(Name className, JCModifiers mods, boolean isInterface, Comment dc) { + int pos = token.pos; + List<JCTypeParameter> typarams = typeParametersOpt(); + // if there are type parameters but no modifiers, save the start + // position of the method in the modifiers. + if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { + mods.pos = pos; + storeEnd(mods, pos); + } + List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION); + + if (annosAfterParams.nonEmpty()) { + checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS); + mods.annotations = mods.annotations.appendList(annosAfterParams); + if (mods.pos == Position.NOPOS) + mods.pos = mods.annotations.head.pos; + } + + Token tk = token; + pos = token.pos; + JCExpression type; + boolean isVoid = token.kind == VOID; + if (isVoid) { + type = to(F.at(pos).TypeIdent(TypeTag.VOID)); + nextToken(); + } else { + // method returns types are un-annotated types + type = unannotatedType(false); + } + if ((token.kind == LPAREN && !isInterface || + token.kind == LBRACE) && type.hasTag(IDENT)) { + if (isInterface || tk.name() != className) + log.error(pos, Errors.InvalidMethDeclRetTypeReq); + else if (annosAfterParams.nonEmpty()) + illegal(annosAfterParams.head.pos); + return List.of(methodDeclaratorRest( + pos, mods, null, names.init, typarams, + isInterface, true, true, dc)); + } else { + pos = token.pos; + Name name = ident(); + if (token.kind == LPAREN) { + return List.of(methodDeclaratorRest( + pos, mods, type, name, typarams, + isInterface, isVoid, true, dc)); + } else if (!isVoid && typarams.isEmpty()) { + if ((mods.flags & Flags.STATIC) != 0) { + List<JCTree> defs = + variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, + new ListBuffer<JCTree>(), false).toList(); + accept(SEMI); + storeEnd(defs.last(), S.prevToken().endPos); + return defs; + } else { + log.error(pos, Errors.RecordFieldsMustBeInHeader); + int tmpPos = token.pos; + nextToken(); + return List.of(syntaxError(tmpPos, null, Errors.Expected(LPAREN))); + } + } else { + pos = token.pos; + List<JCTree> err = isVoid + ? List.of(toP(F.at(pos).MethodDef(mods, name, type, typarams, + List.nil(), List.nil(), null, null))) + : null; + return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN))); + } + } + } /** MethodDeclaratorRest = * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") * VoidMethodDeclaratorRest = * FormalParameters [THROWS TypeList] ( MethodBody | ";") * ConstructorDeclaratorRest =
*** 3903,3912 **** --- 4086,4096 ---- JCModifiers mods, JCExpression type, Name name, List<JCTypeParameter> typarams, boolean isInterface, boolean isVoid, + boolean isRecord, Comment dc) { if (isInterface) { if ((mods.flags & Flags.STATIC) != 0) { checkSourceLevel(Feature.STATIC_INTERFACE_METHODS); }
*** 3916,3931 **** } JCVariableDecl prevReceiverParam = this.receiverParam; try { this.receiverParam = null; // Parsing formalParameters sets the receiverParam, if present ! List<JCVariableDecl> params = formalParameters(); ! if (!isVoid) type = bracketsOpt(type); List<JCExpression> thrown = List.nil(); ! if (token.kind == THROWS) { ! nextToken(); ! thrown = qualidentList(true); } JCBlock body = null; JCExpression defaultValue; if (token.kind == LBRACE) { body = block(); --- 4100,4118 ---- } JCVariableDecl prevReceiverParam = this.receiverParam; try { this.receiverParam = null; // Parsing formalParameters sets the receiverParam, if present ! List<JCVariableDecl> params = List.nil(); List<JCExpression> thrown = List.nil(); ! if (!isRecord || name != names.init || token.kind == LPAREN) { ! params = formalParameters(); ! if (!isVoid) type = bracketsOpt(type); ! if (token.kind == THROWS) { ! nextToken(); ! thrown = qualidentList(true); ! } } JCBlock body = null; JCExpression defaultValue; if (token.kind == LBRACE) { body = block();
*** 3944,3954 **** if (token.kind == LBRACE) { body = block(); } } } - JCMethodDecl result = toP(F.at(pos).MethodDef(mods, name, type, typarams, receiverParam, params, thrown, body, defaultValue)); attach(result, dc); --- 4131,4140 ----
< prev index next >