@@ -1090,27 +1090,45 @@ object Parsers {
10901090 }
10911091
10921092 /** Is the token sequence following the current `:` token classified as a lambda?
1093- * This is the case if the input starts with an identifier, a wildcard, or
1094- * something enclosed in (...) or [...], and this is followed by a `=>` or `?=>`
1095- * and an INDENT.
1096- */
1097- def followingIsLambdaAfterColon (): Boolean =
1093+ * If yes return a defined parsing function to parse the lambda body, if not
1094+ * return None. The case is triggered in two :if the input starts with an identifier,
1095+ * a wildcard, or something enclosed in (...) or [...], this is followed by a
1096+ * `=>` or `?=>`, one one of the following two cases applies:
1097+ * 1. The next token is an indent. In this case the return parsing function parses
1098+ * an Expr in location Location.InColonArg.
1099+ * 2. The next token is on the same line and the enclosing region is not `(...)`.
1100+ * In this case the parsing function parses an Expr in location Location.InColonArg
1101+ * enclosed in a SingleLineLambda region, and then eats the ENDlambda token
1102+ * generated by the Scanner at the end of that region.
1103+ * The reason for excluding (2) in regions enclosed in parentheses is to avoid
1104+ * an ambiguity with type ascription `(x: A => B)`, where function types are only
1105+ * allowed inside parentheses.
1106+ */
1107+ def followingIsLambdaAfterColon (): Option [() => Tree ] =
10981108 val lookahead = in.LookaheadScanner (allowIndent = true )
10991109 .tap(_.currentRegion.knownWidth = in.currentRegion.indentWidth)
1100- def isArrowIndent () =
1101- lookahead.isArrow
1102- && {
1110+ def isArrowIndent (): Option [() => Tree ] =
1111+ if lookahead.isArrow then
11031112 lookahead.observeArrowIndented()
1104- lookahead.token == INDENT || lookahead.token == EOF
1105- }
1113+ if lookahead.token == INDENT || lookahead.token == EOF then
1114+ Some (() => expr(Location .InColonArg ))
1115+ else if ! in.currentRegion.isInstanceOf [InParens ] then
1116+ Some : () =>
1117+ val t = inSepRegion(SingleLineLambda (_)):
1118+ expr(Location .InColonArg )
1119+ accept(ENDlambda )
1120+ t
1121+ else None
1122+ else None
11061123 lookahead.nextToken()
11071124 if lookahead.isIdent || lookahead.token == USCORE then
11081125 lookahead.nextToken()
11091126 isArrowIndent()
11101127 else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
11111128 lookahead.skipParens()
11121129 isArrowIndent()
1113- else false
1130+ else
1131+ None
11141132
11151133 /** Can the next lookahead token start an operand as defined by
11161134 * leadingOperandTokens, or is postfix ops enabled?
@@ -1175,12 +1193,17 @@ object Parsers {
11751193 case _ => infixOp
11761194 }
11771195
1178- /** True if we are seeing a lambda argument after a colon of the form:
1196+ /** Optionally, if we are seeing a lambda argument after a colon of the form
11791197 * : (params) =>
11801198 * body
1199+ * or a single-line lambda
1200+ * : (params) => body
1201+ * then return the function used to parse `body`.
11811202 */
1182- def isColonLambda =
1183- sourceVersion.enablesFewerBraces && in.token == COLONfollow && followingIsLambdaAfterColon()
1203+ def detectColonLambda : Option [() => Tree ] =
1204+ if sourceVersion.enablesFewerBraces && in.token == COLONfollow
1205+ then followingIsLambdaAfterColon()
1206+ else None
11841207
11851208 /** operand { infixop operand | MatchClause } [postfixop],
11861209 *
@@ -1204,17 +1227,19 @@ object Parsers {
12041227 opStack = OpInfo (top1, op, in.offset) :: opStack
12051228 colonAtEOLOpt()
12061229 newLineOptWhenFollowing(canStartOperand)
1207- if isColonLambda then
1208- in.nextToken()
1209- recur(expr(Location .InColonArg ))
1210- else if maybePostfix && ! canStartOperand(in.token) then
1211- val topInfo = opStack.head
1212- opStack = opStack.tail
1213- val od = reduceStack(base, topInfo.operand, 0 , true , in.name, isType)
1214- atSpan(startOffset(od), topInfo.offset) {
1215- PostfixOp (od, topInfo.operator)
1216- }
1217- else recur(operand(location))
1230+ detectColonLambda match
1231+ case Some (parseExpr) =>
1232+ in.nextToken()
1233+ recur(parseExpr())
1234+ case _ =>
1235+ if maybePostfix && ! canStartOperand(in.token) then
1236+ val topInfo = opStack.head
1237+ opStack = opStack.tail
1238+ val od = reduceStack(base, topInfo.operand, 0 , true , in.name, isType)
1239+ atSpan(startOffset(od), topInfo.offset) {
1240+ PostfixOp (od, topInfo.operator)
1241+ }
1242+ else recur(operand(location))
12181243 else
12191244 val t = reduceStack(base, top, minPrec, leftAssoc = true , in.name, isType)
12201245 if ! isType && in.token == MATCH then recurAtMinPrec(matchClause(t))
@@ -2771,6 +2796,7 @@ object Parsers {
27712796 * | SimpleExpr1 ColonArgument
27722797 * ColonArgument ::= colon [LambdaStart]
27732798 * indent (CaseClauses | Block) outdent
2799+ * | colon LambdaStart expr ENDlambda -- under experimental.relaxedLambdaSyntax
27742800 * LambdaStart ::= FunParams (‘=>’ | ‘?=>’)
27752801 * | TypTypeParamClause ‘=>’
27762802 * ColonArgBody ::= indent (CaseClauses | Block) outdent
@@ -2853,12 +2879,14 @@ object Parsers {
28532879 makeParameter(name.asTermName, typedOpt(), Modifiers (), isBackquoted = isBackquoted(id))
28542880 }
28552881 case _ => t
2856- else if isColonLambda then
2857- val app = atSpan(startOffset(t), in.skipToken()) {
2858- Apply (t, expr(Location .InColonArg ) :: Nil )
2859- }
2860- simpleExprRest(app, location, canApply = true )
2861- else t
2882+ else detectColonLambda match
2883+ case Some (parseExpr) =>
2884+ val app =
2885+ atSpan(startOffset(t), in.skipToken()):
2886+ Apply (t, parseExpr() :: Nil )
2887+ simpleExprRest(app, location, canApply = true )
2888+ case None =>
2889+ t
28622890 end simpleExprRest
28632891
28642892 /** SimpleExpr ::= ‘new’ ConstrApp {`with` ConstrApp} [TemplateBody]
0 commit comments