@@ -254,6 +254,7 @@ object Parsers {
254
254
|| skipStopTokens.contains(in.token) && (in.currentRegion eq lastRegion)
255
255
while ! atStop do
256
256
in.nextToken()
257
+ lastErrorOffset = in.offset
257
258
258
259
def warning (msg : Message , sourcePos : SourcePosition ): Unit =
259
260
report.warning(msg, sourcePos)
@@ -273,11 +274,9 @@ object Parsers {
273
274
*/
274
275
def syntaxErrorOrIncomplete (msg : Message , offset : Int = in.offset): Unit =
275
276
if (in.token == EOF ) incompleteInputError(msg)
276
- else {
277
+ else
277
278
syntaxError(msg, offset)
278
279
skip()
279
- lastErrorOffset = in.offset
280
- }
281
280
282
281
/** Consume one token of the specified type, or
283
282
* signal an error if it is not there.
@@ -312,6 +311,35 @@ object Parsers {
312
311
def acceptStatSep (): Unit =
313
312
if in.isNewLine then in.nextToken() else accept(SEMI )
314
313
314
+ def exitStats [T <: Tree ](stats : ListBuffer [T ], altEnd : Token = EOF , noPrevStat : Boolean ): Boolean =
315
+ def recur (sepSeen : Boolean , endSeen : Boolean ): Boolean =
316
+ if isStatSep then
317
+ in.nextToken()
318
+ recur(true , endSeen)
319
+ else if in.token == END then
320
+ if endSeen then syntaxError(" duplicate end marker" )
321
+ checkEndMarker(stats)
322
+ recur(sepSeen, true )
323
+ else if isStatSeqEnd || in.token == altEnd then
324
+ true
325
+ else if sepSeen || endSeen then
326
+ false
327
+ else
328
+ val found = in.token
329
+ syntaxError(
330
+ if noPrevStat then IllegalStartOfStatement (isModifier)
331
+ else i " end of statement expected but ${showToken(found)} found " )
332
+ if mustStartStatTokens.contains(found) then
333
+ true // it's a statement that might be legal in an outer context
334
+ else
335
+ in.nextToken() // needed to ensure progress; otherwise we might cycle forever
336
+ skip()
337
+ false
338
+
339
+ in.observeOutdented()
340
+ recur(false , false )
341
+ end exitStats
342
+
315
343
def acceptStatSepUnlessAtEnd [T <: Tree ](stats : ListBuffer [T ], altEnd : Token = EOF ): Unit =
316
344
def skipEmptyStats (): Unit =
317
345
while (in.token == SEMI || in.token == NEWLINE || in.token == NEWLINES ) do in.nextToken()
@@ -3891,8 +3919,8 @@ object Parsers {
3891
3919
*/
3892
3920
def blockStatSeq (): List [Tree ] = checkNoEscapingPlaceholders {
3893
3921
val stats = new ListBuffer [Tree ]
3894
- var exitOnError = false
3895
- while ( ! isStatSeqEnd && in.token != CASE && ! exitOnError) {
3922
+ while
3923
+ var empty = false
3896
3924
if (in.token == IMPORT )
3897
3925
stats ++= importClause(IMPORT , mkImport())
3898
3926
else if (isExprIntro)
@@ -3903,12 +3931,10 @@ object Parsers {
3903
3931
stats += extension()
3904
3932
else if isDefIntro(localModifierTokens, excludedSoftModifiers = Set (nme.`opaque`)) then
3905
3933
stats +++= localDef(in.offset)
3906
- else if (! isStatSep && (in.token != CASE )) {
3907
- exitOnError = mustStartStat
3908
- syntaxErrorOrIncomplete(IllegalStartOfStatement (isModifier))
3909
- }
3910
- acceptStatSepUnlessAtEnd(stats, CASE )
3911
- }
3934
+ else
3935
+ empty = true
3936
+ ! exitStats(stats, CASE , empty)
3937
+ do ()
3912
3938
stats.toList
3913
3939
}
3914
3940
0 commit comments