@@ -43,6 +43,7 @@ object Parsers {
43
43
enum Location (val inParens : Boolean , val inPattern : Boolean , val inArgs : Boolean ):
44
44
case InParens extends Location (true , false , false )
45
45
case InArgs extends Location (true , false , true )
46
+ case InColonArg extends Location (false , false , true )
46
47
case InPattern extends Location (false , true , false )
47
48
case InGuard extends Location (false , false , false )
48
49
case InPatternArgs extends Location (false , true , true ) // InParens not true, since it might be an alternative
@@ -431,7 +432,7 @@ object Parsers {
431
432
convertToParam(t, mods) :: Nil
432
433
case Tuple (ts) =>
433
434
ts.map(convertToParam(_, mods))
434
- case t : Typed =>
435
+ case t @ Typed ( Ident (_), _) =>
435
436
report.errorOrMigrationWarning(
436
437
em " parentheses are required around the parameter of a lambda ${rewriteNotice()}" ,
437
438
in.sourcePos(), from = `3.0`)
@@ -444,22 +445,24 @@ object Parsers {
444
445
445
446
/** Convert tree to formal parameter
446
447
*/
447
- def convertToParam (tree : Tree , mods : Modifiers , expected : String = " formal parameter" ): ValDef = tree match
448
- case param : ValDef =>
449
- param.withMods(param.mods | mods.flags)
450
- case id @ Ident (name) =>
451
- makeParameter(name.asTermName, TypeTree (), mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
452
- // the following three cases are needed only for 2.x parameters without enclosing parentheses
453
- case Typed (_, tpt : TypeBoundsTree ) =>
454
- syntaxError(s " not a legal $expected" , tree.span)
455
- makeParameter(nme.ERROR , tree, mods)
456
- case Typed (id @ Ident (name), tpt) =>
457
- makeParameter(name.asTermName, tpt, mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
458
- case Typed (Splice (Ident (name)), tpt) =>
459
- makeParameter((" $" + name).toTermName, tpt, mods).withSpan(tree.span)
460
- case _ =>
461
- syntaxError(s " not a legal $expected" , tree.span)
448
+ def convertToParam (tree : Tree , mods : Modifiers ): ValDef =
449
+ def fail () =
450
+ syntaxError(s " not a legal formal parameter for a function literal " , tree.span)
462
451
makeParameter(nme.ERROR , tree, mods)
452
+ tree match
453
+ case param : ValDef =>
454
+ param.withMods(param.mods | mods.flags)
455
+ case id @ Ident (name) =>
456
+ makeParameter(name.asTermName, TypeTree (), mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
457
+ // the following three cases are needed only for 2.x parameters without enclosing parentheses
458
+ case Typed (_, tpt : TypeBoundsTree ) =>
459
+ fail()
460
+ case Typed (id @ Ident (name), tpt) =>
461
+ makeParameter(name.asTermName, tpt, mods, isBackquoted = isBackquoted(id)).withSpan(tree.span)
462
+ case Typed (Splice (Ident (name)), tpt) =>
463
+ makeParameter((" $" + name).toTermName, tpt, mods).withSpan(tree.span)
464
+ case _ =>
465
+ fail()
463
466
464
467
/** Convert (qual)ident to type identifier
465
468
*/
@@ -893,9 +896,8 @@ object Parsers {
893
896
val next = in.lookahead.token
894
897
next == LBRACKET || next == LPAREN
895
898
896
-
897
899
def followingIsSelfType () =
898
- val lookahead = in.LookaheadScanner ()
900
+ val lookahead = in.LookaheadScanner (allowIndent = true )
899
901
lookahead.nextToken()
900
902
lookahead.token == COLON
901
903
&& {
@@ -917,10 +919,10 @@ object Parsers {
917
919
}
918
920
}
919
921
920
- /** When encountering a `:`, is that in the first binding of a lambda?
921
- * @pre location of the enclosing expression is `InParens`, so there is am open `(`.
922
+ /** When encountering a `:`, is that in the binding of a lambda?
923
+ * @pre location of the enclosing expression is `InParens`, so there is an open `(`.
922
924
*/
923
- def followingisLambdaParams () =
925
+ def followingIsLambdaParams () =
924
926
val lookahead = in.LookaheadScanner ()
925
927
lookahead.nextToken()
926
928
while lookahead.token != RPAREN && lookahead.token != EOF do
@@ -932,6 +934,28 @@ object Parsers {
932
934
lookahead.isArrow
933
935
}
934
936
937
+ /** Is the token sequence following the current `:` token classified as a lambda?
938
+ * This is the case if the input starts with an identifier, a wildcard, or
939
+ * something enclosed in (...) or [...], and this is followed by a `=>` or `?=>`
940
+ * and an INDENT.
941
+ */
942
+ def followingIsLambdaAfterColon (): Boolean =
943
+ val lookahead = in.LookaheadScanner (allowIndent = true )
944
+ def isArrowIndent () =
945
+ lookahead.isArrow
946
+ && {
947
+ lookahead.nextToken()
948
+ lookahead.token == INDENT
949
+ }
950
+ lookahead.nextToken()
951
+ if lookahead.isIdent || lookahead.token == USCORE then
952
+ lookahead.nextToken()
953
+ isArrowIndent()
954
+ else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
955
+ lookahead.skipParens()
956
+ isArrowIndent()
957
+ else false
958
+
935
959
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
936
960
937
961
var opStack : List [OpInfo ] = Nil
@@ -2226,7 +2250,11 @@ object Parsers {
2226
2250
in.nextToken()
2227
2251
else
2228
2252
accept(ARROW )
2229
- Function (params, if (location == Location .InBlock ) block() else expr())
2253
+ val body =
2254
+ if location == Location .InBlock then block()
2255
+ else if location == Location .InColonArg && in.token == INDENT then blockExpr()
2256
+ else expr()
2257
+ Function (params, body)
2230
2258
}
2231
2259
2232
2260
/** PostfixExpr ::= InfixExpr [id [nl]]
@@ -2276,9 +2304,11 @@ object Parsers {
2276
2304
* | SimpleExpr `.` MatchClause
2277
2305
* | SimpleExpr (TypeArgs | NamedTypeArgs)
2278
2306
* | SimpleExpr1 ArgumentExprs
2279
- * | SimpleExpr1 `:` IndentedExpr -- under language.experimental.fewerBraces
2280
- * | SimpleExpr1 FunParams (‘=>’ | ‘?=>’) IndentedExpr -- under language.experimental.fewerBraces
2281
- * IndentedExpr ::= indent (CaseClauses | Block) outdent
2307
+ * | SimpleExpr1 `:` ColonArgument -- under language.experimental.fewerBraces
2308
+ * ColonArgument ::= indent (CaseClauses | Block) outdent
2309
+ * | FunParams (‘=>’ | ‘?=>’) ColonArgBody
2310
+ * | HkTypeParamClause ‘=>’ ColonArgBody
2311
+ * ColonArgBody ::= indent (CaseClauses | Block) outdent
2282
2312
* Quoted ::= ‘'’ ‘{’ Block ‘}’
2283
2313
* | ‘'’ ‘[’ Type ‘]’
2284
2314
*/
@@ -2334,65 +2364,38 @@ object Parsers {
2334
2364
simpleExprRest(t, location, canApply)
2335
2365
}
2336
2366
2337
- def simpleExprRest (t : Tree , location : Location , canApply : Boolean = true ): Tree = {
2367
+ def simpleExprRest (t : Tree , location : Location , canApply : Boolean = true ): Tree =
2338
2368
if (canApply) argumentStart()
2339
- in.token match {
2369
+ in.token match
2340
2370
case DOT =>
2341
2371
in.nextToken()
2342
2372
simpleExprRest(selectorOrMatch(t), location, canApply = true )
2343
2373
case LBRACKET =>
2344
2374
val tapp = atSpan(startOffset(t), in.offset) { TypeApply (t, typeArgs(namedOK = true , wildOK = false )) }
2345
2375
simpleExprRest(tapp, location, canApply = true )
2346
- case LPAREN if canApply =>
2347
- val app = atSpan(startOffset(t), in.offset) {
2348
- val argExprs @ (args, isUsing) = argumentExprs()
2349
- if ! isUsing && in.isArrow && location != Location .InGuard && in.fewerBracesEnabled then
2350
- val params = convertToParams(Tuple (args))
2351
- if params.forall(_.name != nme.ERROR ) then
2352
- applyToClosure(t, in.offset, params)
2353
- else
2354
- mkApply(t, argExprs)
2355
- else
2356
- mkApply(t, argExprs)
2357
- }
2358
- simpleExprRest(app, location, canApply = true )
2359
- case LBRACE | INDENT if canApply =>
2376
+ case LPAREN | LBRACE | INDENT if canApply =>
2360
2377
val app = atSpan(startOffset(t), in.offset) { mkApply(t, argumentExprs()) }
2361
2378
simpleExprRest(app, location, canApply = true )
2362
2379
case USCORE =>
2363
- if in.lookahead.isArrow && location != Location .InGuard && in.fewerBracesEnabled then
2364
- val app = applyToClosure(t, in.offset, convertToParams(wildcardIdent()))
2365
- simpleExprRest(app, location, canApply = true )
2366
- else
2367
- atSpan(startOffset(t), in.skipToken()) { PostfixOp (t, Ident (nme.WILDCARD )) }
2368
- case IDENTIFIER
2369
- if ! in.isOperator && in.lookahead.isArrow && location != Location .InGuard && in.fewerBracesEnabled =>
2370
- val app = applyToClosure(t, in.offset, convertToParams(termIdent()))
2371
- simpleExprRest(app, location, canApply = true )
2380
+ atSpan(startOffset(t), in.skipToken()) { PostfixOp (t, Ident (nme.WILDCARD )) }
2372
2381
case _ =>
2373
- t match
2374
- case id @ Ident (name)
2375
- if in.isColon() && location == Location .InParens && followingisLambdaParams() =>
2376
- if name.is(WildcardParamName ) then
2377
- assert(name == placeholderParams.head.name)
2378
- placeholderParams = placeholderParams.tail
2379
- atSpan(startOffset(id)) {
2380
- makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2381
- }
2382
- case _ =>
2383
- t
2384
- }
2385
- }
2386
-
2387
- def applyToClosure (t : Tree , start : Offset , params : List [ValDef ]): Tree =
2388
- atSpan(startOffset(t), in.offset) {
2389
- val arg = atSpan(start, in.skipToken()) {
2390
- if in.token != INDENT then
2391
- syntaxErrorOrIncomplete(i " indented expression expected, ${in} found " )
2392
- Function (params, blockExpr())
2393
- }
2394
- Apply (t, arg)
2395
- }
2382
+ if in.isColon() && location == Location .InParens && followingIsLambdaParams() then
2383
+ t match
2384
+ case id @ Ident (name) =>
2385
+ if name.is(WildcardParamName ) then
2386
+ assert(name == placeholderParams.head.name)
2387
+ placeholderParams = placeholderParams.tail
2388
+ atSpan(startOffset(id)) {
2389
+ makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2390
+ }
2391
+ case _ => t
2392
+ else if in.fewerBracesEnabled && in.token == COLON && followingIsLambdaAfterColon() then
2393
+ val app = atSpan(startOffset(t), in.skipToken()) {
2394
+ Apply (t, expr(Location .InColonArg ) :: Nil )
2395
+ }
2396
+ simpleExprRest(app, location, canApply = true )
2397
+ else t
2398
+ end simpleExprRest
2396
2399
2397
2400
/** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody]
2398
2401
* | ‘new’ TemplateBody
0 commit comments