diff options
-rw-r--r-- | src/dotty/tools/dotc/ast/untpd.scala | 50 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 34 |
2 files changed, 70 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index 852c3a346..3ffc47bf8 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -94,9 +94,42 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp) // ----- Modifiers ----------------------------------------------------- + /** Mod is intended to record syntactic information about modifiers, it's + * NOT a replacement of flagsets. + * + * For any query about semantic information, check `flags` instead. + */ + sealed trait Mod extends Positioned - /** Modifiers and annotations for definitions - * @param flags The set flags + object Mod { + case class Private() extends Mod + + case class Protected() extends Mod + + case class Val() extends Mod + + case class Var() extends Mod + + case class Implicit() extends Mod + + case class Final() extends Mod + + case class Sealed() extends Mod + + case class Override() extends Mod + + case class Abstract() extends Mod + + case class Lazy() extends Mod + + case class Inline() extends Mod + + case class Type() extends Mod + } + + /** Modifiers and annotations for definitions + * + * @param flags The set flags * @param privateWithin If a private or protected has is followed by a * qualifier [q], the name q, "" as a typename otherwise. * @param annotations The annotations preceding the modifiers @@ -104,7 +137,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Modifiers ( flags: FlagSet = EmptyFlags, privateWithin: TypeName = tpnme.EMPTY, - annotations: List[Tree] = Nil) extends Positioned with Cloneable { + annotations: List[Tree] = Nil, + mods: List[Mod] = Nil) extends Positioned with Cloneable { def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc @@ -120,7 +154,15 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { if (this.flags == flags) this else copy(flags = flags) - def withAddedAnnotation(annot: Tree): Modifiers = + def withAddedMod(mod: Mod): Modifiers = + if (mods.exists(_ eq mod)) this + else withMods(mods :+ mod) + + def withMods(ms: List[Mod]): Modifiers = + if (mods eq ms) this + else copy(mods = ms) + + def withAddedAnnotation(annot: Tree): Modifiers = if (annotations.exists(_ eq annot)) this else withAnnotations(annotations :+ annot) diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 80c8f7b15..574a4d4fc 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1476,7 +1476,19 @@ object Parsers { case SEALED => Sealed } - /** Drop `private' modifier when followed by a qualifier. + private def modOfToken(tok: Int): Mod = tok match { + case ABSTRACT => Mod.Abstract() + case FINAL => Mod.Final() + case IMPLICIT => Mod.Implicit() + case INLINE => Mod.Inline() + case LAZY => Mod.Lazy() + case OVERRIDE => Mod.Override() + case PRIVATE => Mod.Private() + case PROTECTED => Mod.Protected() + case SEALED => Mod.Sealed() + } + + /** Drop `private' modifier when followed by a qualifier. * Contract `abstract' and `override' to ABSOVERRIDE */ private def normalize(mods: Modifiers): Modifiers = @@ -1488,10 +1500,12 @@ object Parsers { mods private def addModifier(mods: Modifiers): Modifiers = { - val flag = flagOfToken(in.token) + val tok = in.token + val flag = flagOfToken(tok) + val mod = atPos(in.offset) { in.nextToken(); modOfToken(tok) } + if (mods is flag) syntaxError(RepeatedModifier(flag.toString)) - val res = addFlag(mods, flag) - in.nextToken() + val res = addFlag(mods, flag).withAddedMod(mod) res } @@ -1614,8 +1628,8 @@ object Parsers { mods = atPos(start, in.offset) { if (in.token == TYPE) { - in.nextToken() - mods | Param | ParamAccessor + val mod = atPos(in.offset) { in.nextToken(); Mod.Type() } + (mods | Param | ParamAccessor).withAddedMod(mod) } else { if (mods.hasFlags) syntaxError("`type' expected") mods | Param | PrivateLocal @@ -1670,11 +1684,11 @@ object Parsers { mods = atPos(start, in.offset) { if (in.token == VAL) { - in.nextToken() - mods + val mod = atPos(in.offset) { in.nextToken(); Mod.Val() } + mods.withAddedMod(mod) } else if (in.token == VAR) { - in.nextToken() - addFlag(mods, Mutable) + val mod = atPos(in.offset) { in.nextToken(); Mod.Var() } + addFlag(mods, Mutable).withAddedMod(mod) } else { if (!(mods.flags &~ (ParamAccessor | Inline)).isEmpty) syntaxError("`val' or `var' expected") |