Skip to content

Commit df7c412

Browse files
committed
When eating unexpected tokens in string interpolation, match opened '(' when looking for the closing ')'
1 parent 8c883ab commit df7c412

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

Sources/SwiftParser/Expressions.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1756,7 +1756,14 @@ extension Parser {
17561756
var runexpectedTokens = [RawSyntax]()
17571757
let runexpected: RawUnexpectedNodesSyntax?
17581758
var loopProgress = LoopProgressCondition()
1759-
while !subparser.at(any: [.eof, .rightParen]) && loopProgress.evaluate(subparser.currentToken) {
1759+
var openParens = 0
1760+
// Terminate the loop when we've reached EOF or are at a ')' with no more open '(' that we need to skip
1761+
while !subparser.at(.eof) && !(subparser.at(.rightParen) && openParens == 0) && loopProgress.evaluate(subparser.currentToken) {
1762+
if subparser.at(.leftParen) {
1763+
openParens += 1
1764+
} else if subparser.at(.rightParen) {
1765+
openParens -= 1
1766+
}
17601767
runexpectedTokens.append(RawSyntax(subparser.consumeAnyToken()))
17611768
}
17621769
if !runexpectedTokens.isEmpty {

Tests/SwiftParserTest/translated/UnclosedStringInterpolationTests.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ final class UnclosedStringInterpolationTests: XCTestCase {
8181
let zzz = "\(x1️⃣; print(x)2️⃣
8282
"""##,
8383
diagnostics: [
84-
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '; print(x' in string literal"),
84+
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '; print(x)' in string literal"),
85+
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' in string literal"),
8586
DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#),
8687
]
8788
)
@@ -114,4 +115,16 @@ final class UnclosedStringInterpolationTests: XCTestCase {
114115
)
115116
}
116117

118+
func testSkipUnexpectedOpeningParensInStringLiteral() {
119+
AssertParse(
120+
#"""
121+
"\(e 1️⃣H()r2️⃣
122+
"""#,
123+
diagnostics: [
124+
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code 'H()r' in string literal"),
125+
DiagnosticSpec(locationMarker: "2️⃣", message: "expected ')' in string literal"),
126+
DiagnosticSpec(locationMarker: "2️⃣", message: #"expected '"' to end string literal"#),
127+
]
128+
)
129+
}
117130
}

0 commit comments

Comments
 (0)