aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-02-08 21:19:16 +1100
committerMartin Odersky <odersky@gmail.com>2017-04-04 13:28:44 +0200
commit41d83d42650d0c0b54c47c1a9043d0b92315aa4e (patch)
tree1bf4ca65464cf3f74b10ec14f718d4b4599223d7 /compiler/src/dotty/tools/dotc/parsing/Parsers.scala
parent69fd9dc80e78feb35ee601a9aaac813eef331e6a (diff)
downloaddotty-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.scala41
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