diff options
author | Martin Odersky <odersky@gmail.com> | 2017-02-05 15:55:44 +1100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-04-04 13:20:45 +0200 |
commit | 669c5a8ed52f77942ee1ed7cf5813451d3762579 (patch) | |
tree | 7d48c11969725bba472005c68e068bba90a0f791 /compiler | |
parent | 0a4891153f65315473cac4294b0427a071efa70a (diff) | |
download | dotty-669c5a8ed52f77942ee1ed7cf5813451d3762579.tar.gz dotty-669c5a8ed52f77942ee1ed7cf5813451d3762579.tar.bz2 dotty-669c5a8ed52f77942ee1ed7cf5813451d3762579.zip |
Add enum syntax
Modify syntax.md and Tokens/Parser/untpd to support enums.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/untpd.scala | 7 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 116 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/parsing/Tokens.scala | 4 |
3 files changed, 102 insertions, 25 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 9b55720b8..e14c6714b 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -39,6 +39,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl) } + /** mods case name impl */ + case class EnumDef(name: TypeName, impl: Template) extends MemberDef + case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree case class SymbolLit(str: String) extends TermTree @@ -132,6 +135,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Inline() extends Mod(Flags.Inline) case class Type() extends Mod(Flags.EmptyFlags) + + case class Enum() extends Mod(Flags.EmptyFlags) + + case class EnumCase() extends Mod(Flags.EmptyFlags) } /** Modifiers and annotations for definitions diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index b644c94cc..d3c100406 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1873,15 +1873,16 @@ object Parsers { mods1 } - /** Def ::= val PatDef - * | var VarDef - * | def DefDef - * | type {nl} TypeDcl - * | TmplDef - * Dcl ::= val ValDcl - * | var ValDcl - * | def DefDcl - * | type {nl} TypeDcl + /** Def ::= val PatDef + * | var VarDef + * | def DefDef + * | type {nl} TypeDcl + * | TmplDef + * Dcl ::= val ValDcl + * | var ValDcl + * | def DefDcl + * | type {nl} TypeDcl + * EnumCase ::= `case' (EnumClassDef | ObjectDef) */ def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match { case VAL => @@ -1896,6 +1897,8 @@ object Parsers { defDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) case TYPE => typeDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) + case CASE => + enumCase(start, mods, in.getDocComment(start)) case _ => tmplDef(start, mods) } @@ -2041,8 +2044,9 @@ object Parsers { } } - /** TmplDef ::= ([`case'] `class' | `trait') ClassDef - * | [`case'] `object' ObjectDef + /** TmplDef ::= ([`case' | `enum]'] ‘class’ | [`enum'] trait’) ClassDef + * | [`case' | `enum'] `object' ObjectDef + * | `enum' EnumDef */ def tmplDef(start: Int, mods: Modifiers): Tree = { val docstring = in.getDocComment(start) @@ -2057,29 +2061,39 @@ object Parsers { objectDef(start, posMods(start, mods | Module), docstring) case CASEOBJECT => objectDef(start, posMods(start, mods | Case | Module), docstring) + case ENUM => + val mods1 = addMod(mods, atPos(in.skipToken()) { Mod.Enum() }) + in.token match { + case CLASS | TRAIT | OBJECT => tmplDef(start, mods1) + case _ => enumDef(start, mods, docstring) + } case _ => syntaxErrorOrIncomplete("expected start of definition") EmptyTree } } - /** ClassDef ::= id [ClsTypeParamClause] - * [ConstrMods] ClsParamClauses TemplateOpt + /** ClassDef ::= id ClassConstr TemplateOpt */ def classDef(start: Offset, mods: Modifiers, docstring: Option[Comment]): TypeDef = atPos(start, nameStart) { - val name = ident().toTypeName - val constr = atPos(in.lastOffset) { - val tparams = typeParamClauseOpt(ParamOwner.Class) - val cmods = constrModsOpt(name) - val vparamss = paramClauses(name, mods is Case) + classDefRest(start, mods, docstring, ident().toTypeName) + } - makeConstructor(tparams, vparamss).withMods(cmods) - } + def classDefRest(start: Offset, mods: Modifiers, docstring: Option[Comment], name: TypeName): TypeDef = { + val constr = classConstr(name, isCaseClass = mods is Case) val templ = templateOpt(constr) - TypeDef(name, templ).withMods(mods).setComment(docstring) } + /** ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses + */ + def classConstr(owner: Name, isCaseClass: Boolean = false): DefDef = atPos(in.lastOffset) { + val tparams = typeParamClauseOpt(ParamOwner.Class) + val cmods = constrModsOpt(owner) + val vparamss = paramClauses(owner, isCaseClass) + makeConstructor(tparams, vparamss).withMods(cmods) + } + /** ConstrMods ::= AccessModifier * | Annotation {Annotation} (AccessModifier | `this') */ @@ -2094,12 +2108,64 @@ object Parsers { /** ObjectDef ::= id TemplateOpt */ def objectDef(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): ModuleDef = atPos(start, nameStart) { - val name = ident() - val template = templateOpt(emptyConstructor) + objectDefRest(start, mods, docstring, ident()) + } + def objectDefRest(start: Offset, mods: Modifiers, docstring: Option[Comment] = None, name: TermName): ModuleDef = { + val template = templateOpt(emptyConstructor) ModuleDef(name, template).withMods(mods).setComment(docstring) } + /** id ClassConstr [`extends' [ConstrApps]] + * [nl] ‘{’ EnumCaseStats ‘}’ + */ + def enumDef(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): EnumDef = atPos(start, nameStart) { + val name = ident().toTypeName + val constr = classConstr(name) + val parents = + if (in.token == EXTENDS) { + in.nextToken(); + newLineOptWhenFollowedBy(LBRACE) + if (in.token == LBRACE) Nil else tokenSeparated(WITH, constrApp) + } + else Nil + newLineOptWhenFollowedBy(LBRACE) + val body = inBraces(enumCaseStats) + EnumDef(name, Template(constr, Nil, EmptyValDef, body)) + .withMods(mods).setComment(in.getDocComment(start)).asInstanceOf[EnumDef] + } + + /** EnumCaseStats = EnumCaseStat {semi EnumCaseStat */ + def enumCaseStats(): List[MemberDef] = { + val cases = new ListBuffer[MemberDef] += enumCaseStat() + while (in.token != RBRACE) { + acceptStatSep() + cases += enumCaseStat() + } + cases.toList + } + + /** EnumCaseStat = {Annotation [nl]} {Modifier} EnumCase */ + def enumCaseStat(): MemberDef = { + val start = in.offset + val docstring = in.getDocComment(start) + val mods = defAnnotsMods(modifierTokens) + enumCase(start, mods, docstring) + } + + /** EnumCase = `case' (EnumClassDef | ObjectDef) */ + def enumCase(start: Offset, mods: Modifiers, docstring: Option[Comment]): MemberDef = { + val mods1 = mods.withAddedMod(atPos(in.offset)(Mod.EnumCase())) | Case + accept(CASE) + atPos(start, nameStart) { + val name = ident() + if (in.token == LBRACKET || in.token == LPAREN) + classDefRest(start, mods1, docstring, name.toTypeName) + else + objectDefRest(start, mods1, docstring, name) + } + } + /* -------- TEMPLATES ------------------------------------------- */ /** ConstrApp ::= SimpleType {ParArgumentExprs} @@ -2209,8 +2275,8 @@ object Parsers { * TemplateStat ::= Import * | Annotations Modifiers Def * | Annotations Modifiers Dcl + * | EnumCaseStat * | Expr1 - * | super ArgumentExprs {ArgumentExprs} * | */ def templateStatSeq(): (ValDef, List[Tree]) = checkNoEscapingPlaceholders { @@ -2240,7 +2306,7 @@ object Parsers { stats ++= importClause() else if (isExprIntro) stats += expr1() - else if (isDefIntro(modifierTokens)) + else if (isDefIntro(modifierTokensOrCase)) stats += defOrDcl(in.offset, defAnnotsMods(modifierTokens)) else if (!isStatSep) { exitOnError = mustStartStat diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index 8d42e525a..6109dda2a 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -92,6 +92,7 @@ abstract class TokensCommon { //final val THEN = 60; enter(THEN, "then") //final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate //final val INLINE = 62; enter(INLINE, "inline") + //final val ENUM = 63; enter(ENUM, "enum") /** special symbols */ final val COMMA = 70; enter(COMMA, "','") @@ -175,6 +176,7 @@ object Tokens extends TokensCommon { final val THEN = 60; enter(THEN, "then") final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate final val INLINE = 62; enter(INLINE, "inline") + final val ENUM = 63; enter(ENUM, "enum") /** special symbols */ final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line") @@ -228,6 +230,8 @@ object Tokens extends TokensCommon { final val modifierTokens = localModifierTokens | accessModifierTokens | BitSet( OVERRIDE) + final val modifierTokensOrCase = modifierTokens | BitSet(CASE) + /** Is token only legal as start of statement (eof also included)? */ final val mustStartStatTokens = defIntroTokens | modifierTokens | BitSet( IMPORT, PACKAGE) |