Skip to content

Commit fdce624

Browse files
authored
Match API on Substring too (#118)
1 parent 83c94bf commit fdce624

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

Sources/_StringProcessing/Executor.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ public struct Executor {
3131
return MatchResult(range.lowerBound..<endIndex, .void)
3232
}
3333
}
34+
public func execute(
35+
input: Substring,
36+
mode: MatchMode = .wholeString
37+
) -> MatchResult? {
38+
self.execute(
39+
input: input.base,
40+
in: input.startIndex..<input.endIndex,
41+
mode: mode)
42+
}
3443

3544
public func executeFlat(
3645
input: String,

Sources/_StringProcessing/Legacy/VirtualMachine.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,18 @@ extension VirtualMachine {
5656
func execute(
5757
input: String, mode: MatchMode = .wholeString
5858
) -> MatchResult? {
59-
execute(input: input, in: input.startIndex..<input.endIndex, mode: mode)
59+
execute(
60+
input: input,
61+
in: input.startIndex..<input.endIndex,
62+
mode: mode)
63+
}
64+
func execute(
65+
input: Substring, mode: MatchMode = .wholeString
66+
) -> MatchResult? {
67+
execute(
68+
input: input.base,
69+
in: input.startIndex ..< input.endIndex,
70+
mode: mode)
6071
}
6172
}
6273

Sources/_StringProcessing/RegexDSL/Core.swift

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,22 @@ public struct Regex<Match: MatchProtocol>: RegexProtocol {
112112
}
113113

114114
extension RegexProtocol {
115+
public func match(in input: String) -> RegexMatch<Match>? {
116+
_match(
117+
input, in: input.startIndex..<input.endIndex)
118+
}
119+
public func match(in input: Substring) -> RegexMatch<Match>? {
120+
_match(
121+
input.base, in: input.startIndex..<input.endIndex)
122+
}
123+
115124
// FIXME: This is mostly hacky because we go down two different paths based on
116125
// whether there are captures. This will be cleaned up once we deprecate the
117126
// legacy virtual machines.
118-
public func match(in input: String) -> RegexMatch<Match>? {
127+
func _match(
128+
_ input: String,
129+
in inputRange: Range<String.Index>
130+
) -> RegexMatch<Match>? {
119131
// Casts a Swift tuple to the custom `Tuple<n>`, assuming their memory
120132
// layout is compatible.
121133
func bitCastToMatch<T>(_ x: T) -> Match {
@@ -125,7 +137,9 @@ extension RegexProtocol {
125137
// TODO: Remove this branch when the matching engine supports captures.
126138
if regex.ast.hasCapture {
127139
let vm = HareVM(program: regex.program.legacyLoweredProgram)
128-
guard let (range, captures) = vm.execute(input: input)?.destructure else {
140+
guard let (range, captures) = vm.execute(
141+
input: input, in: inputRange, mode: .wholeString
142+
)?.destructure else {
129143
return nil
130144
}
131145
let convertedMatch: Match
@@ -142,7 +156,9 @@ extension RegexProtocol {
142156
return RegexMatch(range: range, match: convertedMatch)
143157
}
144158
let executor = Executor(program: regex.program.loweredProgram)
145-
guard let result = executor.execute(input: input) else {
159+
guard let result = executor.execute(
160+
input: input, in: inputRange, mode: .wholeString
161+
) else {
146162
return nil
147163
}
148164
let convertedMatch: Match
@@ -169,7 +185,17 @@ extension String {
169185
match(content())
170186
}
171187
}
188+
extension Substring {
189+
public func match<R: RegexProtocol>(_ regex: R) -> RegexMatch<R.Match>? {
190+
regex.match(in: self)
191+
}
172192

193+
public func match<R: RegexProtocol>(
194+
@RegexBuilder _ content: () -> R
195+
) -> RegexMatch<R.Match>? {
196+
match(content())
197+
}
198+
}
173199
public struct MockRegexLiteral<Match: MatchProtocol>: RegexProtocol {
174200
public typealias MatchValue = Substring
175201
public let regex: Regex<Match>

Tests/RegexTests/RegexDSLTests.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ class RegexDSLTests: XCTestCase {
2323
let _: Tuple3<Substring, Substring, Int>.Type = type(of: regex).Match.self
2424
let maybeMatch = "ab1".match(regex)
2525
let match = try XCTUnwrap(maybeMatch)
26-
XCTAssertTrue(match.match == Tuple3("ab1", "b", 1))
26+
XCTAssertEqual(match.match, Tuple3("ab1", "b", 1))
27+
28+
let substring = "ab1"[...]
29+
let substringMatch = try XCTUnwrap(
30+
substring.match(regex))
31+
XCTAssertEqual(match.match, substringMatch.match)
2732
}
2833

2934
func testCharacterClasses() throws {

0 commit comments

Comments
 (0)