Skip to content

Commit f2ed846

Browse files
committed
DSL free functions -> types
Replace free functions such as `oneOrMore` with types such as `OneOrMore`. This hides overloads of free functions as initializers within those types. It also makes the DSL consistent with SwiftUI. - `oneOrMore` -> `OneOrMore` - `zeroOrMore` -> `ZeroOrMore` - `optionally` -> `Optionally` - `repeating` -> `Repeat` - `choiceOf` -> `ChoiceOf` - `capture` -> `Capture` - `tryCapture` -> `TryCapture` Note: The reason we didn't realize this was possible (e.g. in #126) was because we were narrowly focused on including the subpattern type in the quantifier/combinator's generic parameter, i.e. `OneOrMore<Component: RegexComponent>`, which made it impossible to deduce each type's `typealias Match` from `Component`. Now we have an unconstrained generic parameter (e.g. `OneOrMore<Match>`) which gives us the full flexibility to hide `Match` deduction rules in initializers' type signatures.
1 parent cd3ad6d commit f2ed846

File tree

8 files changed

+3594
-2652
lines changed

8 files changed

+3594
-2652
lines changed

Sources/Exercises/Participants/RegexParticipant.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,16 @@ private func graphemeBreakPropertyData(
8080
forLine line: String
8181
) -> GraphemeBreakEntry? {
8282
line.match {
83-
tryCapture(oneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) }
84-
optionally {
83+
TryCapture(OneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) }
84+
Optionally {
8585
".."
86-
tryCapture(oneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) }
86+
TryCapture(OneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) }
8787
}
88-
oneOrMore(.whitespace)
88+
OneOrMore(.whitespace)
8989
";"
90-
oneOrMore(.whitespace)
91-
tryCapture(oneOrMore(.word)) { Unicode.GraphemeBreakProperty($0) }
92-
zeroOrMore(.any)
90+
OneOrMore(.whitespace)
91+
TryCapture(OneOrMore(.word)) { Unicode.GraphemeBreakProperty($0) }
92+
ZeroOrMore(.any)
9393
}.map {
9494
let (_, lower, upper, property) = $0.match
9595
return GraphemeBreakEntry(lower...(upper ?? lower), property)

Sources/VariadicsGenerator/VariadicsGenerator.swift

+260-199
Large diffs are not rendered by default.

Sources/_StringProcessing/RegexDSL/Builder.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111

1212
@resultBuilder
1313
public enum RegexComponentBuilder {
14-
@_disfavoredOverload
14+
public static func buildBlock() -> Regex<Substring> {
15+
.init(node: .empty)
16+
}
17+
18+
// TODO: Rename to `buildPartialBlock(first:)` when the feature lands.
1519
public static func buildBlock<R0: RegexComponent>(_ r0: R0) -> R0 {
1620
r0
1721
}

Sources/_StringProcessing/RegexDSL/DSL.swift

+89-37
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111

1212
import _MatchingEngine
1313

14+
// A convenience protocol for builtin regex components that are initialized with
15+
// a `DSLTree` node.
16+
internal protocol _BuiltinRegexComponent: RegexComponent {
17+
init(_ regex: Regex<Match>)
18+
}
19+
20+
extension _BuiltinRegexComponent {
21+
init(node: DSLTree.Node) {
22+
self.init(Regex(node: node))
23+
}
24+
}
25+
1426
// MARK: - Primitives
1527

1628
extension String: RegexComponent {
@@ -115,37 +127,49 @@ extension QuantificationBehavior {
115127
}
116128
}
117129

118-
// TODO: Variadic generics
119-
// struct _OneOrMore<W, C..., Component: RegexComponent>
120-
// where R.Match == (W, C...)
121-
// {
122-
// typealias Match = (Substring, [(C...)])
123-
// let regex: Regex<Match>
124-
// init(_ component: Component) {
125-
// regex = .init(oneOrMore(r0))
126-
// }
127-
// }
128-
//
129-
// struct _OneOrMoreNonCapturing<Component: RegexComponent> {
130-
// typealias Match = Substring
131-
// let regex: Regex<Match>
132-
// init(_ component: Component) {
133-
// regex = .init(oneOrMore(r0))
134-
// }
135-
// }
136-
//
137-
// func oneOrMore<W, C..., Component: RegexComponent>(
138-
// _ component: Component
139-
// ) -> <R: RegexComponent where R.Match == (Substring, [(C...)])> R {
140-
// _OneOrMore(component)
141-
// }
142-
//
143-
// @_disfavoredOverload
144-
// func oneOrMore<Component: RegexComponent>(
145-
// _ component: Component
146-
// ) -> <R: RegexComponent where R.Match == Substring> R {
147-
// _OneOrMoreNonCapturing(component)
148-
// }
130+
public struct OneOrMore<Match>: _BuiltinRegexComponent {
131+
public var regex: Regex<Match>
132+
133+
internal init(_ regex: Regex<Match>) {
134+
self.regex = regex
135+
}
136+
137+
// Note: Public initializers and operators are currently gyb'd. See
138+
// Variadics.swift.
139+
}
140+
141+
public struct ZeroOrMore<Match>: _BuiltinRegexComponent {
142+
public var regex: Regex<Match>
143+
144+
internal init(_ regex: Regex<Match>) {
145+
self.regex = regex
146+
}
147+
148+
// Note: Public initializers and operators are currently gyb'd. See
149+
// Variadics.swift.
150+
}
151+
152+
public struct Optionally<Match>: _BuiltinRegexComponent {
153+
public var regex: Regex<Match>
154+
155+
internal init(_ regex: Regex<Match>) {
156+
self.regex = regex
157+
}
158+
159+
// Note: Public initializers and operators are currently gyb'd. See
160+
// Variadics.swift.
161+
}
162+
163+
public struct Repeat<Match>: _BuiltinRegexComponent {
164+
public var regex: Regex<Match>
165+
166+
internal init(_ regex: Regex<Match>) {
167+
self.regex = regex
168+
}
169+
170+
// Note: Public initializers and operators are currently gyb'd. See
171+
// Variadics.swift.
172+
}
149173

150174
postfix operator .?
151175
postfix operator .*
@@ -168,8 +192,8 @@ postfix operator .+
168192
@resultBuilder
169193
public struct AlternationBuilder {
170194
@_disfavoredOverload
171-
public static func buildBlock<R: RegexComponent>(_ regex: R) -> R {
172-
regex
195+
public static func buildBlock<R: RegexComponent>(_ component: R) -> ChoiceOf<R.Match> {
196+
.init(component.regex)
173197
}
174198

175199
public static func buildExpression<R: RegexComponent>(_ regex: R) -> R {
@@ -185,10 +209,38 @@ public struct AlternationBuilder {
185209
}
186210
}
187211

188-
public func choiceOf<R: RegexComponent>(
189-
@AlternationBuilder builder: () -> R
190-
) -> R {
191-
builder()
212+
public struct ChoiceOf<Match>: _BuiltinRegexComponent {
213+
public var regex: Regex<Match>
214+
215+
internal init(_ regex: Regex<Match>) {
216+
self.regex = regex
217+
}
218+
219+
public init(@AlternationBuilder _ builder: () -> Self) {
220+
self = builder()
221+
}
222+
}
223+
224+
// MARK: - Capture
225+
226+
public struct Capture<Match>: _BuiltinRegexComponent {
227+
public var regex: Regex<Match>
228+
229+
internal init(_ regex: Regex<Match>) {
230+
self.regex = regex
231+
}
232+
233+
// Note: Public initializers are currently gyb'd. See Variadics.swift.
234+
}
235+
236+
public struct TryCapture<Match>: _BuiltinRegexComponent {
237+
public var regex: Regex<Match>
238+
239+
internal init(_ regex: Regex<Match>) {
240+
self.regex = regex
241+
}
242+
243+
// Note: Public initializers are currently gyb'd. See Variadics.swift.
192244
}
193245

194246
// MARK: - Backreference

0 commit comments

Comments
 (0)