Skip to content

Commit 0261bb3

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 894db54 commit 0261bb3

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
@@ -2332,6 +2332,14 @@ extension RegexTests {
23322332
$0.as(AST.Atom.self)!.as(AST.Atom.Scalar.self)!.location
23332333
})
23342334

2335+
rangeTest(#"\u{ 65 58 }"#, range(5 ..< 7), at: {
2336+
$0.as(AST.Atom.self)!.as(AST.Atom.ScalarSequence.self)!.scalars[0].location
2337+
})
2338+
2339+
rangeTest(#"\u{ 65 58 }"#, range(8 ..< 10), at: {
2340+
$0.as(AST.Atom.self)!.as(AST.Atom.ScalarSequence.self)!.scalars[1].location
2341+
})
2342+
23352343
// MARK: References
23362344

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

0 commit comments

Comments
 (0)