Skip to content

Commit 883d358

Browse files
authored
Prefix capture and tryCapture. (#151)
Introduce free functions `capture(_:)`, `capture(_:transform:)`, `tryCapture(_:transform:)` for capturing. Remove postfix modifiers `.capture` and `.tryCapture`.
1 parent 60b8f26 commit 883d358

File tree

7 files changed

+1054
-283
lines changed

7 files changed

+1054
-283
lines changed

Sources/Exercises/Participants/RegexParticipant.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ private func graphemeBreakPropertyData(
8080
forLine line: String
8181
) -> GraphemeBreakEntry? {
8282
line.match {
83-
oneOrMore(.hexDigit).tryCapture(Unicode.Scalar.init(hex:))
83+
tryCapture(oneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) }
8484
optionally {
8585
".."
86-
oneOrMore(.hexDigit).tryCapture(Unicode.Scalar.init(hex:))
86+
tryCapture(oneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) }
8787
}
8888
oneOrMore(.whitespace)
8989
";"
9090
oneOrMore(.whitespace)
91-
oneOrMore(.word).tryCapture(Unicode.GraphemeBreakProperty.init)
91+
tryCapture(oneOrMore(.word)) { Unicode.GraphemeBreakProperty($0) }
9292
many(.any)
9393
}.map {
9494
let (_, lower, upper, property) = $0.match

Sources/VariadicsGenerator/VariadicsGenerator.swift

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ struct VariadicsGenerator: ParsableCommand {
174174
emitUnaryAlternationBuildBlock(arity: arity)
175175
}
176176

177+
print("Generating 'capture' and 'tryCapture' overloads...", to: &standardError)
178+
for arity in 0..<maxArity {
179+
print(" Capture arity: \(arity)", to: &standardError)
180+
emitCapture(arity: arity)
181+
}
182+
177183
output("\n\n")
178184

179185
output("// END AUTO-GENERATED CONTENT\n")
@@ -471,4 +477,105 @@ struct VariadicsGenerator: ParsableCommand {
471477
472478
""")
473479
}
480+
481+
func emitCapture(arity: Int) {
482+
let genericParams = arity == 0
483+
? "R: \(regexProtocolName), W"
484+
: "R: \(regexProtocolName), W, " + (0..<arity).map { "C\($0)" }.joined(separator: ", ")
485+
let matchType = arity == 0
486+
? "W"
487+
: "(W, " + (0..<arity).map { "C\($0)" }.joined(separator: ", ") + ")"
488+
func newMatchType(transformed: Bool) -> String {
489+
let newCaptureType = transformed ? "NewCapture" : baseMatchTypeName
490+
return arity == 0
491+
? "(W, \(newCaptureType))"
492+
: "(W, \(newCaptureType), " + (0..<arity).map { "C\($0)" }.joined(separator: ", ") + ")"
493+
}
494+
let whereClause = "where R.\(matchAssociatedTypeName) == \(matchType)"
495+
output("""
496+
// MARK: - Non-builder capture arity \(arity)
497+
498+
public func capture<\(genericParams)>(_ component: R) -> \(regexTypeName)<\(newMatchType(transformed: false))> \(whereClause) {
499+
.init(node: .group(.capture, component.regex.root))
500+
}
501+
502+
public func capture<\(genericParams), NewCapture>(
503+
_ component: R, transform: @escaping (Substring) -> NewCapture
504+
) -> \(regexTypeName)<\(newMatchType(transformed: true))> \(whereClause) {
505+
.init(node: .groupTransform(
506+
.capture,
507+
component.regex.root,
508+
CaptureTransform(resultType: NewCapture.self) {
509+
transform($0) as Any
510+
}))
511+
}
512+
513+
public func tryCapture<\(genericParams), NewCapture>(
514+
_ component: R, transform: @escaping (Substring) throws -> NewCapture
515+
) -> \(regexTypeName)<\(newMatchType(transformed: true))> \(whereClause) {
516+
.init(node: .groupTransform(
517+
.capture,
518+
component.regex.root,
519+
CaptureTransform(resultType: NewCapture.self) {
520+
try transform($0) as Any
521+
}))
522+
}
523+
524+
public func tryCapture<\(genericParams), NewCapture>(
525+
_ component: R, transform: @escaping (Substring) -> NewCapture?
526+
) -> \(regexTypeName)<\(newMatchType(transformed: true))> \(whereClause) {
527+
.init(node: .groupTransform(
528+
.capture,
529+
component.regex.root,
530+
CaptureTransform(resultType: NewCapture.self) {
531+
transform($0) as Any?
532+
}))
533+
}
534+
535+
// MARK: - Builder capture arity \(arity)
536+
537+
public func capture<\(genericParams)>(
538+
@RegexBuilder _ component: () -> R
539+
) -> \(regexTypeName)<\(newMatchType(transformed: false))> \(whereClause) {
540+
.init(node: .group(.capture, component().regex.root))
541+
}
542+
543+
public func capture<\(genericParams), NewCapture>(
544+
@RegexBuilder _ component: () -> R,
545+
transform: @escaping (Substring) -> NewCapture
546+
) -> \(regexTypeName)<\(newMatchType(transformed: true))> \(whereClause) {
547+
.init(node: .groupTransform(
548+
.capture,
549+
component().regex.root,
550+
CaptureTransform(resultType: NewCapture.self) {
551+
transform($0) as Any
552+
}))
553+
}
554+
555+
public func tryCapture<\(genericParams), NewCapture>(
556+
@RegexBuilder _ component: () -> R,
557+
transform: @escaping (Substring) throws -> NewCapture
558+
) -> \(regexTypeName)<\(newMatchType(transformed: true))> \(whereClause) {
559+
.init(node: .groupTransform(
560+
.capture,
561+
component().regex.root,
562+
CaptureTransform(resultType: NewCapture.self) {
563+
try transform($0) as Any
564+
}))
565+
}
566+
567+
public func tryCapture<\(genericParams), NewCapture>(
568+
@RegexBuilder _ component: () -> R,
569+
transform: @escaping (Substring) -> NewCapture?
570+
) -> \(regexTypeName)<\(newMatchType(transformed: true))> \(whereClause) {
571+
.init(node: .groupTransform(
572+
.capture,
573+
component().regex.root,
574+
CaptureTransform(resultType: NewCapture.self) {
575+
transform($0) as Any?
576+
}))
577+
}
578+
579+
""")
580+
}
474581
}

Sources/_StringProcessing/RegexDSL/DSL.swift

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -150,59 +150,3 @@ public func oneOf<R: RegexProtocol>(
150150
) -> R {
151151
builder()
152152
}
153-
154-
// MARK: - Capture
155-
156-
public struct CapturingGroup<Match>: RegexProtocol {
157-
public let regex: Regex<Match>
158-
159-
init<Component: RegexProtocol>(
160-
_ component: Component
161-
) {
162-
self.regex = .init(node: .group(
163-
.capture, component.regex.root))
164-
}
165-
166-
init<Component: RegexProtocol>(
167-
_ component: Component,
168-
transform: CaptureTransform
169-
) {
170-
self.regex = .init(node: .groupTransform(
171-
.capture,
172-
component.regex.root,
173-
transform))
174-
}
175-
176-
init<NewCapture, Component: RegexProtocol>(
177-
_ component: Component,
178-
transform: @escaping (Substring) -> NewCapture
179-
) {
180-
self.init(
181-
component,
182-
transform: CaptureTransform(resultType: NewCapture.self) {
183-
transform($0) as Any
184-
})
185-
}
186-
187-
init<NewCapture, Component: RegexProtocol>(
188-
_ component: Component,
189-
transform: @escaping (Substring) throws -> NewCapture
190-
) {
191-
self.init(
192-
component,
193-
transform: CaptureTransform(resultType: NewCapture.self) {
194-
try transform($0) as Any
195-
})
196-
}
197-
198-
init<NewCapture, Component: RegexProtocol>(
199-
_ component: Component,
200-
transform: @escaping (Substring) -> NewCapture?
201-
) {
202-
self.init(
203-
component,
204-
transform: CaptureTransform(resultType: NewCapture.self) {
205-
transform($0) as Any?
206-
})
207-
}
208-
}

Sources/_StringProcessing/RegexDSL/DSLCapture.swift

Lines changed: 0 additions & 120 deletions
This file was deleted.

0 commit comments

Comments
 (0)