Skip to content

Commit 2a524e7

Browse files
Azoyhamishknight
authored andcommitted
Remove the namedCaptureOffset and StructuredCapture
1 parent 7d20453 commit 2a524e7

File tree

7 files changed

+43
-57
lines changed

7 files changed

+43
-57
lines changed

Sources/_StringProcessing/Capture.swift

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,6 @@
1111

1212
@_implementationOnly import _RegexParser
1313

14-
/// A structured capture
15-
struct StructuredCapture {
16-
/// The `.optional` height of the result
17-
var optionalCount = 0
18-
19-
var storedCapture: StoredCapture?
20-
21-
var someCount: Int {
22-
storedCapture == nil ? optionalCount - 1 : optionalCount
23-
}
24-
}
25-
26-
/// A storage form for a successful capture
27-
struct StoredCapture {
28-
// TODO: drop optional when engine tracks all ranges
29-
var range: Range<String.Index>?
30-
31-
// If strongly typed, value is set
32-
var value: Any? = nil
33-
}
34-
3514
// TODO: Where should this live? Inside TypeConstruction?
3615
func constructExistentialOutputComponent(
3716
from input: Substring,

Sources/_StringProcessing/Engine/Structuralize.swift

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
@_implementationOnly import _RegexParser
2-
32
extension CaptureList {
4-
func structuralize(
3+
@available(SwiftStdlib 5.7, *)
4+
func createElements(
55
_ list: MECaptureList,
66
_ input: String
7-
) -> [StructuredCapture] {
7+
) -> [AnyRegexOutput.ElementRepresentation] {
88
assert(list.values.count == captures.count)
9-
10-
var result = [StructuredCapture]()
11-
for (cap, meStored) in zip(self.captures, list.values) {
12-
let stored = StoredCapture(
13-
range: meStored.latest, value: meStored.latestValue)
14-
15-
result.append(.init(
16-
optionalCount: cap.optionalDepth, storedCapture: stored))
9+
10+
var result = [AnyRegexOutput.ElementRepresentation]()
11+
12+
for (cap, meStored) in zip(captures, list.values) {
13+
let element = AnyRegexOutput.ElementRepresentation(
14+
optionalDepth: cap.optionalDepth,
15+
bounds: meStored.latest,
16+
name: cap.name,
17+
value: meStored.latestValue
18+
)
19+
20+
result.append(element)
1721
}
22+
1823
return result
1924
}
2025
}

Sources/_StringProcessing/Executor.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct Executor {
4040
referencedCaptureOffsets: engine.program.referencedCaptureOffsets)
4141

4242
let range = inputRange.lowerBound..<endIdx
43-
let caps = engine.program.captureList.structuralize(capList, input)
43+
let caps = engine.program.captureList.createElements(capList, input)
4444

4545
// FIXME: This is a workaround for not tracking (or
4646
// specially compiling) whole-match values.
@@ -57,7 +57,6 @@ struct Executor {
5757

5858
let anyRegexOutput = AnyRegexOutput(
5959
input: input,
60-
namedCaptureOffsets: capList.namedCaptureOffsets,
6160
elements: caps
6261
)
6362

Sources/_StringProcessing/Regex/AnyRegexOutput.swift

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,16 @@ extension Regex.Match where Output == AnyRegexOutput {
4545
}
4646

4747
public subscript(name: String) -> AnyRegexOutput.Element? {
48-
anyRegexOutput.namedCaptureOffsets[name].map { self[$0 + 1] }
48+
anyRegexOutput.first {
49+
$0.name == name
50+
}
4951
}
5052
}
5153

5254
/// A type-erased regex output.
5355
@available(SwiftStdlib 5.7, *)
5456
public struct AnyRegexOutput {
5557
let input: String
56-
let namedCaptureOffsets: [String: Int]
5758
let _elements: [ElementRepresentation]
5859

5960
/// The underlying representation of the element of a type-erased regex
@@ -65,6 +66,10 @@ public struct AnyRegexOutput {
6566

6667
/// The bounds of the output element.
6768
let bounds: Range<String.Index>?
69+
70+
/// The name of the capture.
71+
var name: String? = nil
72+
6873
/// If the output vaule is strongly typed, then this will be set.
6974
var value: Any? = nil
7075
}
@@ -96,27 +101,16 @@ extension AnyRegexOutput {
96101

97102
@available(SwiftStdlib 5.7, *)
98103
extension AnyRegexOutput {
99-
internal init<C: Collection>(
100-
input: String, namedCaptureOffsets: [String: Int], elements: C
101-
) where C.Element == StructuredCapture {
104+
internal init(input: String, elements: [ElementRepresentation]) {
102105
self.init(
103106
input: input,
104-
namedCaptureOffsets: namedCaptureOffsets,
105-
_elements: elements.map(ElementRepresentation.init)
107+
_elements: elements
106108
)
107109
}
108110
}
109111

110112
@available(SwiftStdlib 5.7, *)
111113
extension AnyRegexOutput.ElementRepresentation {
112-
init(_ element: StructuredCapture) {
113-
self.init(
114-
optionalDepth: element.optionalCount,
115-
bounds: element.storedCapture.flatMap(\.range),
116-
value: element.storedCapture.flatMap(\.value)
117-
)
118-
}
119-
120114
func value(forInput input: String) -> Any {
121115
// Ok for now because `existentialMatchComponent`
122116
// wont slice the input if there's no range to slice with
@@ -128,7 +122,8 @@ extension AnyRegexOutput.ElementRepresentation {
128122
from: input,
129123
in: bounds,
130124
value: nil,
131-
optionalCount: optionalDepth)
125+
optionalCount: optionalDepth
126+
)
132127
}
133128
}
134129

@@ -141,7 +136,11 @@ extension AnyRegexOutput: RandomAccessCollection {
141136
var optionalDepth: Int {
142137
representation.optionalDepth
143138
}
144-
139+
140+
var name: String? {
141+
representation.name
142+
}
143+
145144
/// The range over which a value was captured. `nil` for no-capture.
146145
public var range: Range<String.Index>? {
147146
representation.bounds
@@ -186,7 +185,9 @@ extension AnyRegexOutput: RandomAccessCollection {
186185
@available(SwiftStdlib 5.7, *)
187186
extension AnyRegexOutput {
188187
public subscript(name: String) -> Element? {
189-
namedCaptureOffsets[name].map { self[$0 + 1] }
188+
first {
189+
$0.name == name
190+
}
190191
}
191192
}
192193

Sources/_StringProcessing/Regex/Match.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ extension Regex.Match {
4141

4242
let output = AnyRegexOutput(
4343
input: anyRegexOutput.input,
44-
namedCaptureOffsets: anyRegexOutput.namedCaptureOffsets,
4544
_elements: [wholeMatchCapture] + anyRegexOutput._elements
4645
)
4746

Sources/_StringProcessing/Utility/TypeVerification.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ extension Regex {
4242

4343
let createdType = TypeConstruction.tupleType(
4444
of: tupleElements,
45-
labels: labels
45+
46+
// If all of our labels are spaces, that means no actual label was added
47+
// to the tuple. In that case, don't pass a label string.
48+
labels: labels.all { $0 == " " } ? nil : labels
4649
)
4750

4851
return Output.self == createdType

Tests/RegexTests/CaptureTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,17 +461,17 @@ extension RegexTests {
461461

462462
func testTypeVerification() throws {
463463
let opaque1 = try Regex("abc")
464-
let concrete1 = try XCTUnwrap(opaque1.as(Substring.self))
464+
_ = try XCTUnwrap(opaque1.as(Substring.self))
465465
XCTAssertNil(opaque1.as((Substring, Substring).self))
466466
XCTAssertNil(opaque1.as(Int.self))
467467

468468
let opaque2 = try Regex("(abc)")
469-
let concrete2 = try XCTUnwrap(opaque2.as((Substring, Substring).self))
469+
_ = try XCTUnwrap(opaque2.as((Substring, Substring).self))
470470
XCTAssertNil(opaque2.as(Substring.self))
471471
XCTAssertNil(opaque2.as((Substring, Int).self))
472472

473473
let opaque3 = try Regex("(?<someLabel>abc)")
474-
let concrete3 = try XCTUnwrap(opaque3.as((Substring, someLabel: Substring).self))
474+
_ = try XCTUnwrap(opaque3.as((Substring, someLabel: Substring).self))
475475
XCTAssertNil(opaque3.as((Substring, Substring).self))
476476
XCTAssertNil(opaque3.as(Substring.self))
477477
}

0 commit comments

Comments
 (0)