@@ -311,7 +311,11 @@ object Parsers {
311
311
def acceptStatSep (): Unit =
312
312
if in.isNewLine then in.nextToken() else accept(SEMI )
313
313
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 =
315
319
def recur (sepSeen : Boolean , endSeen : Boolean ): Boolean =
316
320
if isStatSep then
317
321
in.nextToken()
@@ -321,42 +325,25 @@ object Parsers {
321
325
checkEndMarker(stats)
322
326
recur(sepSeen, true )
323
327
else if isStatSeqEnd || in.token == altEnd then
324
- true
325
- else if sepSeen || endSeen then
326
328
false
329
+ else if sepSeen || endSeen then
330
+ true
327
331
else
328
332
val found = in.token
329
333
val statFollows = mustStartStatTokens.contains(found)
330
334
syntaxError(
331
335
if noPrevStat then IllegalStartOfStatement (what, isModifier, statFollows)
332
336
else i " end of $what expected but ${showToken(found)} found " )
333
337
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
335
339
else
336
340
in.nextToken() // needed to ensure progress; otherwise we might cycle forever
337
341
skip()
338
- false
342
+ true
339
343
340
344
in.observeOutdented()
341
345
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
360
347
361
348
def rewriteNotice (version : String = " 3.0" , additionalOption : String = " " ) = {
362
349
val optionStr = if (additionalOption.isEmpty) " " else " " ++ additionalOption
@@ -3642,10 +3629,10 @@ object Parsers {
3642
3629
*/
3643
3630
def extMethods (numLeadParams : Int ): List [DefDef ] = checkNoEscapingPlaceholders {
3644
3631
val meths = new ListBuffer [DefDef ]
3645
- val exitOnError = false
3646
- while ! isStatSeqEnd && ! exitOnError do
3632
+ while
3647
3633
meths += extMethod(numLeadParams)
3648
- acceptStatSepUnlessAtEnd(meths)
3634
+ statSepOrEnd(meths, what = " extension method" )
3635
+ do ()
3649
3636
if meths.isEmpty then syntaxError(" `def` expected" )
3650
3637
meths.toList
3651
3638
}
@@ -3781,7 +3768,8 @@ object Parsers {
3781
3768
*/
3782
3769
def topStatSeq (outermost : Boolean = false ): List [Tree ] = {
3783
3770
val stats = new ListBuffer [Tree ]
3784
- while (! isStatSeqEnd) {
3771
+ while
3772
+ var empty = false
3785
3773
if (in.token == PACKAGE ) {
3786
3774
val start = in.skipToken()
3787
3775
if (in.token == OBJECT ) {
@@ -3798,13 +3786,10 @@ object Parsers {
3798
3786
stats += extension()
3799
3787
else if isDefIntro(modifierTokens) then
3800
3788
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 ()
3808
3793
stats.toList
3809
3794
}
3810
3795
@@ -3836,13 +3821,12 @@ object Parsers {
3836
3821
in.token = SELFARROW // suppresses INDENT insertion after `=>`
3837
3822
in.nextToken()
3838
3823
}
3839
- else {
3824
+ else
3840
3825
stats += first
3841
- acceptStatSepUnlessAtEnd(stats)
3842
- }
3826
+ statSepOrEnd(stats)
3843
3827
}
3844
- var exitOnError = false
3845
- while ( ! isStatSeqEnd && ! exitOnError) {
3828
+ while
3829
+ var empty = false
3846
3830
if (in.token == IMPORT )
3847
3831
stats ++= importClause(IMPORT , mkImport())
3848
3832
else if (in.token == EXPORT )
@@ -3853,12 +3837,10 @@ object Parsers {
3853
3837
stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens))
3854
3838
else if (isExprIntro)
3855
3839
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 ()
3862
3844
(self, if (stats.isEmpty) List (EmptyTree ) else stats.toList)
3863
3845
}
3864
3846
@@ -3887,16 +3869,14 @@ object Parsers {
3887
3869
if problem.isEmpty then tree :: Nil
3888
3870
else { syntaxError(problem, tree.span); Nil }
3889
3871
3890
- while (! isStatSeqEnd) {
3891
- if (isDclIntro)
3872
+ while
3873
+ val dclFound = isDclIntro
3874
+ if dclFound then
3892
3875
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 ()
3900
3880
stats.toList
3901
3881
}
3902
3882
@@ -3934,7 +3914,7 @@ object Parsers {
3934
3914
stats +++= localDef(in.offset)
3935
3915
else
3936
3916
empty = true
3937
- ! exitStats (stats, empty, CASE )
3917
+ statSepOrEnd (stats, empty, altEnd = CASE )
3938
3918
do ()
3939
3919
stats.toList
3940
3920
}
@@ -3952,7 +3932,7 @@ object Parsers {
3952
3932
in.nextToken()
3953
3933
ts += objectDef(start, Modifiers (Package ))
3954
3934
if (in.token != EOF ) {
3955
- acceptStatSepUnlessAtEnd (ts)
3935
+ statSepOrEnd (ts, what = " toplevel definition " )
3956
3936
ts ++= topStatSeq()
3957
3937
}
3958
3938
}
@@ -3969,7 +3949,7 @@ object Parsers {
3969
3949
acceptStatSep()
3970
3950
ts += makePackaging(start, pkg, topstats())
3971
3951
if continue then
3972
- acceptStatSepUnlessAtEnd (ts)
3952
+ statSepOrEnd (ts, what = " toplevel definition " )
3973
3953
ts ++= topStatSeq()
3974
3954
}
3975
3955
else
0 commit comments