Skip to content

Commit 6bf25d2

Browse files
committed
Syntax and parsing for derives clauses
1 parent 0dc0191 commit 6bf25d2

File tree

5 files changed

+35
-15
lines changed

5 files changed

+35
-15
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -649,8 +649,8 @@ object Parsers {
649649

650650
/** QualId ::= id {`.' id}
651651
*/
652-
def qualId(): Tree =
653-
dotSelectors(termIdent())
652+
val qualId: () => Tree =
653+
() => dotSelectors(termIdent())
654654

655655
/** SimpleExpr ::= literal
656656
* | symbol
@@ -2437,7 +2437,7 @@ object Parsers {
24372437
finalizeDef(ModuleDef(name, templ), mods, start)
24382438
}
24392439

2440-
/** EnumDef ::= id ClassConstr [`extends' ConstrApps] EnumBody
2440+
/** EnumDef ::= id ClassConstr InheritClauses EnumBody
24412441
*/
24422442
def enumDef(start: Offset, mods: Modifiers, enumMod: Mod): TypeDef = atSpan(start, nameStart) {
24432443
val modName = ident()
@@ -2518,15 +2518,32 @@ object Parsers {
25182518
t :: ts
25192519
}
25202520

2521-
/** Template ::= [‘extends’ ConstrApps] [TemplateBody]
2521+
/** InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
25222522
*/
2523-
def template(constr: DefDef, isEnum: Boolean = false): Template = {
2524-
val parents =
2523+
def inheritClauses(): (List[Tree], List[Tree]) = {
2524+
val extended =
25252525
if (in.token == EXTENDS) {
25262526
in.nextToken()
2527-
constrApps()
2527+
if (in.token == LBRACE) {
2528+
in.errorOrMigrationWarning("`extends' must be followed by at least one parent")
2529+
Nil
2530+
}
2531+
else constrApps()
2532+
}
2533+
else Nil
2534+
val derived =
2535+
if (in.token == DERIVES) {
2536+
in.nextToken()
2537+
tokenSeparated(COMMA, qualId)
25282538
}
25292539
else Nil
2540+
(extended, derived)
2541+
}
2542+
2543+
/** Template ::= InheritClauses [TemplateBody]
2544+
*/
2545+
def template(constr: DefDef, isEnum: Boolean = false): Template = {
2546+
val (parents, deriveds) = inheritClauses()
25302547
newLineOptWhenFollowedBy(LBRACE)
25312548
if (isEnum && in.token != LBRACE)
25322549
syntaxErrorOrIncomplete(ExpectedTokenButFound(LBRACE, in.token))
@@ -2537,7 +2554,7 @@ object Parsers {
25372554
*/
25382555
def templateOpt(constr: DefDef, isEnum: Boolean = false): Template = {
25392556
newLineOptWhenFollowedBy(LBRACE)
2540-
if (in.token == EXTENDS || in.token == LBRACE)
2557+
if (in.token == EXTENDS || in.token == DERIVES || in.token == LBRACE)
25412558
template(constr, isEnum)
25422559
else
25432560
Template(constr, Nil, EmptyValDef, Nil)

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ object Scanners {
205205
private def handleMigration(keyword: Token): Token =
206206
if (!isScala2Mode) keyword
207207
else if ( keyword == ENUM
208-
|| keyword == ERASED) treatAsIdent()
208+
|| keyword == ERASED
209+
|| keyword == DERIVES) treatAsIdent()
209210
else keyword
210211

211212

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ abstract class TokensCommon {
9494
//final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
9595
//final val ENUM = 62; enter(ENUM, "enum")
9696
//final val ERASED = 63; enter(ERASED, "erased")
97+
//final val DERIVES = 64; enter(DERIVES, "derives")
9798

9899
/** special symbols */
99100
final val COMMA = 70; enter(COMMA, "','")
@@ -178,6 +179,7 @@ object Tokens extends TokensCommon {
178179
final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
179180
final val ENUM = 62; enter(ENUM, "enum")
180181
final val ERASED = 63; enter(ERASED, "erased")
182+
final val DERIVES = 64; enter(DERIVES, "derives")
181183

182184
/** special symbols */
183185
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
@@ -198,7 +200,7 @@ object Tokens extends TokensCommon {
198200
/** XML mode */
199201
final val XMLSTART = 96; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
200202

201-
final val alphaKeywords: TokenSet = tokenRange(IF, ERASED)
203+
final val alphaKeywords: TokenSet = tokenRange(IF, DERIVES)
202204
final val symbolicKeywords: TokenSet = tokenRange(USCORE, VIEWBOUND)
203205
final val symbolicTokens: TokenSet = tokenRange(COMMA, VIEWBOUND)
204206
final val keywords: TokenSet = alphaKeywords | symbolicKeywords

docs/docs/internals/syntax.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,9 @@ ClassDef ::= id ClassConstr [Template]
345345
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
346346
ConstrMods ::= {Annotation} [AccessModifier]
347347
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
348-
EnumDef ::= id ClassConstr [‘extends’ ConstrApps] EnumBody EnumDef(mods, name, tparams, template)
349-
Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats)
348+
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
349+
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
350+
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
350351
ConstrApps ::= ConstrApp {‘with’ ConstrApp}
351352
| ConstrApp {‘,’ ConstrApp}
352353
ConstrApp ::= AnnotType {ArgumentExprs} Apply(tp, args)

tests/run/typeclass-derivation2.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,7 @@ object Deriving {
108108
}
109109

110110
// An algebraic datatype
111-
enum Lst[+T] // derives Eq, Pickler
112-
{
111+
enum Lst[+T] derives Eq, Pickler, Show {
113112
case Cons(hd: T, tl: Lst[T])
114113
case Nil
115114
}
@@ -146,7 +145,7 @@ object Lst extends Deriving {
146145
}
147146

148147
// A simple product type
149-
case class Pair[T](x: T, y: T) // derives Eq, Pickler
148+
case class Pair[T](x: T, y: T) derives Eq, Pickler
150149

151150
object Pair extends Deriving {
152151
// common compiler-generated infrastructure

0 commit comments

Comments
 (0)