@@ -89,7 +89,7 @@ struct StandardErrorStream: TextOutputStream {
8989var standardError = StandardErrorStream ( )
9090
9191typealias Counter = Int64
92- let patternProtocolName = " RegexProtocol "
92+ let regexProtocolName = " RegexProtocol "
9393let concatenationStructTypeBaseName = " Concatenate "
9494let capturingGroupTypeBaseName = " CapturingGroup "
9595let matchAssociatedTypeName = " Match "
@@ -132,9 +132,10 @@ struct VariadicsGenerator: ParsableCommand {
132132 emitTupleStruct ( arity: arity)
133133 }
134134
135+ print ( " Generating concatenation overloads... " , to: & standardError)
135136 for (leftArity, rightArity) in Permutations ( totalArity: maxArity) {
136137 print (
137- " Left arity: \( leftArity) Right arity: \( rightArity) " ,
138+ " Left arity: \( leftArity) Right arity: \( rightArity) " ,
138139 to: & standardError)
139140 emitConcatenation ( leftArity: leftArity, rightArity: rightArity)
140141 }
@@ -144,7 +145,20 @@ struct VariadicsGenerator: ParsableCommand {
144145 }
145146
146147 output ( " \n \n " )
147- output ( " // END AUTO-GENERATED CONTENT " )
148+
149+ print ( " Generating quantifiers... " , to: & standardError)
150+ for arity in 0 ..< maxArity {
151+ print ( " Arity \( arity) : " , terminator: " " , to: & standardError)
152+ for kind in QuantifierKind . allCases {
153+ print ( " \( kind. rawValue) " , terminator: " " , to: & standardError)
154+ emitQuantifier ( kind: kind, arity: arity)
155+ }
156+ print ( to: & standardError)
157+ }
158+
159+ output ( " \n \n " )
160+
161+ output ( " // END AUTO-GENERATED CONTENT \n " )
148162
149163 print ( " Done! " , to: & standardError)
150164 }
@@ -231,7 +245,7 @@ struct VariadicsGenerator: ParsableCommand {
231245 }
232246 output ( " , " )
233247 if withConstraints {
234- output ( " R0: \( patternProtocolName ) , R1: \( patternProtocolName ) " )
248+ output ( " R0: \( regexProtocolName ) , R1: \( regexProtocolName ) " )
235249 } else {
236250 output ( " R0, R1 " )
237251 }
@@ -268,7 +282,7 @@ struct VariadicsGenerator: ParsableCommand {
268282 let typeName = " \( concatenationStructTypeBaseName) _ \( leftArity) _ \( rightArity) "
269283 output ( " public struct \( typeName) < \n " )
270284 emitGenericParameters ( withConstraints: true )
271- output ( " \n >: \( patternProtocolName ) " )
285+ output ( " \n >: \( regexProtocolName ) " )
272286 output ( " where " )
273287 output ( " R0.Match == " )
274288 if leftArity == 0 {
@@ -343,7 +357,7 @@ struct VariadicsGenerator: ParsableCommand {
343357 " , C \( $0) "
344358 }
345359 output ( """
346- , R0: \( patternProtocolName ) , R1: \( patternProtocolName ) >(
360+ , R0: \( regexProtocolName ) , R1: \( regexProtocolName ) >(
347361 combining next: R1, into combined: R0
348362 ) -> Regex<
349363 """ )
@@ -374,4 +388,106 @@ struct VariadicsGenerator: ParsableCommand {
374388
375389 """ )
376390 }
391+
392+ enum QuantifierKind : String , CaseIterable {
393+ case zeroOrOne = " optionally "
394+ case zeroOrMore = " many "
395+ case oneOrMore = " oneOrMore "
396+
397+ var typeName : String {
398+ switch self {
399+ case . zeroOrOne: return " _ZeroOrOne "
400+ case . zeroOrMore: return " _ZeroOrMore "
401+ case . oneOrMore: return " _OneOrMore "
402+ }
403+ }
404+
405+ var operatorName : String {
406+ switch self {
407+ case . zeroOrOne: return " .? "
408+ case . zeroOrMore: return " .+ "
409+ case . oneOrMore: return " .* "
410+ }
411+ }
412+
413+ var astQuantifierAmount : String {
414+ switch self {
415+ case . zeroOrOne: return " zeroOrOne "
416+ case . zeroOrMore: return " zeroOrMore "
417+ case . oneOrMore: return " oneOrMore "
418+ }
419+ }
420+ }
421+
422+ func emitQuantifier( kind: QuantifierKind , arity: Int ) {
423+ assert ( arity >= 0 )
424+ func genericParameters( withConstraints: Bool ) -> String {
425+ var result = " "
426+ if arity > 0 {
427+ result += " W "
428+ result += ( 0 ..< arity) . map { " , C \( $0) " } . joined ( )
429+ result += " , "
430+ }
431+ result += " Component "
432+ if withConstraints {
433+ result += " : \( regexProtocolName) "
434+ }
435+ return result
436+ }
437+ let captures = ( 0 ..< arity) . map { " C \( $0) " } . joined ( separator: " , " )
438+ let capturesTupled = arity == 1 ? captures : " Tuple \( arity) < \( captures) > "
439+ let componentConstraint : String = arity == 0 ? " " :
440+ " where Component.Match == Tuple \( arity+ 1 ) <W, \( captures) > "
441+ let quantifiedCaptures : String = {
442+ switch kind {
443+ case . zeroOrOne:
444+ return " \( capturesTupled) ? "
445+ case . zeroOrMore, . oneOrMore:
446+ return " [ \( capturesTupled) ] "
447+ }
448+ } ( )
449+ let matchType = arity == 0 ? baseMatchTypeName : " Tuple2< \( baseMatchTypeName) , \( quantifiedCaptures) > "
450+ output ( """
451+ public struct \( kind. typeName) _ \( arity) < \( genericParameters ( withConstraints: true ) ) >: \( regexProtocolName) \( componentConstraint) {
452+ public typealias \( matchAssociatedTypeName) = \( matchType)
453+ public let regex: Regex< \( matchAssociatedTypeName) >
454+ public init(component: Component) {
455+ self.regex = .init(node: .quantification(. \( kind. astQuantifierAmount) , .eager, component.regex.root))
456+ }
457+ }
458+
459+ \( arity == 0 ? " @_disfavoredOverload " : " " )
460+ public func \( kind. rawValue) < \( genericParameters ( withConstraints: true ) ) >(
461+ _ component: Component
462+ ) -> \( kind. typeName) _ \( arity) < \( genericParameters ( withConstraints: false ) ) > {
463+ .init(component: component)
464+ }
465+
466+ \( arity == 0 ? " @_disfavoredOverload " : " " )
467+ public func \( kind. rawValue) < \( genericParameters ( withConstraints: true ) ) >(
468+ @RegexBuilder _ component: () -> Component
469+ ) -> \( kind. typeName) _ \( arity) < \( genericParameters ( withConstraints: false ) ) > {
470+ \( kind. rawValue) (component())
471+ }
472+
473+ \( arity == 0 ? " @_disfavoredOverload " : " " )
474+ public postfix func \( kind. operatorName) < \( genericParameters ( withConstraints: true ) ) >(
475+ _ component: Component
476+ ) -> \( kind. typeName) _ \( arity) < \( genericParameters ( withConstraints: false ) ) > {
477+ \( kind. rawValue) (component)
478+ }
479+
480+ \( kind == . zeroOrOne ?
481+ """
482+ extension RegexBuilder {
483+ public static func buildLimitedAvailability< \( genericParameters ( withConstraints: true ) ) >(
484+ _ component: Component
485+ ) -> \( kind. typeName) _ \( arity) < \( genericParameters ( withConstraints: false ) ) > {
486+ \( kind. rawValue) (component)
487+ }
488+ }
489+ """ : " " )
490+
491+ """ )
492+ }
377493}
0 commit comments