@@ -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
@@ -893,9 +894,8 @@ object Parsers {
893
894
val next = in.lookahead.token
894
895
next == LBRACKET || next == LPAREN
895
896
896
-
897
897
def followingIsSelfType () =
898
- val lookahead = in.LookaheadScanner ()
898
+ val lookahead = in.LookaheadScanner (allowIndent = true )
899
899
lookahead.nextToken()
900
900
lookahead.token == COLON
901
901
&& {
@@ -917,10 +917,10 @@ object Parsers {
917
917
}
918
918
}
919
919
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 `(`.
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 `(`.
922
922
*/
923
- def followingisLambdaParams () =
923
+ def followingIsLambdaParams () =
924
924
val lookahead = in.LookaheadScanner ()
925
925
lookahead.nextToken()
926
926
while lookahead.token != RPAREN && lookahead.token != EOF do
@@ -932,6 +932,21 @@ object Parsers {
932
932
lookahead.isArrow
933
933
}
934
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
+ */
939
+ def followingIsLambdaAfterColon (): Boolean =
940
+ val lookahead = in.LookaheadScanner ()
941
+ lookahead.nextToken()
942
+ if lookahead.isIdent || lookahead.token == USCORE then
943
+ lookahead.nextToken()
944
+ lookahead.isArrow
945
+ else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
946
+ lookahead.skipParens()
947
+ lookahead.isArrow
948
+ else false
949
+
935
950
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
936
951
937
952
var opStack : List [OpInfo ] = Nil
@@ -2229,7 +2244,17 @@ object Parsers {
2229
2244
in.nextToken()
2230
2245
else
2231
2246
accept(ARROW )
2232
- Function (params, if (location == Location .InBlock ) block() else expr())
2247
+ val body =
2248
+ if location == Location .InBlock then block()
2249
+ else if location == Location .InColonArg then
2250
+ if in.token == INDENT then
2251
+ blockExpr()
2252
+ else
2253
+ in.insertMaxIndent()
2254
+ try casesOrBlock(simplify = true )
2255
+ finally accept(OUTDENT )
2256
+ else expr()
2257
+ Function (params, body)
2233
2258
}
2234
2259
2235
2260
/** PostfixExpr ::= InfixExpr [id [nl]]
@@ -2279,9 +2304,12 @@ object Parsers {
2279
2304
* | SimpleExpr `.` MatchClause
2280
2305
* | SimpleExpr (TypeArgs | NamedTypeArgs)
2281
2306
* | SimpleExpr1 ArgumentExprs
2282
- * | SimpleExpr1 `:` IndentedExpr -- under language.experimental.fewerBraces
2283
- * | SimpleExpr1 FunParams (‘=>’ | ‘?=>’) IndentedExpr -- under language.experimental.fewerBraces
2284
- * 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
2312
+ * | <silent-indent> (CaseClauses | Block) outdent -- silent-indent is inserted by Scanner if no real indent is found
2285
2313
* Quoted ::= ‘'’ ‘{’ Block ‘}’
2286
2314
* | ‘'’ ‘[’ Type ‘]’
2287
2315
*/
@@ -2337,65 +2365,38 @@ object Parsers {
2337
2365
simpleExprRest(t, location, canApply)
2338
2366
}
2339
2367
2340
- def simpleExprRest (t : Tree , location : Location , canApply : Boolean = true ): Tree = {
2368
+ def simpleExprRest (t : Tree , location : Location , canApply : Boolean = true ): Tree =
2341
2369
if (canApply) argumentStart()
2342
- in.token match {
2370
+ in.token match
2343
2371
case DOT =>
2344
2372
in.nextToken()
2345
2373
simpleExprRest(selectorOrMatch(t), location, canApply = true )
2346
2374
case LBRACKET =>
2347
2375
val tapp = atSpan(startOffset(t), in.offset) { TypeApply (t, typeArgs(namedOK = true , wildOK = false )) }
2348
2376
simpleExprRest(tapp, location, canApply = true )
2349
- case LPAREN if canApply =>
2350
- val app = atSpan(startOffset(t), in.offset) {
2351
- val argExprs @ (args, isUsing) = argumentExprs()
2352
- if ! isUsing && in.isArrow && location != Location .InGuard && in.fewerBracesEnabled then
2353
- val params = convertToParams(Tuple (args))
2354
- if params.forall(_.name != nme.ERROR ) then
2355
- applyToClosure(t, in.offset, params)
2356
- else
2357
- mkApply(t, argExprs)
2358
- else
2359
- mkApply(t, argExprs)
2360
- }
2361
- simpleExprRest(app, location, canApply = true )
2362
- case LBRACE | INDENT if canApply =>
2377
+ case LPAREN | LBRACE | INDENT if canApply =>
2363
2378
val app = atSpan(startOffset(t), in.offset) { mkApply(t, argumentExprs()) }
2364
2379
simpleExprRest(app, location, canApply = true )
2365
2380
case USCORE =>
2366
- if in.lookahead.isArrow && location != Location .InGuard && in.fewerBracesEnabled then
2367
- val app = applyToClosure(t, in.offset, convertToParams(wildcardIdent()))
2368
- simpleExprRest(app, location, canApply = true )
2369
- else
2370
- atSpan(startOffset(t), in.skipToken()) { PostfixOp (t, Ident (nme.WILDCARD )) }
2371
- case IDENTIFIER
2372
- if ! in.isOperator && in.lookahead.isArrow && location != Location .InGuard && in.fewerBracesEnabled =>
2373
- val app = applyToClosure(t, in.offset, convertToParams(termIdent()))
2374
- simpleExprRest(app, location, canApply = true )
2381
+ atSpan(startOffset(t), in.skipToken()) { PostfixOp (t, Ident (nme.WILDCARD )) }
2375
2382
case _ =>
2376
- t match
2377
- case id @ Ident (name)
2378
- if in.isColon() && location == Location .InParens && followingisLambdaParams() =>
2379
- if name.is(WildcardParamName ) then
2380
- assert(name == placeholderParams.head.name)
2381
- placeholderParams = placeholderParams.tail
2382
- atSpan(startOffset(id)) {
2383
- makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2384
- }
2385
- case _ =>
2386
- t
2387
- }
2388
- }
2389
-
2390
- def applyToClosure (t : Tree , start : Offset , params : List [ValDef ]): Tree =
2391
- atSpan(startOffset(t), in.offset) {
2392
- val arg = atSpan(start, in.skipToken()) {
2393
- if in.token != INDENT then
2394
- syntaxErrorOrIncomplete(i " indented expression expected, ${in} found " )
2395
- Function (params, blockExpr())
2396
- }
2397
- Apply (t, arg)
2398
- }
2383
+ if in.isColon() && location == Location .InParens && followingIsLambdaParams() then
2384
+ t match
2385
+ case id @ Ident (name) =>
2386
+ if name.is(WildcardParamName ) then
2387
+ assert(name == placeholderParams.head.name)
2388
+ placeholderParams = placeholderParams.tail
2389
+ atSpan(startOffset(id)) {
2390
+ makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
2391
+ }
2392
+ case _ => t
2393
+ else if in.fewerBracesEnabled && in.token == COLON && followingIsLambdaAfterColon() then
2394
+ val app = atSpan(startOffset(t), in.skipToken()) {
2395
+ Apply (t, expr(Location .InColonArg ) :: Nil )
2396
+ }
2397
+ simpleExprRest(app, location, canApply = true )
2398
+ else t
2399
+ end simpleExprRest
2399
2400
2400
2401
/** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody]
2401
2402
* | ‘new’ TemplateBody
@@ -2499,12 +2500,13 @@ object Parsers {
2499
2500
*/
2500
2501
def blockExpr (): Tree = atSpan(in.offset) {
2501
2502
val simplify = in.token == INDENT
2502
- inDefScopeBraces {
2503
- if (in.token == CASE ) Match (EmptyTree , caseClauses(() => caseClause()))
2504
- else block(simplify)
2505
- }
2503
+ inDefScopeBraces { casesOrBlock(simplify) }
2506
2504
}
2507
2505
2506
+ def casesOrBlock (simplify : Boolean ): Tree =
2507
+ if (in.token == CASE ) Match (EmptyTree , caseClauses(() => caseClause()))
2508
+ else block(simplify)
2509
+
2508
2510
/** Block ::= BlockStatSeq
2509
2511
* @note Return tree does not have a defined span.
2510
2512
*/
0 commit comments