Skip to content

Commit fb06ed2

Browse files
committed
Fix source location tracking in lexUntil
The `predicate` may independently advance the location before bailing, and we don't want that to affect the recorded location of the result. We probably ought to replace `lexUntil` with a better API.
1 parent 3ca2bd1 commit fb06ed2

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

Sources/_RegexParser/Regex/Parse/LexicalAnalysis.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,13 +503,22 @@ extension Source {
503503
private mutating func lexUntil(
504504
_ predicate: (inout Source) throws -> Bool
505505
) rethrows -> Located<String> {
506+
// We track locations outside of recordLoc, as the predicate may advance the
507+
// input when we hit the end, and we don't want that to affect the location
508+
// of what was lexed in the `result`. We still want the recordLoc call to
509+
// attach locations to any thrown errors though.
510+
// TODO: We should find a better way of doing this, `lexUntil` seems full
511+
// of footguns.
512+
let start = currentPosition
513+
var end = currentPosition
514+
var result = ""
506515
try recordLoc { src in
507-
var result = ""
508516
while try !predicate(&src) {
509517
result.append(src.eat())
518+
end = src.currentPosition
510519
}
511-
return result
512520
}
521+
return .init(result, start ..< end)
513522
}
514523

515524
private mutating func lexUntil(eating end: String) throws -> Located<String> {

Tests/RegexTests/ParseTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,14 @@ extension RegexTests {
21952195
$0.as(AST.Atom.self)!.as(AST.Atom.Scalar.self)!.location
21962196
})
21972197

2198+
rangeTest(#"\u{ 65 58 }"#, range(5 ..< 7), at: {
2199+
$0.as(AST.Atom.self)!.as(AST.Atom.ScalarSequence.self)!.scalars[0].location
2200+
})
2201+
2202+
rangeTest(#"\u{ 65 58 }"#, range(8 ..< 10), at: {
2203+
$0.as(AST.Atom.self)!.as(AST.Atom.ScalarSequence.self)!.scalars[1].location
2204+
})
2205+
21982206
// MARK: References
21992207

22002208
rangeTest(#"\k<a+2>"#, range(3 ..< 6), at: {

0 commit comments

Comments
 (0)