Skip to content

Commit a6f8167

Browse files
committed
Simplify parameter handling in Parser
1 parent 06c925b commit a6f8167

File tree

1 file changed

+63
-60
lines changed

1 file changed

+63
-60
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,23 @@ object Parsers {
5151
case ElseWhere extends Location(false, false, false)
5252

5353
enum ParamOwner:
54-
case Class, Type, TypeParam, Def
54+
case Class // class or trait or enum
55+
case CaseClass // case class or enum case
56+
case Type // type alias or abstract type
57+
case TypeParam // type parameter
58+
case Def // method
59+
case Given // given definition
60+
case ExtensionPrefix // extension clause, up to and including extension parameter
61+
case ExtensionFollow // extension clause, following extension parameter
62+
63+
def isClass = // owner is a class
64+
this == Class || this == CaseClass
65+
def takesOnlyUsingClauses = // only using clauses allowed for this owner
66+
this == Given || this == ExtensionFollow
67+
def acceptsVariance =
68+
this == Class || this == CaseClass || this == Type
69+
70+
end ParamOwner
5571

5672
enum ParseKind:
5773
case Expr, Type, Pattern
@@ -3214,33 +3230,29 @@ object Parsers {
32143230
* | UsingParamClause
32153231
*/
32163232
def typeOrTermParamClauses(
3217-
ownerKind: ParamOwner,
3218-
numLeadParams: Int = 0
3219-
): List[List[TypeDef] | List[ValDef]] =
3233+
paramOwner: ParamOwner, numLeadParams: Int = 0): List[List[TypeDef] | List[ValDef]] =
32203234

3221-
def recur(firstClause: Boolean, numLeadParams: Int, prevIsTypeClause: Boolean): List[List[TypeDef] | List[ValDef]] =
3235+
def recur(numLeadParams: Int, firstClause: Boolean, prevIsTypeClause: Boolean): List[List[TypeDef] | List[ValDef]] =
32223236
newLineOptWhenFollowedBy(LPAREN)
32233237
newLineOptWhenFollowedBy(LBRACKET)
32243238
if in.token == LPAREN then
32253239
val paramsStart = in.offset
3226-
val params = termParamClause(
3227-
numLeadParams,
3228-
firstClause = firstClause)
3240+
val params = termParamClause(paramOwner, numLeadParams, firstClause)
32293241
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit)
32303242
params :: (
32313243
if lastClause then Nil
3232-
else recur(firstClause = false, numLeadParams + params.length, prevIsTypeClause = false))
3244+
else recur(numLeadParams + params.length, firstClause = false, prevIsTypeClause = false))
32333245
else if in.token == LBRACKET then
32343246
if prevIsTypeClause then
32353247
syntaxError(
32363248
em"Type parameter lists must be separated by a term or using parameter list",
32373249
in.offset
32383250
)
3239-
typeParamClause(ownerKind) :: recur(firstClause, numLeadParams, prevIsTypeClause = true)
3251+
typeParamClause(paramOwner) :: recur(numLeadParams, firstClause, prevIsTypeClause = true)
32403252
else Nil
32413253
end recur
32423254

3243-
recur(firstClause = true, numLeadParams = numLeadParams, prevIsTypeClause = false)
3255+
recur(numLeadParams, firstClause = true, prevIsTypeClause = false)
32443256
end typeOrTermParamClauses
32453257

32463258

@@ -3259,19 +3271,20 @@ object Parsers {
32593271
* HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
32603272
* HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypePamClause] | ‘_’) TypeBounds
32613273
*/
3262-
def typeParamClause(ownerKind: ParamOwner): List[TypeDef] = inBracketsWithCommas {
3274+
def typeParamClause(paramOwner: ParamOwner): List[TypeDef] = inBracketsWithCommas {
32633275

32643276
def checkVarianceOK(): Boolean =
3265-
val ok = ownerKind != ParamOwner.Def && ownerKind != ParamOwner.TypeParam
3277+
val ok = paramOwner.acceptsVariance
32663278
if !ok then syntaxError(em"no `+/-` variance annotation allowed here")
32673279
in.nextToken()
32683280
ok
32693281

32703282
def typeParam(): TypeDef = {
3271-
val isAbstractOwner = ownerKind == ParamOwner.Type || ownerKind == ParamOwner.TypeParam
3283+
val isAbstractOwner = paramOwner == ParamOwner.Type || paramOwner == ParamOwner.TypeParam
32723284
val start = in.offset
32733285
var mods = annotsAsMods() | Param
3274-
if ownerKind == ParamOwner.Class then mods |= PrivateLocal
3286+
if paramOwner == ParamOwner.Class || paramOwner == ParamOwner.CaseClass then
3287+
mods |= PrivateLocal
32753288
if isIdent(nme.raw.PLUS) && checkVarianceOK() then
32763289
mods |= Covariant
32773290
else if isIdent(nme.raw.MINUS) && checkVarianceOK() then
@@ -3291,16 +3304,16 @@ object Parsers {
32913304
commaSeparated(() => typeParam())
32923305
}
32933306

3294-
def typeParamClauseOpt(ownerKind: ParamOwner): List[TypeDef] =
3295-
if (in.token == LBRACKET) typeParamClause(ownerKind) else Nil
3307+
def typeParamClauseOpt(paramOwner: ParamOwner): List[TypeDef] =
3308+
if (in.token == LBRACKET) typeParamClause(paramOwner) else Nil
32963309

32973310
/** ContextTypes ::= FunArgType {‘,’ FunArgType}
32983311
*/
3299-
def contextTypes(ofClass: Boolean, numLeadParams: Int, impliedMods: Modifiers): List[ValDef] =
3312+
def contextTypes(paramOwner: ParamOwner, numLeadParams: Int, impliedMods: Modifiers): List[ValDef] =
33003313
val tps = commaSeparated(funArgType)
33013314
var counter = numLeadParams
33023315
def nextIdx = { counter += 1; counter }
3303-
val paramFlags = if ofClass then LocalParamAccessor else Param
3316+
val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
33043317
tps.map(makeSyntheticParameter(nextIdx, _, paramFlags | Synthetic | impliedMods.flags))
33053318

33063319
/** ClsTermParamClause ::= ‘(’ ClsParams ‘)’ | UsingClsTermParamClause
@@ -3322,11 +3335,8 @@ object Parsers {
33223335
* @return the list of parameter definitions
33233336
*/
33243337
def termParamClause(
3338+
paramOwner: ParamOwner,
33253339
numLeadParams: Int, // number of parameters preceding this clause
3326-
ofClass: Boolean = false, // owner is a class
3327-
ofCaseClass: Boolean = false, // owner is a case class
3328-
prefix: Boolean = false, // clause precedes name of an extension method
3329-
givenOnly: Boolean = false, // only given parameters allowed
33303340
firstClause: Boolean = false // clause is the first in regular list of clauses
33313341
): List[ValDef] = {
33323342
var impliedMods: Modifiers = EmptyModifiers
@@ -3345,7 +3355,7 @@ object Parsers {
33453355
var mods = impliedMods.withAnnotations(annotations())
33463356
if isErasedKw then
33473357
mods = addModifier(mods)
3348-
if (ofClass) {
3358+
if paramOwner.isClass then
33493359
mods = addFlag(modifiers(start = mods), ParamAccessor)
33503360
mods =
33513361
if in.token == VAL then
@@ -3357,9 +3367,8 @@ object Parsers {
33573367
else
33583368
if (!(mods.flags &~ (ParamAccessor | Inline | Erased | impliedMods.flags)).isEmpty)
33593369
syntaxError(em"`val` or `var` expected")
3360-
if (firstClause && ofCaseClass) mods
3370+
if firstClause && paramOwner == ParamOwner.CaseClass then mods
33613371
else mods | PrivateLocal
3362-
}
33633372
else {
33643373
if (isIdent(nme.inline) && in.isSoftModifierInParamModifierPosition)
33653374
mods = addModifier(mods)
@@ -3368,7 +3377,7 @@ object Parsers {
33683377
atSpan(start, nameStart) {
33693378
val name = ident()
33703379
acceptColon()
3371-
if (in.token == ARROW && ofClass && !mods.is(Local))
3380+
if (in.token == ARROW && paramOwner.isClass && !mods.is(Local))
33723381
syntaxError(VarValParametersMayNotBeCallByName(name, mods.is(Mutable)))
33733382
// needed?, it's checked later anyway
33743383
val tpt = paramType()
@@ -3397,13 +3406,17 @@ object Parsers {
33973406

33983407
// begin termParamClause
33993408
inParensWithCommas {
3400-
if in.token == RPAREN && !prefix && !impliedMods.is(Given) then Nil
3409+
if in.token == RPAREN && paramOwner != ParamOwner.ExtensionPrefix && !impliedMods.is(Given)
3410+
then Nil
34013411
else
34023412
val clause =
3403-
if prefix && !isIdent(nme.using) && !isIdent(nme.erased) then param() :: Nil
3413+
if paramOwner == ParamOwner.ExtensionPrefix
3414+
&& !isIdent(nme.using) && !isIdent(nme.erased)
3415+
then
3416+
param() :: Nil
34043417
else
34053418
paramMods()
3406-
if givenOnly && !impliedMods.is(Given) then
3419+
if paramOwner.takesOnlyUsingClauses && !impliedMods.is(Given) then
34073420
syntaxError(em"`using` expected")
34083421
val (firstParamMod, isParams) =
34093422
var mods = EmptyModifiers
@@ -3417,7 +3430,7 @@ object Parsers {
34173430
|| isIdent && (in.name == nme.inline || in.lookahead.isColon)
34183431
(mods, isParams)
34193432
(if isParams then commaSeparated(() => param())
3420-
else contextTypes(ofClass, numLeadParams, impliedMods)) match {
3433+
else contextTypes(paramOwner, numLeadParams, impliedMods)) match {
34213434
case Nil => Nil
34223435
case (h :: t) => h.withAddedFlags(firstParamMod.flags) :: t
34233436
}
@@ -3431,31 +3444,21 @@ object Parsers {
34313444
*
34323445
* @return The parameter definitions
34333446
*/
3434-
def termParamClauses(
3435-
ofClass: Boolean = false,
3436-
ofCaseClass: Boolean = false,
3437-
givenOnly: Boolean = false,
3438-
numLeadParams: Int = 0
3439-
): List[List[ValDef]] =
3447+
def termParamClauses(paramOwner: ParamOwner, numLeadParams: Int = 0): List[List[ValDef]] =
34403448

3441-
def recur(firstClause: Boolean, numLeadParams: Int): List[List[ValDef]] =
3449+
def recur(numLeadParams: Int, firstClause: Boolean): List[List[ValDef]] =
34423450
newLineOptWhenFollowedBy(LPAREN)
34433451
if in.token == LPAREN then
34443452
val paramsStart = in.offset
3445-
val params = termParamClause(
3446-
numLeadParams,
3447-
ofClass = ofClass,
3448-
ofCaseClass = ofCaseClass,
3449-
givenOnly = givenOnly,
3450-
firstClause = firstClause)
3453+
val params = termParamClause(paramOwner, numLeadParams, firstClause)
34513454
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit)
34523455
params :: (
34533456
if lastClause then Nil
3454-
else recur(firstClause = false, numLeadParams + params.length))
3457+
else recur(numLeadParams + params.length, firstClause = false))
34553458
else Nil
34563459
end recur
34573460

3458-
recur(firstClause = true, numLeadParams)
3461+
recur(numLeadParams, firstClause = true)
34593462
end termParamClauses
34603463

34613464
/* -------- DEFS ------------------------------------------- */
@@ -3727,7 +3730,7 @@ object Parsers {
37273730

37283731
if (in.token == THIS) {
37293732
in.nextToken()
3730-
val vparamss = termParamClauses(numLeadParams = numLeadParams)
3733+
val vparamss = termParamClauses(ParamOwner.Def, numLeadParams)
37313734
if (vparamss.isEmpty || vparamss.head.take(1).exists(_.mods.isOneOf(GivenOrImplicit)))
37323735
in.token match {
37333736
case LBRACKET => syntaxError(em"no type parameters allowed here")
@@ -3748,10 +3751,10 @@ object Parsers {
37483751
val paramss =
37493752
if in.featureEnabled(Feature.clauseInterleaving) then
37503753
// If you are making interleaving stable manually, please refer to the PR introducing it instead, section "How to make non-experimental"
3751-
typeOrTermParamClauses(ParamOwner.Def, numLeadParams = numLeadParams)
3754+
typeOrTermParamClauses(ParamOwner.Def, numLeadParams)
37523755
else
37533756
val tparams = typeParamClauseOpt(ParamOwner.Def)
3754-
val vparamss = termParamClauses(numLeadParams = numLeadParams)
3757+
val vparamss = termParamClauses(ParamOwner.Def, numLeadParams)
37553758

37563759
joinParams(tparams, vparamss)
37573760

@@ -3892,16 +3895,16 @@ object Parsers {
38923895
}
38933896

38943897
def classDefRest(start: Offset, mods: Modifiers, name: TypeName): TypeDef =
3895-
val constr = classConstr(isCaseClass = mods.is(Case))
3898+
val constr = classConstr(if mods.is(Case) then ParamOwner.CaseClass else ParamOwner.Class)
38963899
val templ = templateOpt(constr)
38973900
finalizeDef(TypeDef(name, templ), mods, start)
38983901

38993902
/** ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsTermParamClauses
39003903
*/
3901-
def classConstr(isCaseClass: Boolean = false): DefDef = atSpan(in.lastOffset) {
3902-
val tparams = typeParamClauseOpt(ParamOwner.Class)
3904+
def classConstr(paramOwner: ParamOwner): DefDef = atSpan(in.lastOffset) {
3905+
val tparams = typeParamClauseOpt(paramOwner)
39033906
val cmods = fromWithinClassConstr(constrModsOpt())
3904-
val vparamss = termParamClauses(ofClass = true, ofCaseClass = isCaseClass)
3907+
val vparamss = termParamClauses(paramOwner)
39053908
makeConstructor(tparams, vparamss).withMods(cmods)
39063909
}
39073910

@@ -3930,7 +3933,7 @@ object Parsers {
39303933
val mods1 = checkAccessOnly(mods, "definitions")
39313934
val modulName = ident()
39323935
val clsName = modulName.toTypeName
3933-
val constr = classConstr()
3936+
val constr = classConstr(ParamOwner.Class)
39343937
val templ = template(constr, isEnum = true)
39353938
finalizeDef(TypeDef(clsName, templ), mods1, start)
39363939
}
@@ -3952,7 +3955,7 @@ object Parsers {
39523955
val caseDef =
39533956
if (in.token == LBRACKET || in.token == LPAREN || in.token == AT || isModifier) {
39543957
val clsName = id.name.toTypeName
3955-
val constr = classConstr(isCaseClass = true)
3958+
val constr = classConstr(ParamOwner.CaseClass)
39563959
TypeDef(clsName, caseTemplate(constr))
39573960
}
39583961
else
@@ -3999,11 +4002,11 @@ object Parsers {
39994002
val name = if isIdent && followingIsGivenSig() then ident() else EmptyTermName
40004003

40014004
val gdef =
4002-
val tparams = typeParamClauseOpt(ParamOwner.Def)
4005+
val tparams = typeParamClauseOpt(ParamOwner.Given)
40034006
newLineOpt()
40044007
val vparamss =
40054008
if in.token == LPAREN && in.lookahead.isIdent(nme.using)
4006-
then termParamClauses(givenOnly = true)
4009+
then termParamClauses(ParamOwner.Given)
40074010
else Nil
40084011
newLinesOpt()
40094012
val noParams = tparams.isEmpty && vparamss.isEmpty
@@ -4043,15 +4046,15 @@ object Parsers {
40434046
*/
40444047
def extension(): ExtMethods =
40454048
val start = in.skipToken()
4046-
val tparams = typeParamClauseOpt(ParamOwner.Def)
4049+
val tparams = typeParamClauseOpt(ParamOwner.ExtensionPrefix)
40474050
val leadParamss = ListBuffer[List[ValDef]]()
40484051
def numLeadParams = leadParamss.map(_.length).sum
40494052
while
4050-
val extParams = termParamClause(numLeadParams, prefix = true)
4053+
val extParams = termParamClause(ParamOwner.ExtensionPrefix, numLeadParams)
40514054
leadParamss += extParams
40524055
isUsingClause(extParams)
40534056
do ()
4054-
leadParamss ++= termParamClauses(givenOnly = true, numLeadParams = numLeadParams)
4057+
leadParamss ++= termParamClauses(ParamOwner.ExtensionFollow, numLeadParams)
40554058
if in.isColon then
40564059
syntaxError(em"no `:` expected here")
40574060
in.nextToken()

0 commit comments

Comments
 (0)