@@ -2307,9 +2307,59 @@ object Parsers {
2307
2307
def paramClauses (ofClass : Boolean = false ,
2308
2308
ofCaseClass : Boolean = false ,
2309
2309
ofInstance : Boolean = false ): List [List [ValDef ]] = {
2310
+
2311
+ def followingIsParamClause : Boolean = {
2312
+ val lookahead = in.lookaheadScanner
2313
+ lookahead.nextToken()
2314
+ paramIntroTokens.contains(lookahead.token) && {
2315
+ lookahead.token != IDENTIFIER ||
2316
+ lookahead.name == nme.inline || {
2317
+ lookahead.nextToken()
2318
+ lookahead.token == COLON
2319
+ }
2320
+ }
2321
+ }
2322
+
2323
+ /** For given instance definitions we have a disambiguation problem:
2324
+ * given A as B
2325
+ * given C ...
2326
+ * Is the second line a parameter `given C` for the first `given` definition, or is it
2327
+ * a second `given` definition? We only know if we find a `for` or `as` in `...`
2328
+ * The same problem arises for
2329
+ * class A
2330
+ * given C ...
2331
+ * For method definitions we do not have this problem since a parameter clause
2332
+ * in a method definition is always followed by something else. So in
2333
+ * def m(...)
2334
+ * given C ...
2335
+ * we know that `given` must start a parameter list. It cannot be a new given` definition.
2336
+ */
2337
+ def followingIsInstanceDef =
2338
+ (ofClass || ofInstance) && {
2339
+ val lookahead = in.lookaheadScanner // skips newline on startup
2340
+ lookahead.nextToken() // skip the `given`
2341
+ if (lookahead.token == IDENTIFIER || lookahead.token == BACKQUOTED_IDENT ) {
2342
+ lookahead.nextToken()
2343
+ if (lookahead.token == LBRACKET ) {
2344
+ lookahead.nextToken()
2345
+ var openBrackets = 1
2346
+ while (openBrackets > 0 && lookahead.token != EOF ) {
2347
+ if (lookahead.token == LBRACKET ) openBrackets += 1
2348
+ else if (lookahead.token == RBRACKET ) openBrackets -= 1
2349
+ lookahead.nextToken()
2350
+ }
2351
+ }
2352
+ }
2353
+ lookahead.token == FOR ||
2354
+ lookahead.token == IDENTIFIER && lookahead.name == nme.as
2355
+ }
2356
+
2310
2357
def recur (firstClause : Boolean , nparams : Int , contextualOnly : Boolean ): List [List [ValDef ]] = {
2311
2358
var initialMods = EmptyModifiers
2359
+ val isNewLine = in.token == NEWLINE
2312
2360
newLineOptWhenFollowedBy(LPAREN )
2361
+ if (in.token == NEWLINE && in.next.token == GIVEN && ! followingIsInstanceDef)
2362
+ in.nextToken()
2313
2363
if (in.token == GIVEN ) {
2314
2364
in.nextToken()
2315
2365
initialMods |= Given
@@ -2318,22 +2368,10 @@ object Parsers {
2318
2368
in.nextToken()
2319
2369
initialMods |= Erased
2320
2370
}
2321
- val isContextual = initialMods.is(Given )
2371
+ val isGiven = initialMods.is(Given )
2322
2372
newLineOptWhenFollowedBy(LPAREN )
2323
- def isParamClause : Boolean =
2324
- ! isContextual || {
2325
- val lookahead = in.lookaheadScanner
2326
- lookahead.nextToken()
2327
- paramIntroTokens.contains(lookahead.token) && {
2328
- lookahead.token != IDENTIFIER ||
2329
- lookahead.name == nme.inline || {
2330
- lookahead.nextToken()
2331
- lookahead.token == COLON
2332
- }
2333
- }
2334
- }
2335
- if (in.token == LPAREN && isParamClause) {
2336
- if (contextualOnly && ! isContextual)
2373
+ if (in.token == LPAREN && (! isGiven || followingIsParamClause)) {
2374
+ if (contextualOnly && ! isGiven)
2337
2375
if (ofInstance) syntaxError(em " parameters of instance definitions must come after `given' " )
2338
2376
else syntaxError(em " normal parameters cannot come after `given' clauses " )
2339
2377
val params = paramClause(
@@ -2342,15 +2380,15 @@ object Parsers {
2342
2380
firstClause = firstClause,
2343
2381
initialMods = initialMods)
2344
2382
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit )
2345
- params :: (if (lastClause) Nil else recur(firstClause = false , nparams + params.length, isContextual ))
2383
+ params :: (if (lastClause) Nil else recur(firstClause = false , nparams + params.length, isGiven ))
2346
2384
}
2347
- else if (isContextual ) {
2385
+ else if (isGiven ) {
2348
2386
val tps = commaSeparated(() => annotType())
2349
2387
var counter = nparams
2350
2388
def nextIdx = { counter += 1 ; counter }
2351
2389
val paramFlags = if (ofClass) Private | Local | ParamAccessor else Param
2352
2390
val params = tps.map(makeSyntheticParameter(nextIdx, _, paramFlags | Synthetic | Given ))
2353
- params :: recur(firstClause = false , nparams + params.length, isContextual )
2391
+ params :: recur(firstClause = false , nparams + params.length, isGiven )
2354
2392
}
2355
2393
else Nil
2356
2394
}
@@ -2819,7 +2857,7 @@ object Parsers {
2819
2857
val name = if (isIdent && (! newStyle || in.name != nme.as)) ident() else EmptyTermName
2820
2858
val tparams = typeParamClauseOpt(ParamOwner .Def )
2821
2859
val parents =
2822
- if (! newStyle && in.token == FOR || newStyle && isIdent(nme.as)) {
2860
+ if (! newStyle && in.token == FOR || isIdent(nme.as)) { // for the moment, accept both `given for` and `given as`
2823
2861
in.nextToken()
2824
2862
tokenSeparated(COMMA , constrApp)
2825
2863
}
0 commit comments