@@ -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,20 +445,22 @@ 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 _ =>
459
- 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)
460
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 _ =>
463
+ fail()
461
464
462
465
/** Convert (qual)ident to type identifier
463
466
*/
@@ -891,9 +894,8 @@ object Parsers {
891
894
val next = in.lookahead.token
892
895
next == LBRACKET || next == LPAREN
893
896
894
-
895
897
def followingIsSelfType () =
896
- val lookahead = in.LookaheadScanner ()
898
+ val lookahead = in.LookaheadScanner (allowIndent = true )
897
899
lookahead.nextToken()
898
900
lookahead.token == COLON
899
901
&& {
@@ -915,10 +917,10 @@ object Parsers {
915
917
}
916
918
}
917
919
918
- /** When encountering a `:`, is that in the first binding of a lambda?
919
- * @pre location of the enclosing expression is `InParens`, so there is am open `(`.
920
+ /** When encountering a `:`, is that in the binding of a lambda?
921
+ * @pre location of the enclosing expression is `InParens`, so there is an open `(`.
920
922
*/
921
- def followingisLambdaParams () =
923
+ def followingIsLambdaParams () =
922
924
val lookahead = in.LookaheadScanner ()
923
925
lookahead.nextToken()
924
926
while lookahead.token != RPAREN && lookahead.token != EOF do
@@ -930,6 +932,28 @@ object Parsers {
930
932
lookahead.isArrow
931
933
}
932
934
935
+ /** Is the token sequence following the current `:` token classified as a lambda?
936
+ * This is the case if the input starts with an identifier, a wildcard, or
937
+ * something enclosed in (...) or [...], and this is followed by a `=>` or `?=>`
938
+ * and an INDENT.
939
+ */
940
+ def followingIsLambdaAfterColon (): Boolean =
941
+ val lookahead = in.LookaheadScanner (allowIndent = true )
942
+ def isArrowIndent () =
943
+ lookahead.isArrow
944
+ && {
945
+ lookahead.nextToken()
946
+ lookahead.token == INDENT
947
+ }
948
+ lookahead.nextToken()
949
+ if lookahead.isIdent || lookahead.token == USCORE then
950
+ lookahead.nextToken()
951
+ isArrowIndent()
952
+ else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
953
+ lookahead.skipParens()
954
+ isArrowIndent()
955
+ else false
956
+
933
957
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
934
958
935
959
var opStack : List [OpInfo ] = Nil
@@ -2235,7 +2259,11 @@ object Parsers {
2235
2259
in.nextToken()
2236
2260
else
2237
2261
accept(ARROW )
2238
- Function (params, if (location == Location .InBlock ) block() else expr())
2262
+ val body =
2263
+ if location == Location .InBlock then block()
2264
+ else if location == Location .InColonArg && in.token == INDENT then blockExpr()
2265
+ else expr()
2266
+ Function (params, body)
2239
2267
}
2240
2268
2241
2269
/** PostfixExpr ::= InfixExpr [id [nl]]
@@ -2285,9 +2313,11 @@ object Parsers {
2285
2313
* | SimpleExpr `.` MatchClause
2286
2314
* | SimpleExpr (TypeArgs | NamedTypeArgs)
2287
2315
* | SimpleExpr1 ArgumentExprs
2288
- * | SimpleExpr1 `:` IndentedExpr -- under language.experimental.fewerBraces
2289
- * | SimpleExpr1 FunParams (‘=>’ | ‘?=>’) IndentedExpr -- under language.experimental.fewerBraces
2290
- * IndentedExpr ::= indent (CaseClauses | Block) outdent
2316
+ * | SimpleExpr1 `:` ColonArgument -- under language.experimental.fewerBraces
2317
+ * ColonArgument ::= indent (CaseClauses | Block) outdent
2318
+ * | FunParams (‘=>’ | ‘?=>’) ColonArgBody
2319
+ * | HkTypeParamClause ‘=>’ ColonArgBody
2320
+ * ColonArgBody ::= indent (CaseClauses | Block) outdent
2291
2321
* Quoted ::= ‘'’ ‘{’ Block ‘}’
2292
2322
* | ‘'’ ‘[’ Type ‘]’
2293
2323
*/
@@ -2343,65 +2373,38 @@ object Parsers {
2343
2373
simpleExprRest(t, location, canApply)
2344
2374
}
2345
2375
2346
- def simpleExprRest (t : Tree , location : Location , canApply : Boolean = true ): Tree = {
2376
+ def simpleExprRest (t : Tree , location : Location , canApply : Boolean = true ): Tree =
2347
2377
if (canApply) argumentStart()
2348
- in.token match {
2378
+ in.token match
2349
2379
case DOT =>
2350
2380
in.nextToken()
2351
2381
simpleExprRest(selectorOrMatch(t), location, canApply = true )
2352
2382
case LBRACKET =>
2353
2383
val tapp = atSpan(startOffset(t), in.offset) { TypeApply (t, typeArgs(namedOK = true , wildOK = false )) }
2354
2384
simpleExprRest(tapp, location, canApply = true )
2355
- case LPAREN if canApply =>
2356
- val app = atSpan(startOffset(t), in.offset) {
2357
- val argExprs @ (args, isUsing) = argumentExprs()
2358
- if ! isUsing && in.isArrow && location != Location .InGuard && in.fewerBracesEnabled then
2359
- val params = convertToParams(Tuple (args))
2360
- if params.forall(_.name != nme.ERROR ) then
2361
- applyToClosure(t, in.offset, params)
2362
- else
2363
- mkApply(t, argExprs)
2364
- else
2365
- mkApply(t, argExprs)
2366
- }
2367
- simpleExprRest(app, location, canApply = true )
2368
- case LBRACE | INDENT if canApply =>
2385
+ case LPAREN | LBRACE | INDENT if canApply =>
2369
2386
val app = atSpan(startOffset(t), in.offset) { mkApply(t, argumentExprs()) }
2370
2387
simpleExprRest(app, location, canApply = true )
2371
2388
case USCORE =>
2372
- if in.lookahead.isArrow && location != Location .InGuard && in.fewerBracesEnabled then
2373
- val app = applyToClosure(t, in.offset, convertToParams(wildcardIdent()))
2374
- simpleExprRest(app, location, canApply = true )
2375
- else
2376
- atSpan(startOffset(t), in.skipToken()) { PostfixOp (t, Ident (nme.WILDCARD )) }
2377
- case IDENTIFIER
2378
- if ! in.isOperator && in.lookahead.isArrow && location != Location .InGuard && in.fewerBracesEnabled =>
2379
- val app = applyToClosure(t, in.offset, convertToParams(termIdent()))
2380
- simpleExprRest(app, location, canApply = true )
2389
+ atSpan(startOffset(t), in.skipToken()) { PostfixOp (t, Ident (nme.WILDCARD )) }
2381
2390
case _ =>
2382
- t match
2383
- case id @ Ident (name)
2384
- if in.isColon() && location == Location .InParens && followingisLambdaParams() =>
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 _ =>
2392
- t
2393
- }
2394
- }
2395
-
2396
- def applyToClosure (t : Tree , start : Offset , params : List [ValDef ]): Tree =
2397
- atSpan(startOffset(t), in.offset) {
2398
- val arg = atSpan(start, in.skipToken()) {
2399
- if in.token != INDENT then
2400
- syntaxErrorOrIncomplete(i " indented expression expected, ${in} found " )
2401
- Function (params, blockExpr())
2402
- }
2403
- Apply (t, arg)
2404
- }
2391
+ if in.isColon() && location == Location .InParens && followingIsLambdaParams() then
2392
+ t match
2393
+ case id @ Ident (name) =>
2394
+ if name.is(WildcardParamName ) then
2395
+ assert(name == placeholderParams.head.name)
2396
+ placeholderParams = placeholderParams.tail
2397
+ atSpan(startOffset(id)) {
2398
+ makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2399
+ }
2400
+ case _ => t
2401
+ else if in.fewerBracesEnabled && in.token == COLON && followingIsLambdaAfterColon() then
2402
+ val app = atSpan(startOffset(t), in.skipToken()) {
2403
+ Apply (t, expr(Location .InColonArg ) :: Nil )
2404
+ }
2405
+ simpleExprRest(app, location, canApply = true )
2406
+ else t
2407
+ end simpleExprRest
2405
2408
2406
2409
/** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody]
2407
2410
* | ‘new’ TemplateBody
0 commit comments