diff options
author | Martin Odersky <odersky@gmail.com> | 2017-02-08 21:19:16 +1100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-04-04 13:28:44 +0200 |
commit | 41d83d42650d0c0b54c47c1a9043d0b92315aa4e (patch) | |
tree | 1bf4ca65464cf3f74b10ec14f718d4b4599223d7 /compiler/src/dotty/tools/dotc/parsing/Parsers.scala | |
parent | 69fd9dc80e78feb35ee601a9aaac813eef331e6a (diff) | |
download | dotty-41d83d42650d0c0b54c47c1a9043d0b92315aa4e.tar.gz dotty-41d83d42650d0c0b54c47c1a9043d0b92315aa4e.tar.bz2 dotty-41d83d42650d0c0b54c47c1a9043d0b92315aa4e.zip |
Change handling of enum defs.
The previous scheme did not work because desugaring cannot deal with
repeated expansions. We now sidestep the issue by doing the expansion in the parser. Luckily,
positions work out perfectly, so that one can reconstruct the source precisely from the parsed untyped
trees.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/parsing/Parsers.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 7ec44e342..ee736179a 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -49,6 +49,13 @@ object Parsers { val Class, Type, TypeParam, Def = Value } + private implicit class AddDeco(val buf: ListBuffer[Tree]) extends AnyVal { + def +++=(x: Tree) = x match { + case x: Thicket => buf ++= x.trees + case x => buf += x + } + } + /** The parse starting point depends on whether the source file is self-contained: * if not, the AST will be supplemented. */ @@ -2061,8 +2068,9 @@ object Parsers { case CASEOBJECT => objectDef(start, posMods(start, mods | Case | Module)) case ENUM => - val mods1 = addMod(mods, atPos(in.skipToken()) { Mod.Enum() }) - if (in.token == CLASS) tmplDef(start, mods1) else enumDef(start, mods) + val enumMod = atPos(in.skipToken()) { Mod.Enum() } + if (in.token == CLASS) tmplDef(start, addMod(mods, enumMod)) + else enumDef(start, mods, enumMod) case _ => syntaxErrorOrIncomplete("expected start of definition") EmptyTree @@ -2115,9 +2123,11 @@ object Parsers { /** id ClassConstr [`extends' [ConstrApps]] * [nl] ‘{’ EnumCaseStats ‘}’ */ - def enumDef(start: Offset, mods: Modifiers): EnumDef = atPos(start, nameStart) { - val name = ident().toTypeName - val constr = classConstr(name) + def enumDef(start: Offset, mods: Modifiers, enumMod: Mod): Thicket = { + val point = nameStart + val modName = ident() + val clsName = modName.toTypeName + val constr = classConstr(clsName) val parents = if (in.token == EXTENDS) { in.nextToken(); @@ -2125,10 +2135,17 @@ object Parsers { if (in.token == LBRACE) Nil else tokenSeparated(WITH, constrApp) } else Nil + val clsDef = atPos(start, point) { + TypeDef(clsName, Template(constr, parents, EmptyValDef, Nil)) + .withMods(addMod(mods, enumMod)).setComment(in.getDocComment(start)) + } newLineOptWhenFollowedBy(LBRACE) - val body = inBraces(enumCaseStats) - EnumDef(name, Template(constr, Nil, EmptyValDef, body)) - .withMods(mods).setComment(in.getDocComment(start)).asInstanceOf[EnumDef] + val modDef = atPos(in.offset) { + val body = inBraces(enumCaseStats) + ModuleDef(modName, Template(emptyConstructor, Nil, EmptyValDef, body)) + .withMods(mods) + } + Thicket(clsDef :: modDef :: Nil) } /** EnumCaseStats = EnumCaseStat {semi EnumCaseStat */ @@ -2249,7 +2266,7 @@ object Parsers { else if (in.token == IMPORT) stats ++= importClause() else if (in.token == AT || isTemplateIntro || isModifier) - stats += tmplDef(in.offset, defAnnotsMods(modifierTokens)) + stats +++= tmplDef(in.offset, defAnnotsMods(modifierTokens)) else if (!isStatSep) { if (in.token == CASE) syntaxErrorOrIncomplete("only `case class` or `case object` allowed") @@ -2299,7 +2316,7 @@ object Parsers { else if (isExprIntro) stats += expr1() else if (isDefIntro(modifierTokensOrCase)) - stats += defOrDcl(in.offset, defAnnotsMods(modifierTokens)) + stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens)) else if (!isStatSep) { exitOnError = mustStartStat syntaxErrorOrIncomplete("illegal start of definition") @@ -2357,9 +2374,9 @@ object Parsers { val start = in.offset val imods = implicitMods() if (isBindingIntro) stats += implicitClosure(start, Location.InBlock, imods) - else stats += localDef(start, imods) + else stats +++= localDef(start, imods) } else { - stats += localDef(in.offset) + stats +++= localDef(in.offset) } else if (!isStatSep && (in.token != CASE)) { exitOnError = mustStartStat |