Skip to content

Commit 64dc9b9

Browse files
committed
Syntax and parsing for derives clauses
1 parent ed14830 commit 64dc9b9

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
@@ -642,8 +642,8 @@ object Parsers {
642642

643643
/** QualId ::= id {`.' id}
644644
*/
645-
def qualId(): Tree =
646-
dotSelectors(termIdent())
645+
val qualId: () => Tree =
646+
() => dotSelectors(termIdent())
647647

648648
/** SimpleExpr ::= literal
649649
* | symbol
@@ -2404,7 +2404,7 @@ object Parsers {
24042404
ModuleDef(name, templ).withMods(mods).setComment(in.getDocComment(start))
24052405
}
24062406

2407-
/** EnumDef ::= id ClassConstr [`extends' ConstrApps] EnumBody
2407+
/** EnumDef ::= id ClassConstr InheritClauses EnumBody
24082408
*/
24092409
def enumDef(start: Offset, mods: Modifiers, enumMod: Mod): TypeDef = atPos(start, nameStart) {
24102410
val modName = ident()
@@ -2485,15 +2485,32 @@ object Parsers {
24852485
t :: ts
24862486
}
24872487

2488-
/** Template ::= [‘extends’ ConstrApps] [TemplateBody]
2488+
/** InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
24892489
*/
2490-
def template(constr: DefDef, isEnum: Boolean = false): Template = {
2491-
val parents =
2490+
def inheritClauses(): (List[Tree], List[Tree]) = {
2491+
val extended =
24922492
if (in.token == EXTENDS) {
24932493
in.nextToken()
2494-
constrApps()
2494+
if (in.token == LBRACE) {
2495+
in.errorOrMigrationWarning("`extends' must be followed by at least one parent")
2496+
Nil
2497+
}
2498+
else constrApps()
2499+
}
2500+
else Nil
2501+
val derived =
2502+
if (in.token == DERIVES) {
2503+
in.nextToken()
2504+
tokenSeparated(COMMA, qualId)
24952505
}
24962506
else Nil
2507+
(extended, derived)
2508+
}
2509+
2510+
/** Template ::= InheritClauses [TemplateBody]
2511+
*/
2512+
def template(constr: DefDef, isEnum: Boolean = false): Template = {
2513+
val (parents, deriveds) = inheritClauses()
24972514
newLineOptWhenFollowedBy(LBRACE)
24982515
if (isEnum && in.token != LBRACE)
24992516
syntaxErrorOrIncomplete(ExpectedTokenButFound(LBRACE, in.token))
@@ -2504,7 +2521,7 @@ object Parsers {
25042521
*/
25052522
def templateOpt(constr: DefDef, isEnum: Boolean = false): Template = {
25062523
newLineOptWhenFollowedBy(LBRACE)
2507-
if (in.token == EXTENDS || in.token == LBRACE)
2524+
if (in.token == EXTENDS || in.token == DERIVES || in.token == LBRACE)
25082525
template(constr, isEnum)
25092526
else
25102527
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
@@ -344,8 +344,9 @@ ClassDef ::= id ClassConstr [Template]
344344
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
345345
ConstrMods ::= {Annotation} [AccessModifier]
346346
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
347-
EnumDef ::= id ClassConstr [‘extends’ ConstrApps] EnumBody EnumDef(mods, name, tparams, template)
348-
Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats)
347+
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
348+
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
349+
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
349350
ConstrApps ::= ConstrApp {‘with’ ConstrApp}
350351
| ConstrApp {‘,’ ConstrApp}
351352
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)