@@ -308,14 +308,21 @@ object Parsers {
308308 * class constructor
309309 */
310310 private [this ] var inClassConstrAnnots = false
311-
312311 private def fromWithinClassConstr [T ](body : => T ): T = {
313312 val saved = inClassConstrAnnots
314313 inClassConstrAnnots = true
315314 try body
316315 finally inClassConstrAnnots = saved
317316 }
318317
318+ private [this ] var inEnum = false
319+ private def withinEnum [T ](isEnum : Boolean )(body : => T ): T = {
320+ val saved = inEnum
321+ inEnum = isEnum
322+ try body
323+ finally inEnum = saved
324+ }
325+
319326 def migrationWarningOrError (msg : String , offset : Int = in.offset) =
320327 if (in.isScala2Mode)
321328 ctx.migrationWarning(msg, source atPos Position (offset))
@@ -1975,7 +1982,7 @@ object Parsers {
19751982 * | var ValDcl
19761983 * | def DefDcl
19771984 * | type {nl} TypeDcl
1978- * EnumCase ::= `case' (EnumClassDef | ObjectDef )
1985+ * EnumCase ::= `case' (id ClassConstr [`extends' ConstrApps]] | ids )
19791986 */
19801987 def defOrDcl (start : Int , mods : Modifiers ): Tree = in.token match {
19811988 case VAL =>
@@ -1990,7 +1997,7 @@ object Parsers {
19901997 defDefOrDcl(start, posMods(start, mods))
19911998 case TYPE =>
19921999 typeDefOrDcl(start, posMods(start, mods))
1993- case CASE =>
2000+ case CASE if inEnum =>
19942001 enumCase(start, mods)
19952002 case _ =>
19962003 tmplDef(start, mods)
@@ -2135,7 +2142,7 @@ object Parsers {
21352142 }
21362143 }
21372144
2138- /** TmplDef ::= ([`case' | `enum]' ] ‘class’ | trait’) ClassDef
2145+ /** TmplDef ::= ([`case'] ‘class’ | trait’) ClassDef
21392146 * | [`case'] `object' ObjectDef
21402147 * | `enum' EnumDef
21412148 */
@@ -2152,9 +2159,7 @@ object Parsers {
21522159 case CASEOBJECT =>
21532160 objectDef(start, posMods(start, mods | Case | Module ))
21542161 case ENUM =>
2155- val enumMod = atPos(in.skipToken()) { Mod .Enum () }
2156- if (in.token == CLASS ) tmplDef(start, addMod(mods, enumMod))
2157- else enumDef(start, mods, enumMod)
2162+ enumDef(start, mods, atPos(in.skipToken()) { Mod .Enum () })
21582163 case _ =>
21592164 syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition ())
21602165 EmptyTree
@@ -2198,55 +2203,18 @@ object Parsers {
21982203 ModuleDef (name, template).withMods(mods).setComment(in.getDocComment(start))
21992204 }
22002205
2201- /** id ClassConstr [`extends' [ConstrApps]]
2202- * [nl] ‘{’ EnumCaseStats ‘}’
2206+ /** EnumDef ::= id ClassConstr [`extends' [ConstrApps]] EnumBody
22032207 */
2204- def enumDef (start : Offset , mods : Modifiers , enumMod : Mod ): Thicket = {
2205- val point = nameStart
2208+ def enumDef (start : Offset , mods : Modifiers , enumMod : Mod ): TypeDef = atPos(start, nameStart) {
22062209 val modName = ident()
22072210 val clsName = modName.toTypeName
22082211 val constr = classConstr(clsName)
2209- val parents =
2210- if (in.token == EXTENDS ) {
2211- in.nextToken();
2212- newLineOptWhenFollowedBy(LBRACE )
2213- if (in.token == LBRACE ) Nil else tokenSeparated(WITH , constrApp)
2214- }
2215- else Nil
2216- val clsDef = atPos(start, point) {
2217- TypeDef (clsName, Template (constr, parents, EmptyValDef , Nil ))
2218- .withMods(addMod(mods, enumMod)).setComment(in.getDocComment(start))
2219- }
2220- newLineOptWhenFollowedBy(LBRACE )
2221- val modDef = atPos(in.offset) {
2222- val body = inBraces(enumCaseStats())
2223- ModuleDef (modName, Template (emptyConstructor, Nil , EmptyValDef , body))
2224- .withMods(mods)
2225- }
2226- Thicket (clsDef :: modDef :: Nil )
2227- }
2228-
2229- /** EnumCaseStats = EnumCaseStat {semi EnumCaseStat} */
2230- def enumCaseStats (): List [DefTree ] = {
2231- val cases = new ListBuffer [DefTree ] += enumCaseStat()
2232- var exitOnError = false
2233- while (! isStatSeqEnd && ! exitOnError) {
2234- acceptStatSep()
2235- if (isCaseIntro)
2236- cases += enumCaseStat()
2237- else if (! isStatSep) {
2238- exitOnError = mustStartStat
2239- syntaxErrorOrIncomplete(" illegal start of case" )
2240- }
2241- }
2242- cases.toList
2212+ val impl = templateOpt(constr, isEnum = true )
2213+ TypeDef (clsName, impl).withMods(addMod(mods, enumMod)).setComment(in.getDocComment(start))
22432214 }
22442215
2245- /** EnumCaseStat = {Annotation [nl]} {Modifier} EnumCase */
2246- def enumCaseStat (): DefTree =
2247- enumCase(in.offset, defAnnotsMods(modifierTokens))
2248-
2249- /** EnumCase = `case' (EnumClassDef | ObjectDef) */
2216+ /** EnumCase = `case' (id ClassConstr [`extends' ConstrApps] | ids)
2217+ */
22502218 def enumCase (start : Offset , mods : Modifiers ): DefTree = {
22512219 val mods1 = mods.withAddedMod(atPos(in.offset)(Mod .EnumCase ())) | Case
22522220 accept(CASE )
@@ -2257,18 +2225,36 @@ object Parsers {
22572225
22582226 atPos(start, nameStart) {
22592227 val id = termIdent()
2260- if (in.token == LBRACKET || in.token == LPAREN )
2261- classDefRest(start, mods1, id.name.toTypeName)
2262- else if (in.token == COMMA ) {
2228+ if (in.token == COMMA ) {
22632229 in.nextToken()
22642230 val ids = commaSeparated(() => termIdent())
22652231 PatDef (mods1, id :: ids, TypeTree (), EmptyTree )
22662232 }
2267- else
2268- objectDefRest(start, mods1, id.name.asTermName)
2233+ else {
2234+ val caseDef =
2235+ if (in.token == LBRACKET || in.token == LPAREN || in.token == AT || isModifier) {
2236+ val clsName = id.name.toTypeName
2237+ val constr = classConstr(clsName, isCaseClass = true )
2238+ TypeDef (clsName, caseTemplate(constr))
2239+ }
2240+ else
2241+ ModuleDef (id.name.toTermName, caseTemplate(emptyConstructor))
2242+ caseDef.withMods(mods).setComment(in.getDocComment(start))
2243+ }
22692244 }
22702245 }
22712246
2247+ /** [`extends' ConstrApps] */
2248+ def caseTemplate (constr : DefDef ): Template = {
2249+ val parents =
2250+ if (in.token == EXTENDS ) {
2251+ in.nextToken()
2252+ tokenSeparated(WITH , constrApp)
2253+ }
2254+ else Nil
2255+ Template (constr, parents, EmptyValDef , Nil )
2256+ }
2257+
22722258/* -------- TEMPLATES ------------------------------------------- */
22732259
22742260 /** ConstrApp ::= SimpleType {ParArgumentExprs}
@@ -2285,32 +2271,34 @@ object Parsers {
22852271 * @return a pair consisting of the template, and a boolean which indicates
22862272 * whether the template misses a body (i.e. no {...} part).
22872273 */
2288- def template (constr : DefDef ): (Template , Boolean ) = {
2274+ def template (constr : DefDef , isEnum : Boolean = false ): (Template , Boolean ) = {
22892275 newLineOptWhenFollowedBy(LBRACE )
2290- if (in.token == LBRACE ) (templateBodyOpt(constr, Nil ), false )
2276+ if (in.token == LBRACE ) (templateBodyOpt(constr, Nil , isEnum ), false )
22912277 else {
22922278 val parents = tokenSeparated(WITH , constrApp)
22932279 newLineOptWhenFollowedBy(LBRACE )
2280+ if (isEnum && in.token != LBRACE )
2281+ syntaxErrorOrIncomplete(ExpectedTokenButFound (LBRACE , in.token))
22942282 val missingBody = in.token != LBRACE
2295- (templateBodyOpt(constr, parents), missingBody)
2283+ (templateBodyOpt(constr, parents, isEnum ), missingBody)
22962284 }
22972285 }
22982286
22992287 /** TemplateOpt = [`extends' Template | TemplateBody]
23002288 */
2301- def templateOpt (constr : DefDef ): Template =
2302- if (in.token == EXTENDS ) { in.nextToken(); template(constr)._1 }
2289+ def templateOpt (constr : DefDef , isEnum : Boolean = false ): Template =
2290+ if (in.token == EXTENDS ) { in.nextToken(); template(constr, isEnum )._1 }
23032291 else {
23042292 newLineOptWhenFollowedBy(LBRACE )
2305- if (in.token == LBRACE ) template(constr)._1
2293+ if (in.token == LBRACE ) template(constr, isEnum )._1
23062294 else Template (constr, Nil , EmptyValDef , Nil )
23072295 }
23082296
23092297 /** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
23102298 */
2311- def templateBodyOpt (constr : DefDef , parents : List [Tree ]) = {
2299+ def templateBodyOpt (constr : DefDef , parents : List [Tree ], isEnum : Boolean ) = {
23122300 val (self, stats) =
2313- if (in.token == LBRACE ) templateBody() else (EmptyValDef , Nil )
2301+ if (in.token == LBRACE ) withinEnum(isEnum)( templateBody() ) else (EmptyValDef , Nil )
23142302 Template (constr, parents, self, stats)
23152303 }
23162304
@@ -2378,9 +2366,10 @@ object Parsers {
23782366 * TemplateStat ::= Import
23792367 * | Annotations Modifiers Def
23802368 * | Annotations Modifiers Dcl
2381- * | EnumCaseStat
23822369 * | Expr1
23832370 * |
2371+ * EnumStat ::= TemplateStat
2372+ * | Annotations Modifiers EnumCase
23842373 */
23852374 def templateStatSeq (): (ValDef , List [Tree ]) = checkNoEscapingPlaceholders {
23862375 var self : ValDef = EmptyValDef
0 commit comments