Skip to content

Commit 2c74308

Browse files
committed
Stop at comma only if one could be expected
We now have the following handling of stop symbols in skip: - `)`, `]`, `}`: stop if there is a corresponding opening parenthesis - `,` : stop if we are in a `commaSeparated` production - undent : stop if indent width matches a previously seen indent width - `;`, nl : stop unconditionally, the parser will sync after the current statement
1 parent f190103 commit 2c74308

File tree

4 files changed

+27
-13
lines changed

4 files changed

+27
-13
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ object Parsers {
225225
|| allowedMods.contains(in.token)
226226
|| in.isSoftModifierInModifierPosition && !excludedSoftModifiers.contains(in.name)
227227

228-
def isStatSep: Boolean = in.isNewLine || in.token == SEMI
228+
def isStatSep: Boolean = in.isStatSep
229229

230230
/** A '$' identifier is treated as a splice if followed by a `{`.
231231
* A longer identifier starting with `$` is treated as a splice/id combination
@@ -292,13 +292,13 @@ object Parsers {
292292
*
293293
* @return The offset at the start of the token to accept
294294
*/
295-
def accept(token: Int): Int = {
295+
def accept(token: Int): Int =
296296
val offset = in.offset
297-
if (in.token != token)
297+
def assumedOutdent = token == OUTDENT && in.token == EOF
298+
if in.token != token /*&& !assumedOutdent*/ then
298299
syntaxErrorOrIncomplete(ExpectedTokenButFound(token, in.token))
299-
if (in.token == token) in.nextToken()
300+
if in.token == token then in.nextToken()
300301
offset
301-
}
302302

303303
def accept(name: Name): Int = {
304304
val offset = in.offset
@@ -562,11 +562,13 @@ object Parsers {
562562
inBracesOrIndented(body, rewriteWithColon)
563563

564564
def commaSeparated[T](part: () => T): List[T] =
565-
val ts = new ListBuffer[T] += part()
566-
while in.token == COMMA do
567-
in.nextToken()
568-
ts += part()
569-
ts.toList
565+
in.currentRegion.withCommasExpected {
566+
val ts = new ListBuffer[T] += part()
567+
while in.token == COMMA do
568+
in.nextToken()
569+
ts += part()
570+
ts.toList
571+
}
570572

571573
def inSepRegion[T](f: Region => Region)(op: => T): T =
572574
val cur = in.currentRegion

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ object Scanners {
6767
}
6868

6969
def isNewLine = token == NEWLINE || token == NEWLINES
70+
def isStatSep = isNewLine || token == SEMI
7071
def isIdent = token == IDENTIFIER || token == BACKQUOTED_IDENT
7172
def isIdent(name: Name) = token == IDENTIFIER && this.name == name
7273

@@ -291,8 +292,9 @@ object Scanners {
291292
def atStop =
292293
token == EOF
293294
|| (currentRegion eq lastRegion)
294-
&& (stopSkipTokens.contains(token)
295+
&& (isStatSep
295296
|| closingParens.contains(token) && lastRegion.toList.exists(_.closedBy == token)
297+
|| token == COMMA && lastRegion.toList.exists(_.commasExpected)
296298
|| token == OUTDENT && indentWidth(offset) < lastKnownIndentWidth)
297299
// stop at OUTDENT if the new indentwidth is smaller than the indent width of
298300
// currentRegion. This corrects for the problem that sometimes we don't see an INDENT
@@ -1570,6 +1572,17 @@ object Scanners {
15701572
protected def coversIndent(w: IndentWidth): Boolean =
15711573
knownWidth != null && w == indentWidth
15721574

1575+
private var myCommasExpected: Boolean = false
1576+
1577+
inline def withCommasExpected[T](inline op: => T): T =
1578+
val saved = myCommasExpected
1579+
myCommasExpected = true
1580+
val res = op
1581+
myCommasExpected = false
1582+
res
1583+
1584+
def commasExpected = myCommasExpected
1585+
15731586
def toList: List[Region] =
15741587
this :: (if outer == null then Nil else outer.toList)
15751588

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ object Tokens extends TokensCommon {
288288
final val endMarkerTokens = identifierTokens | BitSet(IF, WHILE, FOR, MATCH, TRY, NEW, THROW, GIVEN, VAL, THIS)
289289

290290
final val closingParens = BitSet(RPAREN, RBRACKET, RBRACE)
291-
final val stopSkipTokens = BitSet(SEMI, COMMA, NEWLINE, NEWLINES)
292291

293292
final val softModifierNames = Set(nme.inline, nme.opaque, nme.open, nme.transparent, nme.infix)
294293
}

tests/neg/i1679.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class A[T]
22
object o {
33
// Testing compiler crash, this test should be modified when named type argument are completely implemented
4-
val x: A[T=Int, T=Int] = ??? // error: ']' expected, but '=' found // error
4+
val x: A[T=Int, T=Int] = ??? // error: ']' expected, but '=' found
55
}

0 commit comments

Comments
 (0)