10
10
//===----------------------------------------------------------------------===//
11
11
12
12
import _MatchingEngine
13
+ @_spi ( RegexBuilder) import _StringProcessing
14
+ import _StringProcessing
15
+
16
+ extension Regex {
17
+ public init < Content: RegexComponent > (
18
+ @RegexComponentBuilder _ content: ( ) -> Content
19
+ ) where Content. Output == Output {
20
+ self . init ( content ( ) )
21
+ }
22
+ }
13
23
14
24
// A convenience protocol for builtin regex components that are initialized with
15
25
// a `DSLTree` node.
@@ -57,17 +67,6 @@ extension UnicodeScalar: RegexComponent {
57
67
}
58
68
}
59
69
60
- extension CharacterClass : RegexComponent {
61
- public typealias Output = Substring
62
-
63
- public var regex : Regex < Output > {
64
- guard let ast = self . makeAST ( ) else {
65
- fatalError ( " FIXME: extended AST? " )
66
- }
67
- return Regex ( ast: ast)
68
- }
69
- }
70
-
71
70
// MARK: - Combinators
72
71
73
72
// MARK: Concatenation
@@ -96,9 +95,9 @@ public struct QuantificationBehavior {
96
95
case reluctantly
97
96
case possessively
98
97
}
99
-
98
+
100
99
var kind : Kind
101
-
100
+
102
101
internal var astKind : AST . Quantification . Kind {
103
102
switch kind {
104
103
case . eagerly: return . eager
@@ -108,19 +107,49 @@ public struct QuantificationBehavior {
108
107
}
109
108
}
110
109
110
+ extension DSLTree . Node {
111
+ /// Generates a DSLTree node for a repeated range of the given DSLTree node.
112
+ /// Individual public API functions are in the generated Variadics.swift file.
113
+ static func repeating(
114
+ _ range: Range < Int > ,
115
+ _ behavior: QuantificationBehavior ,
116
+ _ node: DSLTree . Node
117
+ ) -> DSLTree . Node {
118
+ // TODO: Throw these as errors
119
+ assert ( range. lowerBound >= 0 , " Cannot specify a negative lower bound " )
120
+ assert ( !range. isEmpty, " Cannot specify an empty range " )
121
+
122
+ switch ( range. lowerBound, range. upperBound) {
123
+ case ( 0 , Int . max) : // 0...
124
+ return . quantification( . zeroOrMore, behavior. astKind, node)
125
+ case ( 1 , Int . max) : // 1...
126
+ return . quantification( . oneOrMore, behavior. astKind, node)
127
+ case _ where range. count == 1 : // ..<1 or ...0 or any range with count == 1
128
+ // Note: `behavior` is ignored in this case
129
+ return . quantification( . exactly( . init( faking: range. lowerBound) ) , . eager, node)
130
+ case ( 0 , _) : // 0..<n or 0...n or ..<n or ...n
131
+ return . quantification( . upToN( . init( faking: range. upperBound) ) , behavior. astKind, node)
132
+ case ( _, Int . max) : // n...
133
+ return . quantification( . nOrMore( . init( faking: range. lowerBound) ) , behavior. astKind, node)
134
+ default : // any other range
135
+ return . quantification( . range( . init( faking: range. lowerBound) , . init( faking: range. upperBound) ) , behavior. astKind, node)
136
+ }
137
+ }
138
+ }
139
+
111
140
extension QuantificationBehavior {
112
141
/// Match as much of the input string as possible, backtracking when
113
142
/// necessary.
114
143
public static var eagerly : QuantificationBehavior {
115
144
. init( kind: . eagerly)
116
145
}
117
-
146
+
118
147
/// Match as little of the input string as possible, expanding the matched
119
148
/// region as necessary to complete a match.
120
149
public static var reluctantly : QuantificationBehavior {
121
150
. init( kind: . reluctantly)
122
151
}
123
-
152
+
124
153
/// Match as much of the input string as possible, performing no backtracking.
125
154
public static var possessively : QuantificationBehavior {
126
155
. init( kind: . possessively)
@@ -247,22 +276,18 @@ public struct TryCapture<Output>: _BuiltinRegexComponent {
247
276
248
277
// MARK: - Backreference
249
278
250
- struct ReferenceID : Hashable , Equatable {
251
- private static var counter : Int = 0
252
- var base : Int
253
-
254
- init ( ) {
255
- base = Self . counter
256
- Self . counter += 1
257
- }
258
- }
259
-
260
279
public struct Reference < Capture> : RegexComponent {
261
280
let id = ReferenceID ( )
262
-
281
+
263
282
public init ( _ captureType: Capture . Type = Capture . self) { }
264
283
265
284
public var regex : Regex < Capture > {
266
285
. init( node: . atom( . symbolicReference( id) ) )
267
286
}
268
287
}
288
+
289
+ extension Regex . Match {
290
+ public subscript< Capture> ( _ reference: Reference < Capture > ) -> Capture {
291
+ self [ reference. id]
292
+ }
293
+ }
0 commit comments