@@ -308,14 +308,21 @@ object Parsers {
308
308
* class constructor
309
309
*/
310
310
private [this ] var inClassConstrAnnots = false
311
-
312
311
private def fromWithinClassConstr [T ](body : => T ): T = {
313
312
val saved = inClassConstrAnnots
314
313
inClassConstrAnnots = true
315
314
try body
316
315
finally inClassConstrAnnots = saved
317
316
}
318
317
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
+
319
326
def migrationWarningOrError (msg : String , offset : Int = in.offset) =
320
327
if (in.isScala2Mode)
321
328
ctx.migrationWarning(msg, source atPos Position (offset))
@@ -1975,7 +1982,7 @@ object Parsers {
1975
1982
* | var ValDcl
1976
1983
* | def DefDcl
1977
1984
* | type {nl} TypeDcl
1978
- * EnumCase ::= `case' (EnumClassDef | ObjectDef )
1985
+ * EnumCase ::= `case' (id ClassConstr [`extends' ConstrApps]] | ids )
1979
1986
*/
1980
1987
def defOrDcl (start : Int , mods : Modifiers ): Tree = in.token match {
1981
1988
case VAL =>
@@ -1990,7 +1997,7 @@ object Parsers {
1990
1997
defDefOrDcl(start, posMods(start, mods))
1991
1998
case TYPE =>
1992
1999
typeDefOrDcl(start, posMods(start, mods))
1993
- case CASE =>
2000
+ case CASE if inEnum =>
1994
2001
enumCase(start, mods)
1995
2002
case _ =>
1996
2003
tmplDef(start, mods)
@@ -2135,7 +2142,7 @@ object Parsers {
2135
2142
}
2136
2143
}
2137
2144
2138
- /** TmplDef ::= ([`case' | `enum]' ] ‘class’ | trait’) ClassDef
2145
+ /** TmplDef ::= ([`case'] ‘class’ | trait’) ClassDef
2139
2146
* | [`case'] `object' ObjectDef
2140
2147
* | `enum' EnumDef
2141
2148
*/
@@ -2152,9 +2159,7 @@ object Parsers {
2152
2159
case CASEOBJECT =>
2153
2160
objectDef(start, posMods(start, mods | Case | Module ))
2154
2161
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 () })
2158
2163
case _ =>
2159
2164
syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition ())
2160
2165
EmptyTree
@@ -2198,55 +2203,18 @@ object Parsers {
2198
2203
ModuleDef (name, template).withMods(mods).setComment(in.getDocComment(start))
2199
2204
}
2200
2205
2201
- /** id ClassConstr [`extends' [ConstrApps]]
2202
- * [nl] ‘{’ EnumCaseStats ‘}’
2206
+ /** EnumDef ::= id ClassConstr [`extends' [ConstrApps]] EnumBody
2203
2207
*/
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) {
2206
2209
val modName = ident()
2207
2210
val clsName = modName.toTypeName
2208
2211
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))
2243
2214
}
2244
2215
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
+ */
2250
2218
def enumCase (start : Offset , mods : Modifiers ): DefTree = {
2251
2219
val mods1 = mods.withAddedMod(atPos(in.offset)(Mod .EnumCase ())) | Case
2252
2220
accept(CASE )
@@ -2257,18 +2225,36 @@ object Parsers {
2257
2225
2258
2226
atPos(start, nameStart) {
2259
2227
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 ) {
2263
2229
in.nextToken()
2264
2230
val ids = commaSeparated(() => termIdent())
2265
2231
PatDef (mods1, id :: ids, TypeTree (), EmptyTree )
2266
2232
}
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
+ }
2269
2244
}
2270
2245
}
2271
2246
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
+
2272
2258
/* -------- TEMPLATES ------------------------------------------- */
2273
2259
2274
2260
/** ConstrApp ::= SimpleType {ParArgumentExprs}
@@ -2285,32 +2271,34 @@ object Parsers {
2285
2271
* @return a pair consisting of the template, and a boolean which indicates
2286
2272
* whether the template misses a body (i.e. no {...} part).
2287
2273
*/
2288
- def template (constr : DefDef ): (Template , Boolean ) = {
2274
+ def template (constr : DefDef , isEnum : Boolean = false ): (Template , Boolean ) = {
2289
2275
newLineOptWhenFollowedBy(LBRACE )
2290
- if (in.token == LBRACE ) (templateBodyOpt(constr, Nil ), false )
2276
+ if (in.token == LBRACE ) (templateBodyOpt(constr, Nil , isEnum ), false )
2291
2277
else {
2292
2278
val parents = tokenSeparated(WITH , constrApp)
2293
2279
newLineOptWhenFollowedBy(LBRACE )
2280
+ if (isEnum && in.token != LBRACE )
2281
+ syntaxErrorOrIncomplete(ExpectedTokenButFound (LBRACE , in.token))
2294
2282
val missingBody = in.token != LBRACE
2295
- (templateBodyOpt(constr, parents), missingBody)
2283
+ (templateBodyOpt(constr, parents, isEnum ), missingBody)
2296
2284
}
2297
2285
}
2298
2286
2299
2287
/** TemplateOpt = [`extends' Template | TemplateBody]
2300
2288
*/
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 }
2303
2291
else {
2304
2292
newLineOptWhenFollowedBy(LBRACE )
2305
- if (in.token == LBRACE ) template(constr)._1
2293
+ if (in.token == LBRACE ) template(constr, isEnum )._1
2306
2294
else Template (constr, Nil , EmptyValDef , Nil )
2307
2295
}
2308
2296
2309
2297
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
2310
2298
*/
2311
- def templateBodyOpt (constr : DefDef , parents : List [Tree ]) = {
2299
+ def templateBodyOpt (constr : DefDef , parents : List [Tree ], isEnum : Boolean ) = {
2312
2300
val (self, stats) =
2313
- if (in.token == LBRACE ) templateBody() else (EmptyValDef , Nil )
2301
+ if (in.token == LBRACE ) withinEnum(isEnum)( templateBody() ) else (EmptyValDef , Nil )
2314
2302
Template (constr, parents, self, stats)
2315
2303
}
2316
2304
@@ -2378,9 +2366,10 @@ object Parsers {
2378
2366
* TemplateStat ::= Import
2379
2367
* | Annotations Modifiers Def
2380
2368
* | Annotations Modifiers Dcl
2381
- * | EnumCaseStat
2382
2369
* | Expr1
2383
2370
* |
2371
+ * EnumStat ::= TemplateStat
2372
+ * | Annotations Modifiers EnumCase
2384
2373
*/
2385
2374
def templateStatSeq (): (ValDef , List [Tree ]) = checkNoEscapingPlaceholders {
2386
2375
var self : ValDef = EmptyValDef
0 commit comments