@@ -311,7 +311,11 @@ object Parsers {
311311 def acceptStatSep (): Unit =
312312 if in.isNewLine then in.nextToken() else accept(SEMI )
313313
314- def exitStats [T <: Tree ](stats : ListBuffer [T ], noPrevStat : Boolean , altEnd : Token = EOF , what : String = " statement" ): Boolean =
314+ /** Parse statement separators and end markers. Ensure that there is at least
315+ * one statement separator unless the next token terminates a statement sequence.
316+ * @return true if the statement sequence continues, false if it terminates.
317+ */
318+ def statSepOrEnd [T <: Tree ](stats : ListBuffer [T ], noPrevStat : Boolean = false , what : String = " statement" , altEnd : Token = EOF ): Boolean =
315319 def recur (sepSeen : Boolean , endSeen : Boolean ): Boolean =
316320 if isStatSep then
317321 in.nextToken()
@@ -321,42 +325,25 @@ object Parsers {
321325 checkEndMarker(stats)
322326 recur(sepSeen, true )
323327 else if isStatSeqEnd || in.token == altEnd then
324- true
325- else if sepSeen || endSeen then
326328 false
329+ else if sepSeen || endSeen then
330+ true
327331 else
328332 val found = in.token
329333 val statFollows = mustStartStatTokens.contains(found)
330334 syntaxError(
331335 if noPrevStat then IllegalStartOfStatement (what, isModifier, statFollows)
332336 else i " end of $what expected but ${showToken(found)} found " )
333337 if mustStartStatTokens.contains(found) then
334- true // it's a statement that might be legal in an outer context
338+ false // it's a statement that might be legal in an outer context
335339 else
336340 in.nextToken() // needed to ensure progress; otherwise we might cycle forever
337341 skip()
338- false
342+ true
339343
340344 in.observeOutdented()
341345 recur(false , false )
342- end exitStats
343-
344- def acceptStatSepUnlessAtEnd [T <: Tree ](stats : ListBuffer [T ], altEnd : Token = EOF ): Unit =
345- def skipEmptyStats (): Unit =
346- while (in.token == SEMI || in.token == NEWLINE || in.token == NEWLINES ) do in.nextToken()
347-
348- in.observeOutdented()
349- in.token match
350- case SEMI | NEWLINE | NEWLINES =>
351- skipEmptyStats()
352- checkEndMarker(stats)
353- skipEmptyStats()
354- case `altEnd` =>
355- case _ =>
356- if ! isStatSeqEnd then
357- syntaxError(i " end of statement expected but ${showToken(in.token)} found " )
358- in.nextToken() // needed to ensure progress; otherwise we might cycle forever
359- accept(SEMI )
346+ end statSepOrEnd
360347
361348 def rewriteNotice (version : String = " 3.0" , additionalOption : String = " " ) = {
362349 val optionStr = if (additionalOption.isEmpty) " " else " " ++ additionalOption
@@ -3642,10 +3629,10 @@ object Parsers {
36423629 */
36433630 def extMethods (numLeadParams : Int ): List [DefDef ] = checkNoEscapingPlaceholders {
36443631 val meths = new ListBuffer [DefDef ]
3645- val exitOnError = false
3646- while ! isStatSeqEnd && ! exitOnError do
3632+ while
36473633 meths += extMethod(numLeadParams)
3648- acceptStatSepUnlessAtEnd(meths)
3634+ statSepOrEnd(meths, what = " extension method" )
3635+ do ()
36493636 if meths.isEmpty then syntaxError(" `def` expected" )
36503637 meths.toList
36513638 }
@@ -3781,7 +3768,8 @@ object Parsers {
37813768 */
37823769 def topStatSeq (outermost : Boolean = false ): List [Tree ] = {
37833770 val stats = new ListBuffer [Tree ]
3784- while (! isStatSeqEnd) {
3771+ while
3772+ var empty = false
37853773 if (in.token == PACKAGE ) {
37863774 val start = in.skipToken()
37873775 if (in.token == OBJECT ) {
@@ -3798,13 +3786,10 @@ object Parsers {
37983786 stats += extension()
37993787 else if isDefIntro(modifierTokens) then
38003788 stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens))
3801- else if ! isStatSep then
3802- if (in.token == CASE )
3803- syntaxErrorOrIncomplete(OnlyCaseClassOrCaseObjectAllowed ())
3804- else
3805- syntaxErrorOrIncomplete(ExpectedToplevelDef ())
3806- acceptStatSepUnlessAtEnd(stats)
3807- }
3789+ else
3790+ empty = true
3791+ statSepOrEnd(stats, empty, " toplevel definition" )
3792+ do ()
38083793 stats.toList
38093794 }
38103795
@@ -3836,13 +3821,12 @@ object Parsers {
38363821 in.token = SELFARROW // suppresses INDENT insertion after `=>`
38373822 in.nextToken()
38383823 }
3839- else {
3824+ else
38403825 stats += first
3841- acceptStatSepUnlessAtEnd(stats)
3842- }
3826+ statSepOrEnd(stats)
38433827 }
3844- var exitOnError = false
3845- while ( ! isStatSeqEnd && ! exitOnError) {
3828+ while
3829+ var empty = false
38463830 if (in.token == IMPORT )
38473831 stats ++= importClause(IMPORT , mkImport())
38483832 else if (in.token == EXPORT )
@@ -3853,12 +3837,10 @@ object Parsers {
38533837 stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens))
38543838 else if (isExprIntro)
38553839 stats += expr1()
3856- else if (! isStatSep) {
3857- exitOnError = mustStartStat
3858- syntaxErrorOrIncomplete(" illegal start of definition" )
3859- }
3860- acceptStatSepUnlessAtEnd(stats)
3861- }
3840+ else
3841+ empty = true
3842+ statSepOrEnd(stats, empty)
3843+ do ()
38623844 (self, if (stats.isEmpty) List (EmptyTree ) else stats.toList)
38633845 }
38643846
@@ -3887,16 +3869,14 @@ object Parsers {
38873869 if problem.isEmpty then tree :: Nil
38883870 else { syntaxError(problem, tree.span); Nil }
38893871
3890- while (! isStatSeqEnd) {
3891- if (isDclIntro)
3872+ while
3873+ val dclFound = isDclIntro
3874+ if dclFound then
38923875 stats ++= checkLegal(defOrDcl(in.offset, Modifiers ()))
3893- else if (! isStatSep)
3894- syntaxErrorOrIncomplete(
3895- " illegal start of declaration" +
3896- (if (inFunReturnType) " (possible cause: missing `=` in front of current method body)"
3897- else " " ))
3898- acceptStatSepUnlessAtEnd(stats)
3899- }
3876+ var what = " declaration"
3877+ if inFunReturnType then what += " (possible cause: missing `=` in front of current method body)"
3878+ statSepOrEnd(stats, ! dclFound, what)
3879+ do ()
39003880 stats.toList
39013881 }
39023882
@@ -3934,7 +3914,7 @@ object Parsers {
39343914 stats +++= localDef(in.offset)
39353915 else
39363916 empty = true
3937- ! exitStats (stats, empty, CASE )
3917+ statSepOrEnd (stats, empty, altEnd = CASE )
39383918 do ()
39393919 stats.toList
39403920 }
@@ -3952,7 +3932,7 @@ object Parsers {
39523932 in.nextToken()
39533933 ts += objectDef(start, Modifiers (Package ))
39543934 if (in.token != EOF ) {
3955- acceptStatSepUnlessAtEnd (ts)
3935+ statSepOrEnd (ts, what = " toplevel definition " )
39563936 ts ++= topStatSeq()
39573937 }
39583938 }
@@ -3969,7 +3949,7 @@ object Parsers {
39693949 acceptStatSep()
39703950 ts += makePackaging(start, pkg, topstats())
39713951 if continue then
3972- acceptStatSepUnlessAtEnd (ts)
3952+ statSepOrEnd (ts, what = " toplevel definition " )
39733953 ts ++= topStatSeq()
39743954 }
39753955 else
0 commit comments