@@ -340,43 +340,45 @@ object Parsers {
340340 if in.isNewLine then in.nextToken() else accept(SEMI )
341341
342342 /** Parse statement separators and end markers. Ensure that there is at least
343- * one statement separator unless the next token terminates a statement´ sequence.
344- * @param stats the statements parsed to far
343+ * one statement separator unless the next token terminates a statement sequence.
344+ * @param stats the statements parsed so far
345345 * @param noPrevStat true if there was no immediately preceding statement parsed
346346 * @param what a string indicating what kind of statement is parsed
347347 * @param altEnd a token that is also considered as a terminator of the statement
348- * sequence (the default `EOF` already assumes to terminate a statement
348+ * sequence (the default `EOF` is already assumed to terminate a statement
349349 * sequence).
350350 * @return true if the statement sequence continues, false if it terminates.
351351 */
352352 def statSepOrEnd [T <: Tree ](stats : ListBuffer [T ], noPrevStat : Boolean = false , what : String = " statement" , altEnd : Token = EOF ): Boolean =
353+ inline def stopping = false
354+ inline def continuing = true
353355 def recur (sepSeen : Boolean , endSeen : Boolean ): Boolean =
354356 if isStatSep then
355357 in.nextToken()
356- recur(true , endSeen)
358+ recur(sepSeen = true , endSeen)
357359 else if in.token == END then
358360 if endSeen then syntaxError(em " duplicate end marker " )
359361 checkEndMarker(stats)
360362 recur(sepSeen, endSeen = true )
361363 else if isStatSeqEnd || in.token == altEnd then
362- false
364+ stopping
363365 else if sepSeen || endSeen then
364- true
366+ continuing
365367 else
366368 val found = in.token
367369 val statFollows = mustStartStatTokens.contains(found)
368370 syntaxError(
369371 if noPrevStat then IllegalStartOfStatement (what, isModifier, statFollows)
370372 else em " end of $what expected but ${showToken(found)} found " )
371- if mustStartStatTokens.contains(found) then
372- false // it's a statement that might be legal in an outer context
373+ if statFollows then
374+ stopping // it's a statement that might be legal in an outer context
373375 else
374376 in.nextToken() // needed to ensure progress; otherwise we might cycle forever
375377 skip()
376- true
378+ continuing
377379
378380 in.observeOutdented()
379- recur(false , false )
381+ recur(sepSeen = false , endSeen = false )
380382 end statSepOrEnd
381383
382384 def rewriteNotice (version : SourceVersion = `3.0-migration`, additionalOption : String = " " ) =
@@ -1441,15 +1443,23 @@ object Parsers {
14411443 if sourceVersion.isMigrating then
14421444 patch(source, Span (in.offset), " " )
14431445
1444- def possibleTemplateStart (isNew : Boolean = false ): Unit =
1446+ inline transparent def possibleTemplateStart (inline isNew : Boolean = false ) =
1447+ inline if isNew then newTemplateStart() else (newTemplateStart(): Unit )
1448+
1449+ /** Return true on trivial end */
1450+ def newTemplateStart (): Boolean =
14451451 in.observeColonEOL(inTemplate = true )
14461452 if in.token == COLONeol then
1447- if in.lookahead.token == END then in.token = NEWLINE
1453+ if in.lookahead.token == END then
1454+ in.token = NEWLINE
1455+ true
14481456 else
14491457 in.nextToken()
14501458 if in.token != LBRACE then acceptIndent()
1459+ false
14511460 else
14521461 newLineOptWhenFollowedBy(LBRACE )
1462+ false
14531463
14541464 def checkEndMarker [T <: Tree ](stats : ListBuffer [T ]): Unit =
14551465
@@ -2644,15 +2654,22 @@ object Parsers {
26442654 val parents =
26452655 if in.isNestedStart then Nil
26462656 else constrApps(exclude = COMMA )
2647- possibleTemplateStart(isNew = true )
2648- parents match {
2649- case parent :: Nil if ! in.isNestedStart =>
2650- reposition(if (parent.isType) ensureApplied(wrapNew(parent)) else parent)
2651- case tkn if in.token == INDENT =>
2652- New (templateBodyOpt(emptyConstructor, parents, Nil ))
2653- case _ =>
2654- New (reposition(templateBodyOpt(emptyConstructor, parents, Nil )))
2655- }
2657+ val colonized = possibleTemplateStart(isNew = true )
2658+ parents match
2659+ case parent :: Nil if ! in.isNestedStart =>
2660+ reposition :
2661+ if colonized then New (Template (emptyConstructor, parents, derived = Nil , self = EmptyValDef , body = Nil ))
2662+ else if parent.isType then ensureApplied(wrapNew(parent))
2663+ else parent
2664+ case parents =>
2665+ // With brace syntax, the last token consumed by a parser is }, but with indent syntax,
2666+ // the last token consumed by a parser is OUTDENT, which causes mismatching spans, so don't reposition.
2667+ val indented = in.token == INDENT
2668+ val body =
2669+ val bo = templateBodyOpt(emptyConstructor, parents, derived = Nil )
2670+ if ! indented then reposition(bo) else bo
2671+ New (body)
2672+ end newExpr
26562673
26572674 /** ExprsInParens ::= ExprInParens {`,' ExprInParens}
26582675 * Bindings ::= Binding {`,' Binding}
0 commit comments