@@ -151,6 +151,8 @@ struct VariadicsGenerator: ParsableCommand {
151
151
print ( " \( kind. rawValue) " , terminator: " " , to: & standardError)
152
152
emitQuantifier ( kind: kind, arity: arity)
153
153
}
154
+ print ( " repeating " , terminator: " " , to: & standardError)
155
+ emitRepeating ( arity: arity)
154
156
print ( to: & standardError)
155
157
}
156
158
@@ -307,69 +309,140 @@ struct VariadicsGenerator: ParsableCommand {
307
309
}
308
310
}
309
311
}
312
+
313
+ struct QuantifierParameters {
314
+ var disfavored : String
315
+ var genericParams : String
316
+ var whereClause : String
317
+ var quantifiedCaptures : String
318
+ var matchType : String
319
+
320
+ var repeatingWhereClause : String {
321
+ whereClause. isEmpty
322
+ ? " where R.Bound == Int "
323
+ : whereClause + " , R.Bound == Int "
324
+ }
325
+
326
+ init ( kind: QuantifierKind , arity: Int ) {
327
+ self . disfavored = arity == 0 ? " @_disfavoredOverload \n " : " "
328
+ self . genericParams = {
329
+ var result = " "
330
+ if arity > 0 {
331
+ result += " W "
332
+ result += ( 0 ..< arity) . map { " , C \( $0) " } . joined ( )
333
+ result += " , "
334
+ }
335
+ result += " Component: \( regexProtocolName) "
336
+ return result
337
+ } ( )
338
+
339
+ let captures = ( 0 ..< arity) . map { " C \( $0) " }
340
+ let capturesJoined = captures. joined ( separator: " , " )
341
+ self . whereClause = arity == 0 ? " " :
342
+ " where Component.Match == (W, \( capturesJoined) ) "
343
+ self . quantifiedCaptures = {
344
+ switch kind {
345
+ case . zeroOrOne, . zeroOrMore:
346
+ return captures. map { " \( $0) ? " } . joined ( separator: " , " )
347
+ case . oneOrMore:
348
+ return capturesJoined
349
+ }
350
+ } ( )
351
+ self . matchType = arity == 0
352
+ ? baseMatchTypeName
353
+ : " ( \( baseMatchTypeName) , \( quantifiedCaptures) ) "
354
+ }
355
+ }
310
356
311
357
func emitQuantifier( kind: QuantifierKind , arity: Int ) {
312
358
assert ( arity >= 0 )
313
- let genericParams : String = {
314
- var result = " "
315
- if arity > 0 {
316
- result += " W "
317
- result += ( 0 ..< arity) . map { " , C \( $0) " } . joined ( )
318
- result += " , "
319
- }
320
- result += " Component: \( regexProtocolName) "
321
- return result
322
- } ( )
323
- let captures = ( 0 ..< arity) . map { " C \( $0) " }
324
- let capturesJoined = captures. joined ( separator: " , " )
325
- let whereClause : String = arity == 0 ? " " :
326
- " where Component.Match == (W, \( capturesJoined) ) "
327
- let quantifiedCaptures : String = {
328
- switch kind {
329
- case . zeroOrOne, . zeroOrMore:
330
- return captures. map { " \( $0) ? " } . joined ( separator: " , " )
331
- case . oneOrMore:
332
- return capturesJoined
333
- }
334
- } ( )
335
- let matchType = arity == 0 ? baseMatchTypeName : " ( \( baseMatchTypeName) , \( quantifiedCaptures) ) "
359
+ let params = QuantifierParameters ( kind: kind, arity: arity)
336
360
output ( """
337
- \( arity == 0 ? " @_disfavoredOverload " : " " )
338
- public func \( kind. rawValue) < \( genericParams) >(
361
+ \( params . disfavored ) \
362
+ public func \( kind. rawValue) < \( params . genericParams) >(
339
363
_ component: Component,
340
364
_ behavior: QuantificationBehavior = .eagerly
341
- ) -> \( regexTypeName) < \( matchType) > \( whereClause) {
365
+ ) -> \( regexTypeName) < \( params . matchType) > \( params . whereClause) {
342
366
.init(node: .quantification(. \( kind. astQuantifierAmount) , behavior.astKind, component.regex.root))
343
367
}
344
368
345
- \( arity == 0 ? " @_disfavoredOverload " : " " )
346
- public func \( kind. rawValue) < \( genericParams) >(
369
+ \( params . disfavored ) \
370
+ public func \( kind. rawValue) < \( params . genericParams) >(
347
371
_ behavior: QuantificationBehavior = .eagerly,
348
372
@RegexBuilder _ component: () -> Component
349
- ) -> \( regexTypeName) < \( matchType) > \( whereClause) {
373
+ ) -> \( regexTypeName) < \( params . matchType) > \( params . whereClause) {
350
374
.init(node: .quantification(. \( kind. astQuantifierAmount) , behavior.astKind, component().regex.root))
351
375
}
352
376
353
- \( arity == 0 ? " @_disfavoredOverload " : " " )
354
- public postfix func \( kind. operatorName) < \( genericParams) >(
377
+ \( params . disfavored ) \
378
+ public postfix func \( kind. operatorName) < \( params . genericParams) >(
355
379
_ component: Component
356
- ) -> \( regexTypeName) < \( matchType) > \( whereClause) {
380
+ ) -> \( regexTypeName) < \( params . matchType) > \( params . whereClause) {
357
381
.init(node: .quantification(. \( kind. astQuantifierAmount) , .eager, component.regex.root))
358
382
}
359
383
360
384
\( kind == . zeroOrOne ?
361
385
"""
362
386
extension RegexBuilder {
363
- public static func buildLimitedAvailability< \( genericParams) >(
387
+ public static func buildLimitedAvailability< \( params . genericParams) >(
364
388
_ component: Component
365
- ) -> \( regexTypeName) < \( matchType) > \( whereClause) {
389
+ ) -> \( regexTypeName) < \( params . matchType) > \( params . whereClause) {
366
390
.init(node: .quantification(. \( kind. astQuantifierAmount) , .eager, component.regex.root))
367
391
}
368
392
}
369
393
""" : " " )
370
394
371
395
""" )
372
396
}
397
+
398
+ func emitRepeating( arity: Int ) {
399
+ assert ( arity >= 0 )
400
+ // `repeat(..<5)` has the same generic semantics as zeroOrMore
401
+ let params = QuantifierParameters ( kind: . zeroOrMore, arity: arity)
402
+ // TODO: Could `repeat(count:)` have the same generic semantics as oneOrMore?
403
+ // We would need to prohibit `repeat(count: 0)`; can only happen at runtime
404
+
405
+ output ( """
406
+ \( params. disfavored) \
407
+ public func repeating< \( params. genericParams) >(
408
+ _ component: Component,
409
+ count: Int
410
+ ) -> \( regexTypeName) < \( params. matchType) > \( params. whereClause) {
411
+ assert(count > 0, " Must specify a positive count " )
412
+ // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)`
413
+ return Regex(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root))
414
+ }
415
+
416
+ \( params. disfavored) \
417
+ public func repeating< \( params. genericParams) >(
418
+ count: Int,
419
+ @RegexBuilder _ component: () -> Component
420
+ ) -> \( regexTypeName) < \( params. matchType) > \( params. whereClause) {
421
+ assert(count > 0, " Must specify a positive count " )
422
+ // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)`
423
+ return Regex(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root))
424
+ }
425
+
426
+ \( params. disfavored) \
427
+ public func repeating< \( params. genericParams) , R: RangeExpression>(
428
+ _ component: Component,
429
+ _ expression: R,
430
+ _ behavior: QuantificationBehavior = .eagerly
431
+ ) -> \( regexTypeName) < \( params. matchType) > \( params. repeatingWhereClause) {
432
+ .init(node: .repeating(expression.relative(to: 0..<Int.max), behavior, component.regex.root))
433
+ }
434
+
435
+ \( params. disfavored) \
436
+ public func repeating< \( params. genericParams) , R: RangeExpression>(
437
+ _ expression: R,
438
+ _ behavior: QuantificationBehavior = .eagerly,
439
+ @RegexBuilder _ component: () -> Component
440
+ ) -> \( regexTypeName) < \( params. matchType) > \( params. repeatingWhereClause) {
441
+ .init(node: .repeating(expression.relative(to: 0..<Int.max), behavior, component().regex.root))
442
+ }
443
+
444
+ """ )
445
+ }
373
446
374
447
func emitAlternation( leftArity: Int , rightArity: Int ) {
375
448
let leftGenParams : String = {
0 commit comments