aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala116
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Tokens.scala4
-rw-r--r--docs/docs/internals/syntax.md17
4 files changed, 115 insertions, 29 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)
diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md
index 7f06cdc2a..804a0f57a 100644
--- a/docs/docs/internals/syntax.md
+++ b/docs/docs/internals/syntax.md
@@ -289,7 +289,9 @@ TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat}
TemplateStat ::= Import
| {Annotation [nl]} {Modifier} Def
| {Annotation [nl]} {Modifier} Dcl
+ | EnumCaseStat
| Expr1
+ |
SelfType ::= id [‘:’ InfixType] ‘=>’ ValDef(_, name, tpt, _)
| ‘this’ ‘:’ InfixType ‘=>’
@@ -328,13 +330,20 @@ DefDef ::= DefSig [‘:’ Type] ‘=’ Expr
| ‘this’ DefParamClause DefParamClauses DefDef(_, <init>, Nil, vparamss, EmptyTree, expr | Block)
(‘=’ ConstrExpr | [nl] ConstrBlock)
-TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
- | [‘case’] ‘object’ ObjectDef
-ClassDef ::= id [ClsTypeParamClause] ClassDef(mods, name, tparams, templ)
- [ConstrMods] ClsParamClauses TemplateOpt with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
+TmplDef ::= ([‘case’ | `enum'] ‘class’ | [`enum'] trait’) ClassDef
+ | [‘case’ | `enum'] ‘object’ ObjectDef
+ | `enum' EnumDef
+ClassDef ::= id ClassConstr TemplateOpt ClassDef(mods, name, tparams, templ)
+ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
ConstrMods ::= AccessModifier
| Annotation {Annotation} (AccessModifier | ‘this’)
ObjectDef ::= id TemplateOpt ModuleDef(mods, name, template) // no constructor
+EnumDef ::= id ClassConstr [`extends' [ConstrApps]] EnumDef(mods, name, tparams, template)
+ [nl] ‘{’ EnumCaseStat {semi EnumCaseStat ‘}’
+EnumCaseStat ::= {Annotation [nl]} {Modifier} EnumCase
+EnumCase ::= `case' (EnumClassDef | ObjectDef)
+EnumClassDef ::= id [ClsTpeParamClause | ClsParamClause] ClassDef(mods, name, tparams, templ)
+ ClsParamClauses TemplateOpt
TemplateOpt ::= [‘extends’ Template | [nl] TemplateBody]
Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats)
ConstrApps ::= ConstrApp {‘with’ ConstrApp}