@@ -349,43 +349,45 @@ object Parsers {
349349 if in.isNewLine then in.nextToken() else accept(SEMI )
350350
351351 /** Parse statement separators and end markers. Ensure that there is at least
352- * one statement separator unless the next token terminates a statement´ sequence.
353- * @param stats the statements parsed to far
352+ * one statement separator unless the next token terminates a statement sequence.
353+ * @param stats the statements parsed so far
354354 * @param noPrevStat true if there was no immediately preceding statement parsed
355355 * @param what a string indicating what kind of statement is parsed
356356 * @param altEnd a token that is also considered as a terminator of the statement
357- * sequence (the default `EOF` already assumes to terminate a statement
357+ * sequence (the default `EOF` is already assumed to terminate a statement
358358 * sequence).
359359 * @return true if the statement sequence continues, false if it terminates.
360360 */
361361 def statSepOrEnd [T <: Tree ](stats : ListBuffer [T ], noPrevStat : Boolean = false , what : String = " statement" , altEnd : Token = EOF ): Boolean =
362+ inline def stopping = false
363+ inline def continuing = true
362364 def recur (sepSeen : Boolean , endSeen : Boolean ): Boolean =
363365 if isStatSep then
364366 in.nextToken()
365- recur(true , endSeen)
367+ recur(sepSeen = true , endSeen)
366368 else if in.token == END then
367369 if endSeen then syntaxError(em " duplicate end marker " )
368370 checkEndMarker(stats)
369371 recur(sepSeen, endSeen = true )
370372 else if isStatSeqEnd || in.token == altEnd then
371- false
373+ stopping
372374 else if sepSeen || endSeen then
373- true
375+ continuing
374376 else
375377 val found = in.token
376378 val statFollows = mustStartStatTokens.contains(found)
377379 syntaxError(
378380 if noPrevStat then IllegalStartOfStatement (what, isModifier, statFollows)
379381 else em " end of $what expected but ${showToken(found)} found " )
380- if mustStartStatTokens.contains(found) then
381- false // it's a statement that might be legal in an outer context
382+ if statFollows then
383+ stopping // it's a statement that might be legal in an outer context
382384 else
383385 in.nextToken() // needed to ensure progress; otherwise we might cycle forever
384386 skip()
385- true
387+ continuing
386388
387389 in.observeOutdented()
388- recur(false , false )
390+ recur(sepSeen = false , endSeen = false )
389391 end statSepOrEnd
390392
391393 def rewriteNotice (version : SourceVersion = `3.0-migration`, additionalOption : String = " " ) =
@@ -1566,15 +1568,23 @@ object Parsers {
15661568 if MigrationVersion .Scala2to3 .needsPatch then
15671569 patch(source, Span (in.offset), " " )
15681570
1569- def possibleTemplateStart (isNew : Boolean = false ): Unit =
1571+ inline transparent def possibleTemplateStart (inline isNew : Boolean = false ) =
1572+ inline if isNew then newTemplateStart() else (newTemplateStart(): Unit )
1573+
1574+ /** Return true on trivial end */
1575+ def newTemplateStart (): Boolean =
15701576 in.observeColonEOL(inTemplate = true )
15711577 if in.token == COLONeol then
1572- if in.lookahead.token == END then in.token = NEWLINE
1578+ if in.lookahead.token == END then
1579+ in.token = NEWLINE
1580+ true
15731581 else
15741582 in.nextToken()
15751583 if in.token != LBRACE then acceptIndent()
1584+ false
15761585 else
15771586 newLineOptWhenFollowedBy(LBRACE )
1587+ false
15781588
15791589 def checkEndMarker [T <: Tree ](stats : ListBuffer [T ]): Unit =
15801590
@@ -2915,15 +2925,22 @@ object Parsers {
29152925 val parents =
29162926 if in.isNestedStart then Nil
29172927 else constrApps(exclude = COMMA )
2918- possibleTemplateStart(isNew = true )
2919- parents match {
2920- case parent :: Nil if ! in.isNestedStart =>
2921- reposition(if (parent.isType) ensureApplied(wrapNew(parent)) else parent)
2922- case tkn if in.token == INDENT =>
2923- New (templateBodyOpt(emptyConstructor, parents, Nil ))
2924- case _ =>
2925- New (reposition(templateBodyOpt(emptyConstructor, parents, Nil )))
2926- }
2928+ val colonized = possibleTemplateStart(isNew = true )
2929+ parents match
2930+ case parent :: Nil if ! in.isNestedStart =>
2931+ reposition :
2932+ if colonized then New (Template (emptyConstructor, parents, derived = Nil , self = EmptyValDef , body = Nil ))
2933+ else if parent.isType then ensureApplied(wrapNew(parent))
2934+ else parent
2935+ case parents =>
2936+ // With brace syntax, the last token consumed by a parser is }, but with indent syntax,
2937+ // the last token consumed by a parser is OUTDENT, which causes mismatching spans, so don't reposition.
2938+ val indented = in.token == INDENT
2939+ val body =
2940+ val bo = templateBodyOpt(emptyConstructor, parents, derived = Nil )
2941+ if ! indented then reposition(bo) else bo
2942+ New (body)
2943+ end newExpr
29272944
29282945 /** ExprsInParens ::= ExprInParens {`,' ExprInParens}
29292946 * | NamedExprInParens {‘,’ NamedExprInParens}
0 commit comments