diff --git a/Documentation/Evolution/RegexSyntax.md b/Documentation/Evolution/RegexSyntaxRunTimeConstruction.md similarity index 89% rename from Documentation/Evolution/RegexSyntax.md rename to Documentation/Evolution/RegexSyntaxRunTimeConstruction.md index faa327176..f3dda59ba 100644 --- a/Documentation/Evolution/RegexSyntax.md +++ b/Documentation/Evolution/RegexSyntaxRunTimeConstruction.md @@ -2,7 +2,7 @@ Hello, we want to issue an update to [Regular Expression Literals](https://forums.swift.org/t/pitch-regular-expression-literals/52820) and prepare for a formal proposal. The great delimiter deliberation continues to unfold, so in the meantime, we have a significant amount of surface area to present for review/feedback: the syntax _inside_ a regex literal. Additionally, this is the syntax accepted from a string used for run-time regex construction, so we're devoting an entire pitch/proposal to the topic of _regex syntax_, distinct from the result builder DSL or the choice of delimiters for literals. --> -# Run-time Regex Construction +# Regex Syntax and Run-time Construction - Authors: [Hamish Knight](https://github.com/hamishknight), [Michael Ilseman](https://github.com/milseman) @@ -16,11 +16,33 @@ The overall story is laid out in [Regex Type and Overview](https://github.com/ap Swift aims to be a pragmatic programming language, striking a balance between familiarity, interoperability, and advancing the art. Swift's `String` presents a uniquely Unicode-forward model of string, but currently suffers from limited processing facilities. - +`NSRegularExpression` can construct a processing pipeline from a string containing [ICU regular expression syntax][icu-syntax]. However, it is inherently tied to ICU's engine and thus it operates over a fundamentally different model of string than Swift's `String`. It is also limited in features and carries a fair amount of Objective-C baggage, such as the need to translate between `NSRange` and `Range`. + +```swift +let pattern = #"(\w+)\s\s+(\S+)\s\s+((?:(?!\s\s).)*)\s\s+(.*)"# +let nsRegEx = try! NSRegularExpression(pattern: pattern) + +func processEntry(_ line: String) -> Transaction? { + let range = NSRange(line.startIndex.. +We propose run-time construction of `Regex` from a best-in-class treatment of familiar regular expression syntax. A `Regex` is generic over its `Output`, which includes capture information. This may be an existential `AnyRegexOutput`, or a concrete type provided by the user. + +```swift +let pattern = #"(\w+)\s\s+(\S+)\s\s+((?:(?!\s\s).)*)\s\s+(.*)"# +let regex = try! Regex(pattern) +// regex: Regex + +let regex: Regex<(Substring, Substring, Substring, Substring, Substring)> = + try! Regex(pattern) +``` ### Syntax @@ -51,11 +80,87 @@ Regex syntax will be part of Swift's source-compatibility story as well as its b ## Detailed Design - +We propose initializers to declare and compile a regex from syntax. Upon failure, these initializers throw compilation errors, such as for syntax or type errors. API for retrieving error information is future work. + +```swift +extension Regex { + /// Parse and compile `pattern`, resulting in a strongly-typed capture list. + public init(compiling pattern: String, as: Output.Type = Output.self) throws +} +extension Regex where Output == AnyRegexOutput { + /// Parse and compile `pattern`, resulting in an existentially-typed capture list. + public init(compiling pattern: String) throws +} +``` + +We propose `AnyRegexOutput` for capture types not known at compilation time, alongside casting API to convert to a strongly-typed capture list. + +```swift +/// A type-erased regex output +public struct AnyRegexOutput { + /// Creates a type-erased regex output from an existing output. + /// + /// Use this initializer to fit a regex with strongly typed captures into the + /// use site of a dynamic regex, i.e. one that was created from a string. + public init(_ match: Regex.Match) -We propose the following syntax for regex. + /// Returns a typed output by converting the underlying value to the specified + /// type. + /// + /// - Parameter type: The expected output type. + /// - Returns: The output, if the underlying value can be converted to the + /// output type, or nil otherwise. + public func `as`(_ type: Output.Type) -> Output? +} +extension AnyRegexOutput: RandomAccessCollection { + public struct Element { + /// The range over which a value was captured. `nil` for no-capture. + public var range: Range? + + /// The slice of the input over which a value was captured. `nil` for no-capture. + public var substring: Substring? + + /// The captured value. `nil` for no-capture. + public var value: Any? + } + + // Trivial collection conformance requirements + + public var startIndex: Int { get } + + public var endIndex: Int { get } + + public var count: Int { get } + + public func index(after i: Int) -> Int + + public func index(before i: Int) -> Int + + public subscript(position: Int) -> Element +} +``` + +We propose adding an API to `Regex.Match` to cast the output type to a concrete one. A regex match will lazily create a `Substring` on demand, so casting the match itself saves ARC traffic vs extracting and casting the output. + +```swift +extension Regex.Match where Output == AnyRegexOutput { + /// Creates a type-erased regex match from an existing match. + /// + /// Use this initializer to fit a regex match with strongly typed captures into the + /// use site of a dynamic regex match, i.e. one that was created from a string. + public init(_ match: Regex.Match) + + /// Returns a typed match by converting the underlying values to the specified + /// types. + /// + /// - Parameter type: The expected output type. + /// - Returns: A match generic over the output type if the underlying values can be converted to the + /// output type. Returns `nil` otherwise. + public func `as`(_ type: Output.Type) -> Regex.Match? +} +``` + +The rest of this proposal will be a detailed and exhaustive definition of our proposed regex syntax.
Grammar Notation @@ -827,6 +932,12 @@ We are deferring runtime support for callouts from regex literals as future work ## Alternatives Considered +### Failalbe inits + +There are many ways for compilation to fail, from syntactic errors to unsupported features to type mismatches. In the general case, run-time compilation errors are not recoverable by a tool without modifying the user's input. Even then, the thrown errors contain valuable information as to why compilation failed. For example, swiftpm presents any errors directly to the user. + +As proposed, the errors thrown will be the same errors presented to the Swift compiler, tracking fine-grained source locations with specific reasons why compilation failed. Defining a rich error API is future work, as these errors are rapidly evolving and it is too early to lock in the ABI. + ### Skip the syntax diff --git a/Documentation/Evolution/RegexTypeOverview.md b/Documentation/Evolution/RegexTypeOverview.md index 504111181..cf2fb9265 100644 --- a/Documentation/Evolution/RegexTypeOverview.md +++ b/Documentation/Evolution/RegexTypeOverview.md @@ -1,4 +1,3 @@ - # Regex Type and Overview - Authors: [Michael Ilseman](https://github.com/milseman) and the Standard Library Team @@ -135,11 +134,11 @@ Regexes can be created at run time from a string containing familiar regex synta ```swift let pattern = #"(\w+)\s\s+(\S+)\s\s+((?:(?!\s\s).)*)\s\s+(.*)"# -let regex = try! Regex(compiling: pattern) +let regex = try! Regex(pattern) // regex: Regex let regex: Regex<(Substring, Substring, Substring, Substring, Substring)> = - try! Regex(compiling: pattern) + try! Regex(pattern) ``` *Note*: The syntax accepted and further details on run-time compilation, including `AnyRegexOutput` and extended syntaxes, are discussed in [Run-time Regex Construction][pitches]. @@ -225,7 +224,7 @@ func processEntry(_ line: String) -> Transaction? { The result builder allows for inline failable value construction, which participates in the overall string processing algorithm: returning `nil` signals a local failure and the engine backtracks to try an alternative. This not only relieves the use site from post-processing, it enables new kinds of processing algorithms, allows for search-space pruning, and enhances debuggability. -Swift regexes describe an unambiguous algorithm, were choice is ordered and effects can be reliably observed. For example, a `print()` statement inside the `TryCapture`'s transform function will run whenever the overall algorithm naturally dictates an attempt should be made. Optimizations can only elide such calls if they can prove it is behavior-preserving (e.g. "pure"). +Swift regexes describe an unambiguous algorithm, where choice is ordered and effects can be reliably observed. For example, a `print()` statement inside the `TryCapture`'s transform function will run whenever the overall algorithm naturally dictates an attempt should be made. Optimizations can only elide such calls if they can prove it is behavior-preserving (e.g. "pure"). `CustomMatchingRegexComponent`, discussed in [String Processing Algorithms][pitches], allows industrial-strength parsers to be used a regex components. This allows us to drop the overly-permissive pre-parsing step: @@ -278,14 +277,14 @@ func processEntry(_ line: String) -> Transaction? { *Note*: Details on how references work is discussed in [Regex Builders][pitches]. `Regex.Match` supports referring to _all_ captures by position (`match.1`, etc.) whether named or referenced or neither. Due to compiler limitations, result builders do not support forming labeled tuples for named captures. -### Algorithms, algorithms everywhere +### Regex-powered algorithms Regexes can be used right out of the box with a variety of powerful and convenient algorithms, including trimming, splitting, and finding/replacing all matches within a string. These algorithms are discussed in [String Processing Algorithms][pitches]. -### Onward Unicode +### Unicode handling A regex describes an algorithm to be ran over some model of string, and Swift's `String` has a rather unique Unicode-forward model. `Character` is an [extended grapheme cluster](https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) and equality is determined under [canonical equivalence](https://www.unicode.org/reports/tr15/#Canon_Compat_Equivalence). @@ -301,7 +300,7 @@ Regex targets [UTS\#18 Level 2](https://www.unicode.org/reports/tr18/#Extended_U ```swift /// A regex represents a string processing algorithm. /// -/// let regex = try Regex(compiling: "a(.*)b") +/// let regex = try Regex("a(.*)b") /// let match = "cbaxb".firstMatch(of: regex) /// print(match.0) // "axb" /// print(match.1) // "x" @@ -310,12 +309,12 @@ public struct Regex { /// Match a string in its entirety. /// /// Returns `nil` if no match and throws on abort - public func matchWhole(_ s: String) throws -> Regex.Match? + public func wholeMatch(in s: String) throws -> Regex.Match? /// Match part of the string, starting at the beginning. /// /// Returns `nil` if no match and throws on abort - public func matchPrefix(_ s: String) throws -> Regex.Match? + public func prefixMatch(in s: String) throws -> Regex.Match? /// Find the first match in a string /// @@ -325,17 +324,17 @@ public struct Regex { /// Match a substring in its entirety. /// /// Returns `nil` if no match and throws on abort - public func matchWhole(_ s: Substring) throws -> Regex.Match? + public func wholeMatch(in s: Substring) throws -> Regex.Match? /// Match part of the string, starting at the beginning. /// /// Returns `nil` if no match and throws on abort - public func matchPrefix(_ s: Substring) throws -> Regex.Match? + public func prefixMatch(in s: Substring) throws -> Regex.Match? /// Find the first match in a substring /// /// Returns `nil` if no match is found and throws on abort - public func firstMatch(_ s: Substring) throws -> Regex.Match? + public func firstMatch(in s: Substring) throws -> Regex.Match? /// The result of matching a regex against a string. /// @@ -344,19 +343,19 @@ public struct Regex { @dynamicMemberLookup public struct Match { /// The range of the overall match - public let range: Range + public var range: Range { get } /// The produced output from the match operation - public var output: Output + public var output: Output { get } /// Lookup a capture by name or number - public subscript(dynamicMember keyPath: KeyPath) -> T + public subscript(dynamicMember keyPath: KeyPath) -> T { get } /// Lookup a capture by number @_disfavoredOverload public subscript( dynamicMember keyPath: KeyPath<(Output, _doNotUse: ()), Output> - ) -> Output + ) -> Output { get } // Note: this allows `.0` when `Match` is not a tuple. } @@ -482,6 +481,13 @@ We're also looking for more community discussion on what the default type system The actual `Match` struct just stores ranges: the `Substrings` are lazily created on demand. This avoids unnecessary ARC traffic and memory usage. + +### `Regex` instead of `Regex` + +The generic parameter `Output` is proposed to contain both the whole match (the `.0` element if `Output` is a tuple) and captures. One alternative we have considered is separating `Output` into the entire match and the captures, i.e. `Regex`, and using `Void` for for `Captures` when there are no captures. + +The biggest issue with this alternative design is that the numbering of `Captures` elements misaligns with the numbering of captures in textual regexes, where backreference `\0` refers to the entire match and captures start at `\1`. This design would sacrifice familarity and have the pitfall of introducing off-by-one errors. + ### Future work: static optimization and compilation Swift's support for static compilation is still developing, and future work here is leveraging that to compile regex when profitable. Many regex describe simple [DFAs](https://en.wikipedia.org/wiki/Deterministic_finite_automaton) and can be statically compiled into very efficient programs. Full static compilation needs to be balanced with code size concerns, as a matching-specific bytecode is typically far smaller than a corresponding program (especially since the bytecode interpreter is shared). diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index 9454396ce..b976c562e 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -187,7 +187,7 @@ public protocol CustomMatchingRegexComponent : RegexComponent { _ input: String, startingAt index: String.Index, in bounds: Range - ) -> (upperBound: String.Index, match: Match)? + ) throws -> (upperBound: String.Index, match: Match)? } ``` diff --git a/Package.swift b/Package.swift index e95d98b67..e4a0fb945 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,13 @@ import PackageDescription +let availabilityDefinition = PackageDescription.SwiftSetting.unsafeFlags([ + "-Xfrontend", + "-define-availability", + "-Xfrontend", + #"SwiftStdlib 5.7:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999"#, +]) + let package = Package( name: "swift-experimental-string-processing", products: [ @@ -22,6 +29,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. @@ -30,12 +38,14 @@ let package = Package( name: "_RegexParser", dependencies: [], swiftSettings: [ - .unsafeFlags(["-enable-library-evolution"]) + .unsafeFlags(["-enable-library-evolution"]), + availabilityDefinition ]), .testTarget( name: "MatchingEngineTests", dependencies: [ - "_RegexParser", "_StringProcessing"]), + "_RegexParser", "_StringProcessing" + ]), .target( name: "_CUnicode", dependencies: []), @@ -44,51 +54,63 @@ let package = Package( dependencies: ["_RegexParser", "_CUnicode"], swiftSettings: [ .unsafeFlags(["-enable-library-evolution"]), + availabilityDefinition ]), .target( name: "RegexBuilder", dependencies: ["_StringProcessing", "_RegexParser"], swiftSettings: [ .unsafeFlags(["-enable-library-evolution"]), - .unsafeFlags(["-Xfrontend", "-enable-experimental-pairwise-build-block"]) + .unsafeFlags(["-Xfrontend", "-enable-experimental-pairwise-build-block"]), + availabilityDefinition ]), .testTarget( name: "RegexTests", - dependencies: ["_StringProcessing"]), + dependencies: ["_StringProcessing"], + swiftSettings: [ + .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) + ]), .testTarget( name: "RegexBuilderTests", dependencies: ["_StringProcessing", "RegexBuilder"], swiftSettings: [ - .unsafeFlags(["-Xfrontend", "-enable-experimental-pairwise-build-block"]) + .unsafeFlags(["-Xfrontend", "-enable-experimental-pairwise-build-block"]), + .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) ]), .target( name: "Prototypes", - dependencies: ["_RegexParser", "_StringProcessing"]), + dependencies: ["_RegexParser", "_StringProcessing"], + swiftSettings: [ + .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) + ]), // MARK: Scripts .executableTarget( name: "VariadicsGenerator", dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser") + .product(name: "ArgumentParser", package: "swift-argument-parser") ]), .executableTarget( name: "PatternConverter", dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser"), - "_RegexParser", - "_StringProcessing" + .product(name: "ArgumentParser", package: "swift-argument-parser"), + "_RegexParser", + "_StringProcessing" ]), // MARK: Exercises .target( - name: "Exercises", - dependencies: ["_RegexParser", "Prototypes", "_StringProcessing", "RegexBuilder"], - swiftSettings: [ - .unsafeFlags(["-Xfrontend", "-enable-experimental-pairwise-build-block"]) - ]), + name: "Exercises", + dependencies: ["_RegexParser", "Prototypes", "_StringProcessing", "RegexBuilder"], + swiftSettings: [ + .unsafeFlags(["-Xfrontend", "-enable-experimental-pairwise-build-block"]), + .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) + ]), .testTarget( - name: "ExercisesTests", - dependencies: ["Exercises"]), + name: "ExercisesTests", + dependencies: ["Exercises"], + swiftSettings: [ + .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) + ]) ] ) - diff --git a/Sources/Exercises/Participants/RegexParticipant.swift b/Sources/Exercises/Participants/RegexParticipant.swift index a40de3953..627f9583b 100644 --- a/Sources/Exercises/Participants/RegexParticipant.swift +++ b/Sources/Exercises/Participants/RegexParticipant.swift @@ -62,17 +62,17 @@ private func extractFromCaptures( private func graphemeBreakPropertyData( forLine line: String, using regex: RP -) -> GraphemeBreakEntry? where RP.Output == (Substring, Substring, Substring?, Substring) { - line.matchWhole(regex).map(\.output).flatMap(extractFromCaptures) +) -> GraphemeBreakEntry? where RP.RegexOutput == (Substring, Substring, Substring?, Substring) { + line.wholeMatch(of: regex).map(\.output).flatMap(extractFromCaptures) } private func graphemeBreakPropertyDataLiteral( forLine line: String ) -> GraphemeBreakEntry? { - return graphemeBreakPropertyData( - forLine: line, - using: r(#"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+).*"#, - matching: (Substring, Substring, Substring?, Substring).self)) + let regex = try! Regex( + #"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+).*"#, + as: (Substring, Substring, Substring?, Substring).self) + return graphemeBreakPropertyData(forLine: line, using: regex) } // MARK: - Builder DSL @@ -80,7 +80,7 @@ private func graphemeBreakPropertyDataLiteral( private func graphemeBreakPropertyData( forLine line: String ) -> GraphemeBreakEntry? { - line.matchWhole { + line.wholeMatch { TryCapture(OneOrMore(.hexDigit)) { Unicode.Scalar(hex: $0) } Optionally { ".." diff --git a/Sources/PatternConverter/PatternConverter.swift b/Sources/PatternConverter/PatternConverter.swift index ff47e4be2..f66204884 100644 --- a/Sources/PatternConverter/PatternConverter.swift +++ b/Sources/PatternConverter/PatternConverter.swift @@ -13,7 +13,7 @@ import ArgumentParser import _RegexParser -import _StringProcessing +@_spi(PatternConverter) import _StringProcessing @main struct PatternConverter: ParsableCommand { diff --git a/Sources/RegexBuilder/Anchor.swift b/Sources/RegexBuilder/Anchor.swift index ba910bd30..55b554aea 100644 --- a/Sources/RegexBuilder/Anchor.swift +++ b/Sources/RegexBuilder/Anchor.swift @@ -12,6 +12,7 @@ import _RegexParser @_spi(RegexBuilder) import _StringProcessing +@available(SwiftStdlib 5.7, *) public struct Anchor { internal enum Kind { case startOfSubject @@ -28,6 +29,7 @@ public struct Anchor { var isInverted: Bool = false } +@available(SwiftStdlib 5.7, *) extension Anchor: RegexComponent { var astAssertion: AST.Atom.AssertionKind { if !isInverted { @@ -62,6 +64,7 @@ extension Anchor: RegexComponent { // MARK: - Public API +@available(SwiftStdlib 5.7, *) extension Anchor { public static var startOfSubject: Anchor { Anchor(kind: .startOfSubject) @@ -107,6 +110,7 @@ extension Anchor { } } +@available(SwiftStdlib 5.7, *) public struct Lookahead: _BuiltinRegexComponent { public var regex: Regex @@ -117,7 +121,7 @@ public struct Lookahead: _BuiltinRegexComponent { public init( _ component: R, negative: Bool = false - ) where R.Output == Output { + ) where R.RegexOutput == Output { self.init(node: .nonCapturingGroup( negative ? .negativeLookahead : .lookahead, component.regex.root)) } @@ -125,7 +129,7 @@ public struct Lookahead: _BuiltinRegexComponent { public init( negative: Bool = false, @RegexComponentBuilder _ component: () -> R - ) where R.Output == Output { + ) where R.RegexOutput == Output { self.init(node: .nonCapturingGroup( negative ? .negativeLookahead : .lookahead, component().regex.root)) } diff --git a/Sources/RegexBuilder/Builder.swift b/Sources/RegexBuilder/Builder.swift index 8921c8f25..be9a48e36 100644 --- a/Sources/RegexBuilder/Builder.swift +++ b/Sources/RegexBuilder/Builder.swift @@ -11,6 +11,7 @@ @_spi(RegexBuilder) import _StringProcessing +@available(SwiftStdlib 5.7, *) @resultBuilder public enum RegexComponentBuilder { public static func buildBlock() -> Regex { diff --git a/Sources/RegexBuilder/CharacterClass.swift b/Sources/RegexBuilder/CharacterClass.swift new file mode 100644 index 000000000..d163c336b --- /dev/null +++ b/Sources/RegexBuilder/CharacterClass.swift @@ -0,0 +1,225 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import _RegexParser +@_spi(RegexBuilder) import _StringProcessing + +@available(SwiftStdlib 5.7, *) +public struct CharacterClass { + internal var ccc: DSLTree.CustomCharacterClass + + init(_ ccc: DSLTree.CustomCharacterClass) { + self.ccc = ccc + } + + init(unconverted model: _CharacterClassModel) { + // FIXME: Implement in DSLTree instead of wrapping an AST atom + switch model.makeAST() { + case .atom(let atom): + self.ccc = .init(members: [.atom(.unconverted(atom))]) + default: + fatalError("Unsupported _CharacterClassModel") + } + } + + init(property: AST.Atom.CharacterProperty) { + // FIXME: Implement in DSLTree instead of wrapping an AST atom + let astAtom = AST.Atom(.property(property), .fake) + self.ccc = .init(members: [.atom(.unconverted(astAtom))]) + } +} + +@available(SwiftStdlib 5.7, *) +extension CharacterClass: RegexComponent { + public var regex: Regex { + return Regex(node: DSLTree.Node.customCharacterClass(ccc)) + } +} + +@available(SwiftStdlib 5.7, *) +extension CharacterClass { + public var inverted: CharacterClass { + CharacterClass(ccc.inverted) + } +} + +@available(SwiftStdlib 5.7, *) +extension RegexComponent where Self == CharacterClass { + public static var any: CharacterClass { + .init(DSLTree.CustomCharacterClass(members: [.atom(.any)])) + } + + public static var anyGrapheme: CharacterClass { + .init(unconverted: .anyGrapheme) + } + + public static var whitespace: CharacterClass { + .init(unconverted: .whitespace) + } + + public static var digit: CharacterClass { + .init(unconverted: .digit) + } + + public static var hexDigit: CharacterClass { + .init(DSLTree.CustomCharacterClass(members: [ + .range(.char("A"), .char("F")), + .range(.char("a"), .char("f")), + .range(.char("0"), .char("9")), + ])) + } + + public static var horizontalWhitespace: CharacterClass { + .init(unconverted: .horizontalWhitespace) + } + + public static var newlineSequence: CharacterClass { + .init(unconverted: .newlineSequence) + } + + public static var verticalWhitespace: CharacterClass { + .init(unconverted: .verticalWhitespace) + } + + public static var word: CharacterClass { + .init(unconverted: .word) + } +} + +@available(SwiftStdlib 5.7, *) +extension RegexComponent where Self == CharacterClass { + /// Returns a character class that matches any character in the given string + /// or sequence. + public static func anyOf(_ s: S) -> CharacterClass + where S.Element == Character + { + CharacterClass(DSLTree.CustomCharacterClass( + members: s.map { .atom(.char($0)) })) + } + + /// Returns a character class that matches any unicode scalar in the given + /// sequence. + public static func anyOf(_ s: S) -> CharacterClass + where S.Element == UnicodeScalar + { + CharacterClass(DSLTree.CustomCharacterClass( + members: s.map { .atom(.scalar($0)) })) + } +} + +// Unicode properties +@available(SwiftStdlib 5.7, *) +extension CharacterClass { + public static func generalCategory(_ category: Unicode.GeneralCategory) -> CharacterClass { + guard let extendedCategory = category.extendedGeneralCategory else { + fatalError("Unexpected general category") + } + return CharacterClass(property: + .init(.generalCategory(extendedCategory), isInverted: false, isPOSIX: false)) + } +} + +/// Range syntax for characters in `CharacterClass`es. +@available(SwiftStdlib 5.7, *) +public func ...(lhs: Character, rhs: Character) -> CharacterClass { + let range: DSLTree.CustomCharacterClass.Member = .range(.char(lhs), .char(rhs)) + let ccc = DSLTree.CustomCharacterClass(members: [range], isInverted: false) + return CharacterClass(ccc) +} + +/// Range syntax for unicode scalars in `CharacterClass`es. +@_disfavoredOverload +@available(SwiftStdlib 5.7, *) +public func ...(lhs: UnicodeScalar, rhs: UnicodeScalar) -> CharacterClass { + let range: DSLTree.CustomCharacterClass.Member = .range(.scalar(lhs), .scalar(rhs)) + let ccc = DSLTree.CustomCharacterClass(members: [range], isInverted: false) + return CharacterClass(ccc) +} + +extension Unicode.GeneralCategory { + var extendedGeneralCategory: Unicode.ExtendedGeneralCategory? { + switch self { + case .uppercaseLetter: return .uppercaseLetter + case .lowercaseLetter: return .lowercaseLetter + case .titlecaseLetter: return .titlecaseLetter + case .modifierLetter: return .modifierLetter + case .otherLetter: return .otherLetter + case .nonspacingMark: return .nonspacingMark + case .spacingMark: return .spacingMark + case .enclosingMark: return .enclosingMark + case .decimalNumber: return .decimalNumber + case .letterNumber: return .letterNumber + case .otherNumber: return .otherNumber + case .connectorPunctuation: return .connectorPunctuation + case .dashPunctuation: return .dashPunctuation + case .openPunctuation: return .openPunctuation + case .closePunctuation: return .closePunctuation + case .initialPunctuation: return .initialPunctuation + case .finalPunctuation: return .finalPunctuation + case .otherPunctuation: return .otherPunctuation + case .mathSymbol: return .mathSymbol + case .currencySymbol: return .currencySymbol + case .modifierSymbol: return .modifierSymbol + case .otherSymbol: return .otherSymbol + case .spaceSeparator: return .spaceSeparator + case .lineSeparator: return .lineSeparator + case .paragraphSeparator: return .paragraphSeparator + case .control: return .control + case .format: return .format + case .surrogate: return .surrogate + case .privateUse: return .privateUse + case .unassigned: return .unassigned + @unknown default: return nil + } + } +} + +// MARK: - Set algebra methods + +@available(SwiftStdlib 5.7, *) +extension RegexComponent where Self == CharacterClass { + public init(_ first: CharacterClass, _ rest: CharacterClass...) { + if rest.isEmpty { + self.init(first.ccc) + } else { + let members: [DSLTree.CustomCharacterClass.Member] = + (CollectionOfOne(first) + rest).map { .custom($0.ccc) } + self.init(.init(members: members)) + } + } +} + +@available(SwiftStdlib 5.7, *) +extension CharacterClass { + public func union(_ other: CharacterClass) -> CharacterClass { + CharacterClass(.init(members: [ + .custom(self.ccc), + .custom(other.ccc)])) + } + + public func intersection(_ other: CharacterClass) -> CharacterClass { + CharacterClass(.init(members: [ + .intersection(self.ccc, other.ccc) + ])) + } + + public func subtracting(_ other: CharacterClass) -> CharacterClass { + CharacterClass(.init(members: [ + .subtraction(self.ccc, other.ccc) + ])) + } + + public func symmetricDifference(_ other: CharacterClass) -> CharacterClass { + CharacterClass(.init(members: [ + .symmetricDifference(self.ccc, other.ccc) + ])) + } +} diff --git a/Sources/RegexBuilder/DSL.swift b/Sources/RegexBuilder/DSL.swift index 80662be41..86ec0bee5 100644 --- a/Sources/RegexBuilder/DSL.swift +++ b/Sources/RegexBuilder/DSL.swift @@ -12,26 +12,67 @@ import _RegexParser @_spi(RegexBuilder) import _StringProcessing +@available(SwiftStdlib 5.7, *) extension Regex { public init( @RegexComponentBuilder _ content: () -> Content - ) where Content.Output == Output { + ) where Content.RegexOutput == Output { self = content().regex } } // A convenience protocol for builtin regex components that are initialized with // a `DSLTree` node. +@available(SwiftStdlib 5.7, *) internal protocol _BuiltinRegexComponent: RegexComponent { - init(_ regex: Regex) + init(_ regex: Regex) } +@available(SwiftStdlib 5.7, *) extension _BuiltinRegexComponent { init(node: DSLTree.Node) { self.init(Regex(node: node)) } } +// MARK: - Primitive regex components + +@available(SwiftStdlib 5.7, *) +extension String: RegexComponent { + public typealias Output = Substring + + public var regex: Regex { + .init(node: .quotedLiteral(self)) + } +} + +@available(SwiftStdlib 5.7, *) +extension Substring: RegexComponent { + public typealias Output = Substring + + public var regex: Regex { + .init(node: .quotedLiteral(String(self))) + } +} + +@available(SwiftStdlib 5.7, *) +extension Character: RegexComponent { + public typealias Output = Substring + + public var regex: Regex { + .init(node: .atom(.char(self))) + } +} + +@available(SwiftStdlib 5.7, *) +extension UnicodeScalar: RegexComponent { + public typealias Output = Substring + + public var regex: Regex { + .init(node: .atom(.scalar(self))) + } +} + // MARK: - Combinators // MARK: Concatenation @@ -54,6 +95,7 @@ extension _BuiltinRegexComponent { // Note: Quantifiers are currently gyb'd. /// Specifies how much to attempt to match when using a quantifier. +@available(SwiftStdlib 5.7, *) public struct QuantificationBehavior { internal enum Kind { case eagerly @@ -75,33 +117,37 @@ public struct QuantificationBehavior { extension DSLTree.Node { /// Generates a DSLTree node for a repeated range of the given DSLTree node. /// Individual public API functions are in the generated Variadics.swift file. + @available(SwiftStdlib 5.7, *) static func repeating( _ range: Range, - _ behavior: QuantificationBehavior, + _ behavior: QuantificationBehavior?, _ node: DSLTree.Node ) -> DSLTree.Node { // TODO: Throw these as errors assert(range.lowerBound >= 0, "Cannot specify a negative lower bound") assert(!range.isEmpty, "Cannot specify an empty range") + + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default switch (range.lowerBound, range.upperBound) { case (0, Int.max): // 0... - return .quantification(.zeroOrMore, behavior.astKind, node) + return .quantification(.zeroOrMore, kind, node) case (1, Int.max): // 1... - return .quantification(.oneOrMore, behavior.astKind, node) + return .quantification(.oneOrMore, kind, node) case _ where range.count == 1: // ..<1 or ...0 or any range with count == 1 // Note: `behavior` is ignored in this case - return .quantification(.exactly(.init(faking: range.lowerBound)), .eager, node) + return .quantification(.exactly(.init(faking: range.lowerBound)), .default, node) case (0, _): // 0..: _BuiltinRegexComponent { public var regex: Regex @@ -132,6 +179,7 @@ public struct OneOrMore: _BuiltinRegexComponent { // Variadics.swift. } +@available(SwiftStdlib 5.7, *) public struct ZeroOrMore: _BuiltinRegexComponent { public var regex: Regex @@ -143,6 +191,7 @@ public struct ZeroOrMore: _BuiltinRegexComponent { // Variadics.swift. } +@available(SwiftStdlib 5.7, *) public struct Optionally: _BuiltinRegexComponent { public var regex: Regex @@ -154,6 +203,7 @@ public struct Optionally: _BuiltinRegexComponent { // Variadics.swift. } +@available(SwiftStdlib 5.7, *) public struct Repeat: _BuiltinRegexComponent { public var regex: Regex @@ -179,12 +229,13 @@ public struct Repeat: _BuiltinRegexComponent { // ) -> R where R.Match == (W, C...) // } +@available(SwiftStdlib 5.7, *) @resultBuilder public struct AlternationBuilder { @_disfavoredOverload public static func buildPartialBlock( first component: R - ) -> ChoiceOf { + ) -> ChoiceOf { .init(component.regex) } @@ -201,6 +252,7 @@ public struct AlternationBuilder { } } +@available(SwiftStdlib 5.7, *) public struct ChoiceOf: _BuiltinRegexComponent { public var regex: Regex @@ -215,6 +267,7 @@ public struct ChoiceOf: _BuiltinRegexComponent { // MARK: - Capture +@available(SwiftStdlib 5.7, *) public struct Capture: _BuiltinRegexComponent { public var regex: Regex @@ -225,6 +278,7 @@ public struct Capture: _BuiltinRegexComponent { // Note: Public initializers are currently gyb'd. See Variadics.swift. } +@available(SwiftStdlib 5.7, *) public struct TryCapture: _BuiltinRegexComponent { public var regex: Regex @@ -239,6 +293,7 @@ public struct TryCapture: _BuiltinRegexComponent { /// An atomic group, i.e. opens a local backtracking scope which, upon successful exit, /// discards any remaining backtracking points from within the scope +@available(SwiftStdlib 5.7, *) public struct Local: _BuiltinRegexComponent { public var regex: Regex @@ -249,6 +304,7 @@ public struct Local: _BuiltinRegexComponent { // MARK: - Backreference +@available(SwiftStdlib 5.7, *) public struct Reference: RegexComponent { let id = ReferenceID() @@ -259,6 +315,7 @@ public struct Reference: RegexComponent { } } +@available(SwiftStdlib 5.7, *) extension Regex.Match { public subscript(_ reference: Reference) -> Capture { self[reference.id] diff --git a/Sources/RegexBuilder/Match.swift b/Sources/RegexBuilder/Match.swift index ac07ec0b8..78a466a18 100644 --- a/Sources/RegexBuilder/Match.swift +++ b/Sources/RegexBuilder/Match.swift @@ -11,30 +11,35 @@ import _StringProcessing +@available(SwiftStdlib 5.7, *) extension String { - public func matchWhole( - @RegexComponentBuilder _ content: () -> R - ) -> Regex.Match? { - matchWhole(content()) + @available(SwiftStdlib 5.7, *) + public func wholeMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + wholeMatch(of: content()) } - public func matchPrefix( - @RegexComponentBuilder _ content: () -> R - ) -> Regex.Match? { - matchPrefix(content()) + @available(SwiftStdlib 5.7, *) + public func prefixMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + prefixMatch(of: content()) } } extension Substring { - public func matchWhole( - @RegexComponentBuilder _ content: () -> R - ) -> Regex.Match? { - matchWhole(content()) + @available(SwiftStdlib 5.7, *) + public func wholeMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + wholeMatch(of: content()) } - public func matchPrefix( - @RegexComponentBuilder _ content: () -> R - ) -> Regex.Match? { - matchPrefix(content()) + @available(SwiftStdlib 5.7, *) + public func prefixMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + prefixMatch(of: content()) } } diff --git a/Sources/RegexBuilder/Variadics.swift b/Sources/RegexBuilder/Variadics.swift index 989e5d463..0f8d71a3f 100644 --- a/Sources/RegexBuilder/Variadics.swift +++ b/Sources/RegexBuilder/Variadics.swift @@ -14,2281 +14,2857 @@ import _RegexParser @_spi(RegexBuilder) import _StringProcessing +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0)> where R0.Output == W0, R1.Output == (W1, C0) { + ) -> Regex<(Substring, C0)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1)> where R0.Output == W0, R1.Output == (W1, C0, C1) { + ) -> Regex<(Substring, C0, C1)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2) { + ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3) { + ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == W0, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1)> where R0.Output == (W0, C0), R1.Output == (W1, C1) { + ) -> Regex<(Substring, C0, C1)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2) { + ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3) { + ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2) { + ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3) { + ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3) { + ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6), R1.Output == (W1, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6), R1.Output == (W1, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6), R1.Output == (W1, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.Output == (W1, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.Output == (W1, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8), R1.Output == (W1, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8), R1.RegexOutput == (W1, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex where R0.Output == W0 { + ) -> Regex where R0.RegexOutput == W0 { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0)> where R0.Output == (W0, C0) { + ) -> Regex<(Substring, C0)> where R0.RegexOutput == (W0, C0) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1)> where R0.Output == (W0, C0, C1) { + ) -> Regex<(Substring, C0, C1)> where R0.RegexOutput == (W0, C0, C1) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.Output == (W0, C0, C1, C2) { + ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == (W0, C0, C1, C2) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.Output == (W0, C0, C1, C2, C3) { + ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0, C1, C2, C3) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.Output == (W0, C0, C1, C2, C3, C4) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == Substring { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == Substring { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == Substring { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == Substring { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component ) -> Regex { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == Substring { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == Substring { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == Substring { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == Substring { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == Substring { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == Substring { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == Substring { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == Substring { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, count: Int - ) where Output == Substring { + ) where RegexOutput == Substring { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == Substring { + ) where RegexOutput == Substring { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == Substring, R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == Substring, R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == Substring, R.Bound == Int { + ) where RegexOutput == Substring, R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?), Component.Output == (W, C0) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?), Component.Output == (W, C0) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?)> where Component.Output == (W, C0) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?)> where Component.RegexOutput == (W, C0) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?), Component.Output == (W, C0) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?), Component.Output == (W, C0) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0), Component.Output == (W, C0) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0), Component.Output == (W, C0) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?), Component.Output == (W, C0) { + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?), Component.Output == (W, C0) { + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?), Component.Output == (W, C0), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?), Component.Output == (W, C0), R.Bound == Int { + ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?)> where Component.Output == (W, C0, C1) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?)> where Component.RegexOutput == (W, C0, C1) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1), Component.Output == (W, C0, C1) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1), Component.Output == (W, C0, C1) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?), Component.Output == (W, C0, C1), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?)> where Component.Output == (W, C0, C1, C2) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?)> where Component.RegexOutput == (W, C0, C1, C2) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2), Component.Output == (W, C0, C1, C2) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2), Component.Output == (W, C0, C1, C2) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?), Component.Output == (W, C0, C1, C2), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?)> where Component.Output == (W, C0, C1, C2, C3) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?)> where Component.RegexOutput == (W, C0, C1, C2, C3) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3), Component.Output == (W, C0, C1, C2, C3) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3), Component.Output == (W, C0, C1, C2, C3) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?), Component.Output == (W, C0, C1, C2, C3), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?)> where Component.Output == (W, C0, C1, C2, C3, C4) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3, C4), Component.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4), Component.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?), Component.Output == (W, C0, C1, C2, C3, C4), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?)> where Component.Output == (W, C0, C1, C2, C3, C4, C5) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3, C4, C5), Component.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5), Component.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.Output == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Optionally { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .quantification(.zeroOrOne, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { + @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - .init(node: .quantification(.zeroOrOne, .eager, component.regex.root)) + ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension ZeroOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .quantification(.zeroOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component.regex.root)) + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension OneOrMore { + @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .quantification(.oneOrMore, behavior.astKind, component().regex.root)) + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Repeat { + @available(SwiftStdlib 5.7, *) public init( _ component: Component, count: Int - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { + _ behavior: QuantificationBehavior? = nil + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { + ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component - ) where Output == Substring { + ) where RegexOutput == Substring { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == Substring { + ) where RegexOutput == Substring { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0), Component.Output == (W, C0) { + ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0), Component.Output == (W, C0) { + ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1), Component.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1), Component.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2), Component.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2), Component.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3), Component.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3), Component.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3, C4), Component.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4), Component.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5), Component.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5), Component.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( _ component: Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension Local { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> Component - ) where Output == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 ) -> ChoiceOf where R0: RegexComponent, R1: RegexComponent { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0) { + ) -> ChoiceOf<(Substring, C0?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1) { + ) -> ChoiceOf<(Substring, C0?, C1?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3, C4) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3, C4) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3, C4, C5) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R1.Output == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0) { + ) -> ChoiceOf<(Substring, C0)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1) { + ) -> ChoiceOf<(Substring, C0, C1?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0), R1.Output == (W1, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1) { + ) -> ChoiceOf<(Substring, C0, C1)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2) { + ) -> ChoiceOf<(Substring, C0, C1, C2?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1), R1.Output == (W1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2) { + ) -> ChoiceOf<(Substring, C0, C1, C2)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2), R1.Output == (W1, C3, C4, C5, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3), R1.Output == (W1, C4, C5, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4?, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4), R1.Output == (W1, C5, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5?, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5), R1.Output == (W1, C6, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6?, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6), R1.Output == (W1, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6), R1.Output == (W1, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7?, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6), R1.Output == (W1, C7, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7?, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.Output == (W1, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.Output == (W1, C8, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8?, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { + @available(SwiftStdlib 5.7, *) public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.Output == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8), R1.Output == (W1, C9) { + ) -> ChoiceOf<(Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9?)> where R0: RegexComponent, R1: RegexComponent, R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8), R1.RegexOutput == (W1, C9) { .init(node: accumulated.regex.root.appendingAlternationCase(next.regex.root)) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?)> where R: RegexComponent, R.Output == (W, C0) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?)> where R: RegexComponent, R.RegexOutput == (W, C0) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?)> where R: RegexComponent, R.Output == (W, C0, C1) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?)> where R: RegexComponent, R.Output == (W, C0, C1, C2) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3, C4) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3, C4) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3, C4, C5) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: .orderedChoice([regex.regex.root])) } } +@available(SwiftStdlib 5.7, *) extension AlternationBuilder { - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R: RegexComponent, R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + @available(SwiftStdlib 5.7, *) + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: .orderedChoice([regex.regex.root])) } } // MARK: - Non-builder capture arity 0 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R - ) where Output == (Substring, W), R.Output == W { + ) where RegexOutput == (Substring, W), R.RegexOutput == W { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, as reference: Reference - ) where Output == (Substring, W), R.Output == W { + ) where RegexOutput == (Substring, W), R.RegexOutput == W { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @_disfavoredOverload - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - @_disfavoredOverload - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2296,12 +2872,13 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture( reference: reference.id, .transform( @@ -2310,30 +2887,35 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture), R.Output == W { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture), R.Output == W { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -2341,58 +2923,33 @@ extension TryCapture { // MARK: - Builder capture arity 0 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W), R.Output == W { + ) where RegexOutput == (Substring, W), R.RegexOutput == W { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W), R.Output == W { + ) where RegexOutput == (Substring, W), R.RegexOutput == W { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @_disfavoredOverload - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - @_disfavoredOverload - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2400,12 +2957,13 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture), R.Output == W { + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture( reference: reference.id, .transform( @@ -2414,30 +2972,35 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture), R.Output == W { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture), R.Output == W { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture), R.RegexOutput == W { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -2445,50 +3008,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 1 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2496,11 +3036,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture( reference: reference.id, .transform( @@ -2509,28 +3050,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -2538,53 +3084,30 @@ extension TryCapture { // MARK: - Builder capture arity 1 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2592,11 +3115,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture( reference: reference.id, .transform( @@ -2605,28 +3129,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0), R.Output == (W, C0) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -2634,50 +3163,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 2 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2685,11 +3191,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture( reference: reference.id, .transform( @@ -2698,28 +3205,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -2727,53 +3239,30 @@ extension TryCapture { // MARK: - Builder capture arity 2 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2781,11 +3270,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture( reference: reference.id, .transform( @@ -2794,28 +3284,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1), R.Output == (W, C0, C1) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -2823,50 +3318,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 3 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2874,11 +3346,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( @@ -2887,28 +3360,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -2916,53 +3394,30 @@ extension TryCapture { // MARK: - Builder capture arity 3 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -2970,11 +3425,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( @@ -2983,28 +3439,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2), R.Output == (W, C0, C1, C2) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -3012,50 +3473,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 4 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3063,11 +3501,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( @@ -3076,28 +3515,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -3105,53 +3549,30 @@ extension TryCapture { // MARK: - Builder capture arity 4 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3159,11 +3580,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( @@ -3172,28 +3594,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3), R.Output == (W, C0, C1, C2, C3) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -3201,50 +3628,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 5 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3252,11 +3656,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( @@ -3265,28 +3670,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -3294,53 +3704,30 @@ extension TryCapture { // MARK: - Builder capture arity 5 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3348,11 +3735,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( @@ -3361,28 +3749,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4), R.Output == (W, C0, C1, C2, C3, C4) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -3390,50 +3783,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 6 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3441,11 +3811,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( @@ -3454,28 +3825,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -3483,53 +3859,30 @@ extension TryCapture { // MARK: - Builder capture arity 6 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3537,11 +3890,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( @@ -3550,28 +3904,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.Output == (W, C0, C1, C2, C3, C4, C5) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -3579,50 +3938,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 7 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3630,11 +3966,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( @@ -3643,28 +3980,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -3672,53 +4014,30 @@ extension TryCapture { // MARK: - Builder capture arity 7 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3726,11 +4045,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( @@ -3739,28 +4059,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.Output == (W, C0, C1, C2, C3, C4, C5, C6) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -3768,50 +4093,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 8 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3819,11 +4121,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( @@ -3832,28 +4135,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -3861,53 +4169,30 @@ extension TryCapture { // MARK: - Builder capture arity 8 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3915,11 +4200,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( @@ -3928,28 +4214,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -3957,50 +4248,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 9 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4008,11 +4276,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( @@ -4021,28 +4290,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -4050,53 +4324,30 @@ extension TryCapture { // MARK: - Builder capture arity 9 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4104,11 +4355,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( @@ -4117,28 +4369,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } @@ -4146,50 +4403,27 @@ extension TryCapture { // MARK: - Non-builder capture arity 10 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( _ component: R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(component.regex.root)) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - public init( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - public init( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4197,11 +4431,12 @@ extension TryCapture { component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( @@ -4210,28 +4445,33 @@ extension TryCapture { }, component.regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( _ component: R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + @available(SwiftStdlib 5.7, *) public init( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -4239,53 +4479,30 @@ extension TryCapture { // MARK: - Builder capture arity 10 +@available(SwiftStdlib 5.7, *) extension Capture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(component().regex.root)) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where Output == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - public init( - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - public init( - as reference: Reference, - @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } -} - -extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4293,11 +4510,12 @@ extension TryCapture { component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( @@ -4306,28 +4524,33 @@ extension TryCapture { }, component().regex.root))) } +} +@available(SwiftStdlib 5.7, *) +extension TryCapture { + @available(SwiftStdlib 5.7, *) public init( @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + @available(SwiftStdlib 5.7, *) public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? - ) where Output == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Output == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { + transform: @escaping (Substring) throws -> NewCapture? + ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } diff --git a/Sources/VariadicsGenerator/VariadicsGenerator.swift b/Sources/VariadicsGenerator/VariadicsGenerator.swift index dbeff818c..d1cb41810 100644 --- a/Sources/VariadicsGenerator/VariadicsGenerator.swift +++ b/Sources/VariadicsGenerator/VariadicsGenerator.swift @@ -90,12 +90,13 @@ var standardError = StandardErrorStream() typealias Counter = Int64 let regexComponentProtocolName = "RegexComponent" -let outputAssociatedTypeName = "Output" +let outputAssociatedTypeName = "RegexOutput" let patternProtocolRequirementName = "regex" let regexTypeName = "Regex" let baseMatchTypeName = "Substring" let concatBuilderName = "RegexComponentBuilder" let altBuilderName = "AlternationBuilder" +let defaultAvailableAttr = "@available(SwiftStdlib 5.7, *)" @main struct VariadicsGenerator: ParsableCommand { @@ -240,8 +241,10 @@ struct VariadicsGenerator: ParsableCommand { }() // Emit concatenation builder. - output("extension \(concatBuilderName) {\n") output(""" + \(defaultAvailableAttr) + extension \(concatBuilderName) { + \(defaultAvailableAttr) public static func buildPartialBlock<\(genericParams)>( accumulated: R0, next: R1 ) -> \(regexTypeName)<\(matchType)> \(whereClause) { @@ -255,9 +258,11 @@ struct VariadicsGenerator: ParsableCommand { func emitConcatenationWithEmpty(leftArity: Int) { // T + () = T output(""" - extension \(concatBuilderName) { - public static func buildPartialBlock= 0) let params = QuantifierParameters(kind: kind, arity: arity) output(""" + \(defaultAvailableAttr) extension \(kind.rawValue) { + \(defaultAvailableAttr) \(params.disfavored)\ public init<\(params.genericParams)>( _ component: Component, - _ behavior: QuantificationBehavior = .eagerly + _ behavior: QuantificationBehavior? = nil ) \(params.whereClauseForInit) { - self.init(node: .quantification(.\(kind.astQuantifierAmount), behavior.astKind, component.regex.root)) + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.\(kind.astQuantifierAmount), kind, component.regex.root)) } } + \(defaultAvailableAttr) extension \(kind.rawValue) { + \(defaultAvailableAttr) \(params.disfavored)\ public init<\(params.genericParams)>( - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @\(concatBuilderName) _ component: () -> Component ) \(params.whereClauseForInit) { - self.init(node: .quantification(.\(kind.astQuantifierAmount), behavior.astKind, component().regex.root)) + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + self.init(node: .quantification(.\(kind.astQuantifierAmount), kind, component().regex.root)) } } \(kind == .zeroOrOne ? """ + \(defaultAvailableAttr) extension \(concatBuilderName) { + \(defaultAvailableAttr) public static func buildLimitedAvailability<\(params.genericParams)>( _ component: Component ) -> \(regexTypeName)<\(params.matchType)> \(params.whereClause) { - .init(node: .quantification(.\(kind.astQuantifierAmount), .eager, component.regex.root)) + .init(node: .quantification(.\(kind.astQuantifierAmount), .default, component.regex.root)) } } """ : "") @@ -433,7 +446,9 @@ struct VariadicsGenerator: ParsableCommand { (arity == 0 ? "" : ", Component.\(outputAssociatedTypeName) == (W, \(capturesJoined))") output(""" + \(defaultAvailableAttr) extension \(groupName) { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams)>( _ component: Component @@ -442,7 +457,9 @@ struct VariadicsGenerator: ParsableCommand { } } + \(defaultAvailableAttr) extension \(groupName) { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams)>( @\(concatBuilderName) _ component: () -> Component @@ -463,7 +480,9 @@ struct VariadicsGenerator: ParsableCommand { // We would need to prohibit `repeat(count: 0)`; can only happen at runtime output(""" + \(defaultAvailableAttr) extension Repeat { + \(defaultAvailableAttr) \(params.disfavored)\ public init<\(params.genericParams)>( _ component: Component, @@ -471,9 +490,10 @@ struct VariadicsGenerator: ParsableCommand { ) \(params.whereClauseForInit) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component.regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component.regex.root)) } + \(defaultAvailableAttr) \(params.disfavored)\ public init<\(params.genericParams)>( count: Int, @@ -481,22 +501,24 @@ struct VariadicsGenerator: ParsableCommand { ) \(params.whereClauseForInit) { assert(count > 0, "Must specify a positive count") // TODO: Emit a warning about `repeatMatch(count: 0)` or `repeatMatch(count: 1)` - self.init(node: .quantification(.exactly(.init(faking: count)), .eager, component().regex.root)) + self.init(node: .quantification(.exactly(.init(faking: count)), .default, component().regex.root)) } + \(defaultAvailableAttr) \(params.disfavored)\ public init<\(params.genericParams), R: RangeExpression>( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior = .eagerly + _ behavior: QuantificationBehavior? = nil ) \(params.repeatingWhereClause) { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior = .eagerly, + _ behavior: QuantificationBehavior? = nil, @\(concatBuilderName) _ component: () -> Component ) \(params.repeatingWhereClause) { self.init(node: .repeating(expression.relative(to: 0..( accumulated: R0, next: R1 ) -> ChoiceOf<\(matchType)> \(whereClause) { @@ -571,7 +595,9 @@ struct VariadicsGenerator: ParsableCommand { """ let resultCaptures = (0..(first regex: R) -> ChoiceOf<(W, \(resultCaptures))> \(whereClause) { .init(node: .orderedChoice([regex.regex.root])) } @@ -600,7 +626,9 @@ struct VariadicsGenerator: ParsableCommand { output(""" // MARK: - Non-builder capture arity \(arity) + \(defaultAvailableAttr) extension Capture { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams)>( _ component: R @@ -608,6 +636,7 @@ struct VariadicsGenerator: ParsableCommand { self.init(node: .capture(component.regex.root)) } + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams)>( _ component: R, as reference: Reference @@ -615,35 +644,7 @@ struct VariadicsGenerator: ParsableCommand { self.init(node: .capture(reference: reference.id, component.regex.root)) } - \(disfavored)\ - public init<\(genericParams), NewCapture>( - _ component: R, - transform: @escaping (Substring) -> NewCapture - ) \(whereClauseTransformed) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - - \(disfavored)\ - public init<\(genericParams), NewCapture>( - _ component: R, - as reference: Reference, - transform: @escaping (Substring) -> NewCapture - ) \(whereClauseTransformed) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component.regex.root))) - } - } - - extension TryCapture { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, @@ -656,6 +657,7 @@ struct VariadicsGenerator: ParsableCommand { component.regex.root))) } + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, @@ -670,30 +672,35 @@ struct VariadicsGenerator: ParsableCommand { }, component.regex.root))) } + } + \(defaultAvailableAttr) + extension TryCapture { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, - transform: @escaping (Substring) -> NewCapture? + transform: @escaping (Substring) throws -> NewCapture? ) \(whereClauseTransformed) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, as reference: Reference, - transform: @escaping (Substring) -> NewCapture? + transform: @escaping (Substring) throws -> NewCapture? ) \(whereClauseTransformed) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component.regex.root))) } @@ -701,7 +708,9 @@ struct VariadicsGenerator: ParsableCommand { // MARK: - Builder capture arity \(arity) + \(defaultAvailableAttr) extension Capture { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams)>( @\(concatBuilderName) _ component: () -> R @@ -709,6 +718,7 @@ struct VariadicsGenerator: ParsableCommand { self.init(node: .capture(component().regex.root)) } + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams)>( as reference: Reference, @@ -719,35 +729,7 @@ struct VariadicsGenerator: ParsableCommand { component().regex.root)) } - \(disfavored)\ - public init<\(genericParams), NewCapture>( - @\(concatBuilderName) _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) \(whereClauseTransformed) { - self.init(node: .capture(.transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - - \(disfavored)\ - public init<\(genericParams), NewCapture>( - as reference: Reference, - @\(concatBuilderName) _ component: () -> R, - transform: @escaping (Substring) -> NewCapture - ) \(whereClauseTransformed) { - self.init(node: .capture( - reference: reference.id, - .transform( - CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any - }, - component().regex.root))) - } - } - - extension TryCapture { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( @\(concatBuilderName) _ component: () -> R, @@ -760,6 +742,7 @@ struct VariadicsGenerator: ParsableCommand { component().regex.root))) } + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( as reference: Reference, @@ -774,30 +757,35 @@ struct VariadicsGenerator: ParsableCommand { }, component().regex.root))) } + } + \(defaultAvailableAttr) + extension TryCapture { + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( @\(concatBuilderName) _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? + transform: @escaping (Substring) throws -> NewCapture? ) \(whereClauseTransformed) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } + \(defaultAvailableAttr) \(disfavored)\ public init<\(genericParams), NewCapture>( as reference: Reference, @\(concatBuilderName) _ component: () -> R, - transform: @escaping (Substring) -> NewCapture? + transform: @escaping (Substring) throws -> NewCapture? ) \(whereClauseTransformed) { self.init(node: .capture( reference: reference.id, .transform( CaptureTransform(resultType: NewCapture.self) { - transform($0) as Any? + try transform($0) as Any? }, component().regex.root))) } diff --git a/Sources/_RegexParser/Regex/AST/AST.swift b/Sources/_RegexParser/Regex/AST/AST.swift index ba37b6d62..409d5a7ee 100644 --- a/Sources/_RegexParser/Regex/AST/AST.swift +++ b/Sources/_RegexParser/Regex/AST/AST.swift @@ -304,78 +304,3 @@ extension AST { } } } - -// FIXME: Get this out of here -public struct CaptureTransform: Equatable, Hashable, CustomStringConvertible { - public enum Closure { - case nonfailable((Substring) -> Any) - case failable((Substring) -> Any?) - case throwing((Substring) throws -> Any) - } - public let resultType: Any.Type - public let closure: Closure - - public init(resultType: Any.Type, closure: Closure) { - self.resultType = resultType - self.closure = closure - } - - public init( - resultType: Any.Type, - _ closure: @escaping (Substring) -> Any - ) { - self.init(resultType: resultType, closure: .nonfailable(closure)) - } - - public init( - resultType: Any.Type, - _ closure: @escaping (Substring) -> Any? - ) { - self.init(resultType: resultType, closure: .failable(closure)) - } - - public init( - resultType: Any.Type, - _ closure: @escaping (Substring) throws -> Any - ) { - self.init(resultType: resultType, closure: .throwing(closure)) - } - - public func callAsFunction(_ input: Substring) -> Any? { - switch closure { - case .nonfailable(let closure): - let result = closure(input) - assert(type(of: result) == resultType) - return result - case .failable(let closure): - guard let result = closure(input) else { - return nil - } - assert(type(of: result) == resultType) - return result - case .throwing(let closure): - do { - let result = try closure(input) - assert(type(of: result) == resultType) - return result - } catch { - return nil - } - } - } - - public static func == (lhs: CaptureTransform, rhs: CaptureTransform) -> Bool { - unsafeBitCast(lhs.closure, to: (Int, Int).self) == - unsafeBitCast(rhs.closure, to: (Int, Int).self) - } - - public func hash(into hasher: inout Hasher) { - let (fn, ctx) = unsafeBitCast(closure, to: (Int, Int).self) - hasher.combine(fn) - hasher.combine(ctx) - } - - public var description: String { - "" - } -} diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift index dbe7923ec..1d4332ad0 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift @@ -12,7 +12,7 @@ // MARK: `CollectionSearcher` algorithms extension Collection { - public func contains( + func contains( _ searcher: Searcher ) -> Bool where Searcher.Searched == Self { firstRange(of: searcher) != nil @@ -22,6 +22,12 @@ extension Collection { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { + /// Returns a Boolean value indicating whether the collection contains the + /// given sequence. + /// - Parameter other: A sequence to search for within this collection. + /// - Returns: `true` if the collection contains the specified sequence, + /// otherwise `false`. + @available(SwiftStdlib 5.7, *) public func contains(_ other: S) -> Bool where S.Element == Element { @@ -30,16 +36,25 @@ extension Collection where Element: Equatable { } extension BidirectionalCollection where Element: Comparable { - public func contains(_ other: S) -> Bool + func contains(_ other: S) -> Bool where S.Element == Element { - firstRange(of: other) != nil + if #available(SwiftStdlib 5.7, *) { + return firstRange(of: other) != nil + } + fatalError() } } // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { + /// Returns a Boolean value indicating whether the collection contains the + /// given regex. + /// - Parameter regex: A regex to search for within this collection. + /// - Returns: `true` if the regex was found in the collection, otherwise + /// `false`. + @available(SwiftStdlib 5.7, *) public func contains(_ regex: R) -> Bool { contains(RegexConsumer(regex)) } diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift b/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift index 40d5b9950..508c04663 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift @@ -12,7 +12,7 @@ // MARK: `CollectionSearcher` algorithms extension Collection { - public func firstRange( + func firstRange( of searcher: S ) -> Range? where S.Searched == Self { var state = searcher.state(for: self, in: startIndex..( + func lastRange( of searcher: S ) -> Range? where S.BackwardSearched == Self { var state = searcher.backwardState(for: self, in: startIndex..( of sequence: S ) -> Range? where S.Element == Element { @@ -42,6 +48,12 @@ extension Collection where Element: Equatable { } extension BidirectionalCollection where Element: Comparable { + /// Finds and returns the range of the first occurrence of a given sequence + /// within the collection. + /// - Parameter other: The sequence to search for. + /// - Returns: A range in the collection of the first occurrence of `sequence`. + /// Returns `nil` if `sequence` is not found. + @available(SwiftStdlib 5.7, *) public func firstRange( of other: S ) -> Range? where S.Element == Element { @@ -56,11 +68,18 @@ extension BidirectionalCollection where Element: Comparable { // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { + /// Finds and returns the range of the first occurrence of a given regex + /// within the collection. + /// - Parameter regex: The regex to search for. + /// - Returns: A range in the collection of the first occurrence of `regex`. + /// Returns `nil` if `regex` is not found. + @available(SwiftStdlib 5.7, *) public func firstRange(of regex: R) -> Range? { firstRange(of: RegexConsumer(regex)) } - - public func lastRange(of regex: R) -> Range? { + + @available(SwiftStdlib 5.7, *) + func lastRange(of regex: R) -> Range? { lastRange(of: RegexConsumer(regex)) } } diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift index e56e35e72..f1861fcf2 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift @@ -11,7 +11,7 @@ // MARK: `RangesCollection` -public struct RangesCollection { +struct RangesCollection { public typealias Base = Searcher.Searched let base: Base @@ -33,7 +33,7 @@ public struct RangesCollection { } } -public struct RangesIterator: IteratorProtocol { +struct RangesIterator: IteratorProtocol { public typealias Base = Searcher.Searched let base: Base @@ -92,7 +92,7 @@ extension RangesCollection: Collection { } extension RangesCollection.Index: Comparable { - public static func == (lhs: Self, rhs: Self) -> Bool { + static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs.range, rhs.range) { case (nil, nil): return true @@ -103,7 +103,7 @@ extension RangesCollection.Index: Comparable { } } - public static func < (lhs: Self, rhs: Self) -> Bool { + static func < (lhs: Self, rhs: Self) -> Bool { switch (lhs.range, rhs.range) { case (nil, _): return false @@ -117,8 +117,8 @@ extension RangesCollection.Index: Comparable { // MARK: `ReversedRangesCollection` -public struct ReversedRangesCollection { - public typealias Base = Searcher.BackwardSearched +struct ReversedRangesCollection { + typealias Base = Searcher.BackwardSearched let base: Base let searcher: Searcher @@ -157,7 +157,7 @@ extension ReversedRangesCollection: Sequence { // MARK: `CollectionSearcher` algorithms extension Collection { - public func ranges( + func ranges( of searcher: S ) -> RangesCollection where S.Searched == Self { RangesCollection(base: self, searcher: searcher) @@ -165,7 +165,7 @@ extension Collection { } extension BidirectionalCollection { - public func rangesFromBack( + func rangesFromBack( of searcher: S ) -> ReversedRangesCollection where S.BackwardSearched == Self { ReversedRangesCollection(base: self, searcher: searcher) @@ -175,7 +175,8 @@ extension BidirectionalCollection { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { - public func ranges( + // FIXME: Replace `RangesCollection` when SE-0346 is enabled + func ranges( of other: S ) -> RangesCollection> where S.Element == Element { ranges(of: ZSearcher(pattern: Array(other), by: ==)) @@ -194,7 +195,7 @@ extension BidirectionalCollection where Element: Equatable { } extension BidirectionalCollection where Element: Comparable { - public func ranges( + func ranges( of other: S ) -> RangesCollection>> where S.Element == Element @@ -216,13 +217,16 @@ extension BidirectionalCollection where Element: Comparable { // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { - public func ranges( + // FIXME: Replace `RangesCollection` when SE-0346 is enabled + @available(SwiftStdlib 5.7, *) + func ranges( of regex: R ) -> RangesCollection> { ranges(of: RegexConsumer(regex)) } - - public func rangesFromBack( + + @available(SwiftStdlib 5.7, *) + func rangesFromBack( of regex: R ) -> ReversedRangesCollection> { rangesFromBack(of: RegexConsumer(regex)) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift index e2c9d78a4..4a6da6c10 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift @@ -12,7 +12,7 @@ // MARK: `CollectionSearcher` algorithms extension RangeReplaceableCollection { - public func replacing( + func replacing( _ searcher: Searcher, with replacement: Replacement, subrange: Range, @@ -36,7 +36,7 @@ extension RangeReplaceableCollection { return result } - public func replacing( + func replacing( _ searcher: Searcher, with replacement: Replacement, maxReplacements: Int = .max @@ -50,7 +50,7 @@ extension RangeReplaceableCollection { maxReplacements: maxReplacements) } - public mutating func replace< + mutating func replace< Searcher: CollectionSearcher, Replacement: Collection >( _ searcher: Searcher, @@ -67,6 +67,17 @@ extension RangeReplaceableCollection { // MARK: Fixed pattern algorithms extension RangeReplaceableCollection where Element: Equatable { + /// Returns a new collection in which all occurrences of a target sequence + /// are replaced by another collection. + /// - Parameters: + /// - other: The sequence to replace. + /// - replacement: The new elements to add to the collection. + /// - subrange: The range in the collection in which to search for `other`. + /// - maxReplacements: A number specifying how many occurrences of `other` + /// to replace. Default is `Int.max`. + /// - Returns: A new collection in which all occurrences of `other` in + /// `subrange` of the collection are replaced by `replacement`. + @available(SwiftStdlib 5.7, *) public func replacing( _ other: S, with replacement: Replacement, @@ -79,7 +90,17 @@ extension RangeReplaceableCollection where Element: Equatable { subrange: subrange, maxReplacements: maxReplacements) } - + + /// Returns a new collection in which all occurrences of a target sequence + /// are replaced by another collection. + /// - Parameters: + /// - other: The sequence to replace. + /// - replacement: The new elements to add to the collection. + /// - maxReplacements: A number specifying how many occurrences of `other` + /// to replace. Default is `Int.max`. + /// - Returns: A new collection in which all occurrences of `other` in + /// `subrange` of the collection are replaced by `replacement`. + @available(SwiftStdlib 5.7, *) public func replacing( _ other: S, with replacement: Replacement, @@ -91,7 +112,14 @@ extension RangeReplaceableCollection where Element: Equatable { subrange: startIndex..( _ other: S, with replacement: Replacement, @@ -108,7 +136,7 @@ extension RangeReplaceableCollection where Element: Equatable { extension RangeReplaceableCollection where Self: BidirectionalCollection, Element: Comparable { - public func replacing( + func replacing( _ other: S, with replacement: Replacement, subrange: Range, @@ -121,7 +149,7 @@ extension RangeReplaceableCollection maxReplacements: maxReplacements) } - public func replacing( + func replacing( _ other: S, with replacement: Replacement, maxReplacements: Int = .max @@ -133,7 +161,7 @@ extension RangeReplaceableCollection maxReplacements: maxReplacements) } - public mutating func replace( + mutating func replace( _ other: S, with replacement: Replacement, maxReplacements: Int = .max @@ -149,6 +177,17 @@ extension RangeReplaceableCollection // MARK: Regex algorithms extension RangeReplaceableCollection where SubSequence == Substring { + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another collection. + /// - Parameters: + /// - regex: A regex describing the sequence to replace. + /// - replacement: The new elements to add to the collection. + /// - subrange: The range in the collection in which to search for `regex`. + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` in `subrange` are replaced by `replacement`. + @available(SwiftStdlib 5.7, *) public func replacing( _ regex: R, with replacement: Replacement, @@ -161,7 +200,17 @@ extension RangeReplaceableCollection where SubSequence == Substring { subrange: subrange, maxReplacements: maxReplacements) } - + + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another collection. + /// - Parameters: + /// - regex: A regex describing the sequence to replace. + /// - replacement: The new elements to add to the collection. + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + @available(SwiftStdlib 5.7, *) public func replacing( _ regex: R, with replacement: Replacement, @@ -173,7 +222,15 @@ extension RangeReplaceableCollection where SubSequence == Substring { subrange: startIndex..( _ regex: R, with replacement: Replacement, diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 15c946ca2..485bc3b7f 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -11,7 +11,7 @@ // MARK: `SplitCollection` -public struct SplitCollection { +struct SplitCollection { public typealias Base = Searcher.Searched let ranges: RangesCollection @@ -101,7 +101,7 @@ extension SplitCollection: Collection { } extension SplitCollection.Index: Comparable { - public static func == (lhs: Self, rhs: Self) -> Bool { + static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs.isEndIndex, rhs.isEndIndex) { case (false, false): return lhs.start == rhs.start @@ -110,7 +110,7 @@ extension SplitCollection.Index: Comparable { } } - public static func < (lhs: Self, rhs: Self) -> Bool { + static func < (lhs: Self, rhs: Self) -> Bool { switch (lhs.isEndIndex, rhs.isEndIndex) { case (true, _): return false @@ -124,7 +124,7 @@ extension SplitCollection.Index: Comparable { // MARK: `ReversedSplitCollection` -public struct ReversedSplitCollection { +struct ReversedSplitCollection { public typealias Base = Searcher.BackwardSearched let ranges: ReversedRangesCollection @@ -175,7 +175,7 @@ extension ReversedSplitCollection: Sequence { // MARK: `CollectionSearcher` algorithms extension Collection { - public func split( + func split( by separator: Searcher ) -> SplitCollection where Searcher.Searched == Self { // TODO: `maxSplits`, `omittingEmptySubsequences`? @@ -184,7 +184,7 @@ extension Collection { } extension BidirectionalCollection { - public func splitFromBack( + func splitFromBack( by separator: Searcher ) -> ReversedSplitCollection where Searcher.BackwardSearched == Self @@ -197,7 +197,7 @@ extension BidirectionalCollection { extension Collection { // TODO: Non-escaping and throwing - public func split( + func split( whereSeparator predicate: @escaping (Element) -> Bool ) -> SplitCollection> { split(by: PredicateConsumer(predicate: predicate)) @@ -205,7 +205,7 @@ extension Collection { } extension BidirectionalCollection where Element: Equatable { - public func splitFromBack( + func splitFromBack( whereSeparator predicate: @escaping (Element) -> Bool ) -> ReversedSplitCollection> { splitFromBack(by: PredicateConsumer(predicate: predicate)) @@ -215,7 +215,7 @@ extension BidirectionalCollection where Element: Equatable { // MARK: Single element algorithms extension Collection where Element: Equatable { - public func split( + func split( by separator: Element ) -> SplitCollection> { split(whereSeparator: { $0 == separator }) @@ -223,7 +223,7 @@ extension Collection where Element: Equatable { } extension BidirectionalCollection where Element: Equatable { - public func splitFromBack( + func splitFromBack( by separator: Element ) -> ReversedSplitCollection> { splitFromBack(whereSeparator: { $0 == separator }) @@ -233,7 +233,13 @@ extension BidirectionalCollection where Element: Equatable { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { - public func split( + // FIXME: Replace `SplitCollection` when SE-0346 is enabled + /// Returns the longest possible subsequences of the collection, in order, + /// around elements equal to the given separator. + /// - Parameter separator: The element to be split upon. + /// - Returns: A collection of subsequences, split from this collection's + /// elements. + func split( by separator: S ) -> SplitCollection> where S.Element == Element { split(by: ZSearcher(pattern: Array(separator), by: ==)) @@ -252,7 +258,7 @@ extension BidirectionalCollection where Element: Equatable { } extension BidirectionalCollection where Element: Comparable { - public func split( + func split( by separator: S ) -> SplitCollection>> where S.Element == Element @@ -274,14 +280,21 @@ extension BidirectionalCollection where Element: Comparable { // MARK: Regex algorithms +@available(SwiftStdlib 5.7, *) extension BidirectionalCollection where SubSequence == Substring { - public func split( + // FIXME: Replace `SplitCollection` when SE-0346 is enabled + /// Returns the longest possible subsequences of the collection, in order, + /// around elements equal to the given separator. + /// - Parameter separator: A regex describing elements to be split upon. + /// - Returns: A collection of substrings, split from this collection's + /// elements. + func split( by separator: R ) -> SplitCollection> { split(by: RegexConsumer(separator)) } - public func splitFromBack( + func splitFromBack( by separator: R ) -> ReversedSplitCollection> { splitFromBack(by: RegexConsumer(separator)) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift b/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift index 75c6e1133..0dd91f360 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift @@ -12,7 +12,7 @@ // MARK: `CollectionConsumer` algorithms extension Collection { - public func starts(with consumer: C) -> Bool + func starts(with consumer: C) -> Bool where C.Consumed == SubSequence { consumer.consuming(self[...]) != nil @@ -20,7 +20,7 @@ extension Collection { } extension BidirectionalCollection { - public func ends(with consumer: C) -> Bool + func ends(with consumer: C) -> Bool where C.Consumed == SubSequence { consumer.consumingBack(self[...]) != nil @@ -30,7 +30,7 @@ extension BidirectionalCollection { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { - public func starts(with prefix: C) -> Bool + func starts(with prefix: C) -> Bool where C.Element == Element { starts(with: FixedPatternConsumer(pattern: prefix)) @@ -38,7 +38,7 @@ extension Collection where Element: Equatable { } extension BidirectionalCollection where Element: Equatable { - public func ends(with suffix: C) -> Bool + func ends(with suffix: C) -> Bool where C.Element == Element { ends(with: FixedPatternConsumer(pattern: suffix)) @@ -47,12 +47,18 @@ extension BidirectionalCollection where Element: Equatable { // MARK: Regex algorithms +@available(SwiftStdlib 5.7, *) extension BidirectionalCollection where SubSequence == Substring { + /// Returns a Boolean value indicating whether the initial elements of the + /// sequence are the same as the elements in the specified regex. + /// - Parameter regex: A regex to compare to this sequence. + /// - Returns: `true` if the initial elements of the sequence matches the + /// beginning of `regex`; otherwise, `false`. public func starts(with regex: R) -> Bool { starts(with: RegexConsumer(regex)) } - public func ends(with regex: R) -> Bool { + func ends(with regex: R) -> Bool { ends(with: RegexConsumer(regex)) } } diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift index 65a71e1b7..73a5cd554 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift @@ -12,7 +12,7 @@ // MARK: `CollectionConsumer` algorithms extension Collection { - public func trimmingPrefix( + func trimmingPrefix( _ consumer: Consumer ) -> SubSequence where Consumer.Consumed == Self { let start = consumer.consuming(self) ?? startIndex @@ -21,7 +21,7 @@ extension Collection { } extension Collection where SubSequence == Self { - public mutating func trimPrefix( + mutating func trimPrefix( _ consumer: Consumer ) where Consumer.Consumed == Self { _ = consumer.consume(&self) @@ -32,7 +32,7 @@ extension RangeReplaceableCollection { // NOTE: Disfavored because the `Collection with SubSequence == Self` overload // should be preferred whenever both are available @_disfavoredOverload - public mutating func trimPrefix( + mutating func trimPrefix( _ consumer: Consumer ) where Consumer.Consumed == Self { if let start = consumer.consuming(self) { @@ -42,7 +42,7 @@ extension RangeReplaceableCollection { } extension BidirectionalCollection { - public func trimmingSuffix( + func trimmingSuffix( _ consumer: Consumer ) -> SubSequence where Consumer.Consumed == Self @@ -51,7 +51,7 @@ extension BidirectionalCollection { return self[..( + func trimming( _ consumer: Consumer ) -> SubSequence where Consumer.Consumed == Self { // NOTE: Might give different results than trimming the suffix before @@ -64,7 +64,7 @@ extension BidirectionalCollection { } extension BidirectionalCollection where SubSequence == Self { - public mutating func trimSuffix( + mutating func trimSuffix( _ consumer: Consumer ) where Consumer.Consumed == SubSequence { @@ -81,7 +81,7 @@ extension BidirectionalCollection where SubSequence == Self { extension RangeReplaceableCollection where Self: BidirectionalCollection { @_disfavoredOverload - public mutating func trimSuffix( + mutating func trimSuffix( _ consumer: Consumer ) where Consumer.Consumed == Self { @@ -103,7 +103,7 @@ extension RangeReplaceableCollection where Self: BidirectionalCollection { extension Collection { // TODO: Non-escaping and throwing - public func trimmingPrefix( + func trimmingPrefix( while predicate: @escaping (Element) -> Bool ) -> SubSequence { trimmingPrefix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) @@ -111,6 +111,7 @@ extension Collection { } extension Collection where SubSequence == Self { + @available(SwiftStdlib 5.7, *) public mutating func trimPrefix( while predicate: @escaping (Element) -> Bool ) { @@ -121,6 +122,7 @@ extension Collection where SubSequence == Self { extension RangeReplaceableCollection { @_disfavoredOverload + @available(SwiftStdlib 5.7, *) public mutating func trimPrefix( while predicate: @escaping (Element) -> Bool ) { @@ -129,13 +131,13 @@ extension RangeReplaceableCollection { } extension BidirectionalCollection { - public func trimmingSuffix( + func trimmingSuffix( while predicate: @escaping (Element) -> Bool ) -> SubSequence { trimmingSuffix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) } - public func trimming( + func trimming( while predicate: @escaping (Element) -> Bool ) -> SubSequence { trimming(ManyConsumer(base: PredicateConsumer(predicate: predicate))) @@ -143,14 +145,14 @@ extension BidirectionalCollection { } extension BidirectionalCollection where SubSequence == Self { - public mutating func trimSuffix( + mutating func trimSuffix( while predicate: @escaping (Element) -> Bool ) { trimSuffix(ManyConsumer( base: PredicateConsumer(predicate: predicate))) } - public mutating func trim(while predicate: @escaping (Element) -> Bool) { + mutating func trim(while predicate: @escaping (Element) -> Bool) { let consumer = ManyConsumer( base: PredicateConsumer(predicate: predicate)) trimPrefix(consumer) @@ -160,14 +162,14 @@ extension BidirectionalCollection where SubSequence == Self { extension RangeReplaceableCollection where Self: BidirectionalCollection { @_disfavoredOverload - public mutating func trimSuffix( + mutating func trimSuffix( while predicate: @escaping (Element) -> Bool ) { trimSuffix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) } @_disfavoredOverload - public mutating func trim(while predicate: @escaping (Element) -> Bool) { + mutating func trim(while predicate: @escaping (Element) -> Bool) { let consumer = ManyConsumer( base: PredicateConsumer(predicate: predicate)) trimPrefix(consumer) @@ -178,6 +180,14 @@ extension RangeReplaceableCollection where Self: BidirectionalCollection { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { + /// Returns a new collection of the same type by removing initial elements + /// that satisfy the given predicate from the start. + /// - Parameter predicate: A closure that takes an element of the sequence + /// as its argument and returns a Boolean value indicating whether the + /// element should be removed from the collection. + /// - Returns: A collection containing the elements of the collection that are + /// not removed by `predicate`. + @available(SwiftStdlib 5.7, *) public func trimmingPrefix( _ prefix: Prefix ) -> SubSequence where Prefix.Element == Element { @@ -186,6 +196,12 @@ extension Collection where Element: Equatable { } extension Collection where SubSequence == Self, Element: Equatable { + /// Removes the initial elements that satisfy the given predicate from the + /// start of the sequence. + /// - Parameter predicate: A closure that takes an element of the sequence + /// as its argument and returns a Boolean value indicating whether the + /// element should be removed from the collection. + @available(SwiftStdlib 5.7, *) public mutating func trimPrefix( _ prefix: Prefix ) where Prefix.Element == Element { @@ -195,6 +211,12 @@ extension Collection where SubSequence == Self, Element: Equatable { extension RangeReplaceableCollection where Element: Equatable { @_disfavoredOverload + /// Removes the initial elements that satisfy the given predicate from the + /// start of the sequence. + /// - Parameter predicate: A closure that takes an element of the sequence + /// as its argument and returns a Boolean value indicating whether the + /// element should be removed from the collection. + @available(SwiftStdlib 5.7, *) public mutating func trimPrefix( _ prefix: Prefix ) where Prefix.Element == Element { @@ -203,13 +225,13 @@ extension RangeReplaceableCollection where Element: Equatable { } extension BidirectionalCollection where Element: Equatable { - public func trimmingSuffix( + func trimmingSuffix( _ suffix: Suffix ) -> SubSequence where Suffix.Element == Element { trimmingSuffix(FixedPatternConsumer(pattern: suffix)) } - public func trimming( + func trimming( _ pattern: Pattern ) -> SubSequence where Pattern.Element == Element { trimming(FixedPatternConsumer(pattern: pattern)) @@ -219,13 +241,13 @@ extension BidirectionalCollection where Element: Equatable { extension BidirectionalCollection where SubSequence == Self, Element: Equatable { - public mutating func trimSuffix( + mutating func trimSuffix( _ suffix: Suffix ) where Suffix.Element == Element { trimSuffix(FixedPatternConsumer(pattern: suffix)) } - public mutating func trim( + mutating func trim( _ pattern: Pattern ) where Pattern.Element == Element { let consumer = FixedPatternConsumer(pattern: pattern) @@ -238,14 +260,14 @@ extension RangeReplaceableCollection where Self: BidirectionalCollection, Element: Equatable { @_disfavoredOverload - public mutating func trimSuffix( + mutating func trimSuffix( _ prefix: Suffix ) where Suffix.Element == Element { trimSuffix(FixedPatternConsumer(pattern: prefix)) } @_disfavoredOverload - public mutating func trim( + mutating func trim( _ pattern: Pattern ) where Pattern.Element == Element { let consumer = FixedPatternConsumer(pattern: pattern) @@ -257,15 +279,23 @@ extension RangeReplaceableCollection // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { + /// Returns a new collection of the same type by removing `prefix` from the + /// start. + /// - Parameter prefix: The collection to remove from this collection. + /// - Returns: A collection containing the elements that does not match + /// `prefix` from the start. + @available(SwiftStdlib 5.7, *) public func trimmingPrefix(_ regex: R) -> SubSequence { trimmingPrefix(RegexConsumer(regex)) } - - public func trimmingSuffix(_ regex: R) -> SubSequence { + + @available(SwiftStdlib 5.7, *) + func trimmingSuffix(_ regex: R) -> SubSequence { trimmingSuffix(RegexConsumer(regex)) } - - public func trimming(_ regex: R) -> SubSequence { + + @available(SwiftStdlib 5.7, *) + func trimming(_ regex: R) -> SubSequence { trimming(RegexConsumer(regex)) } } @@ -273,15 +303,20 @@ extension BidirectionalCollection where SubSequence == Substring { extension RangeReplaceableCollection where Self: BidirectionalCollection, SubSequence == Substring { + /// Removes the initial elements that matches the given regex. + /// - Parameter regex: The regex to remove from this collection. + @available(SwiftStdlib 5.7, *) public mutating func trimPrefix(_ regex: R) { trimPrefix(RegexConsumer(regex)) } - - public mutating func trimSuffix(_ regex: R) { + + @available(SwiftStdlib 5.7, *) + mutating func trimSuffix(_ regex: R) { trimSuffix(RegexConsumer(regex)) } - - public mutating func trim(_ regex: R) { + + @available(SwiftStdlib 5.7, *) + mutating func trim(_ regex: R) { let consumer = RegexConsumer(regex) trimPrefix(consumer) trimSuffix(consumer) @@ -289,15 +324,18 @@ extension RangeReplaceableCollection } extension Substring { - public mutating func trimPrefix(_ regex: R) { + @available(SwiftStdlib 5.7, *) + mutating func trimPrefix(_ regex: R) { trimPrefix(RegexConsumer(regex)) } - - public mutating func trimSuffix(_ regex: R) { + + @available(SwiftStdlib 5.7, *) + mutating func trimSuffix(_ regex: R) { trimSuffix(RegexConsumer(regex)) } - - public mutating func trim(_ regex: R) { + + @available(SwiftStdlib 5.7, *) + mutating func trim(_ regex: R) { let consumer = RegexConsumer(regex) trimPrefix(consumer) trimSuffix(consumer) diff --git a/Sources/_StringProcessing/Algorithms/Consumers/CollectionConsumer.swift b/Sources/_StringProcessing/Algorithms/Consumers/CollectionConsumer.swift index 95f772d7b..b71af470e 100644 --- a/Sources/_StringProcessing/Algorithms/Consumers/CollectionConsumer.swift +++ b/Sources/_StringProcessing/Algorithms/Consumers/CollectionConsumer.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -public protocol CollectionConsumer { +protocol CollectionConsumer { associatedtype Consumed: Collection func consuming( _ consumed: Consumed, @@ -18,13 +18,13 @@ public protocol CollectionConsumer { } extension CollectionConsumer { - public func consuming(_ consumed: Consumed) -> Consumed.Index? { + func consuming(_ consumed: Consumed) -> Consumed.Index? { consuming(consumed, in: consumed.startIndex.. Bool + func consume(_ consumed: inout Consumed) -> Bool where Consumed.SubSequence == Consumed { guard let index = consuming(consumed) else { return false } @@ -35,7 +35,7 @@ extension CollectionConsumer { // MARK: Consuming from the back -public protocol BidirectionalCollectionConsumer: CollectionConsumer +protocol BidirectionalCollectionConsumer: CollectionConsumer where Consumed: BidirectionalCollection { func consumingBack( @@ -45,11 +45,11 @@ public protocol BidirectionalCollectionConsumer: CollectionConsumer } extension BidirectionalCollectionConsumer { - public func consumingBack(_ consumed: Consumed) -> Consumed.Index? { + func consumingBack(_ consumed: Consumed) -> Consumed.Index? { consumingBack(consumed, in: consumed.startIndex.. Bool + func consumeBack(_ consumed: inout Consumed) -> Bool where Consumed.SubSequence == Consumed { guard let index = consumingBack(consumed) else { return false } diff --git a/Sources/_StringProcessing/Algorithms/Consumers/PredicateConsumer.swift b/Sources/_StringProcessing/Algorithms/Consumers/PredicateConsumer.swift index c9b92b9ec..caf523d1c 100644 --- a/Sources/_StringProcessing/Algorithms/Consumers/PredicateConsumer.swift +++ b/Sources/_StringProcessing/Algorithms/Consumers/PredicateConsumer.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -public struct PredicateConsumer { +struct PredicateConsumer { let predicate: (Consumed.Element) -> Bool } @@ -29,7 +29,7 @@ extension PredicateConsumer: CollectionConsumer { extension PredicateConsumer: BidirectionalCollectionConsumer where Consumed: BidirectionalCollection { - public func consumingBack( + func consumingBack( _ consumed: Consumed, in range: Range ) -> Consumed.Index? { @@ -59,9 +59,9 @@ extension PredicateConsumer: BackwardCollectionSearcher, BackwardStatelessCollectionSearcher where Searched: BidirectionalCollection { - public typealias BackwardSearched = Consumed + typealias BackwardSearched = Consumed - public func searchBack( + func searchBack( _ searched: BackwardSearched, in range: Range ) -> Range? { diff --git a/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift b/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift index 3ab1e579d..4956406da 100644 --- a/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift +++ b/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift @@ -9,22 +9,25 @@ // //===----------------------------------------------------------------------===// -public struct RegexConsumer< +// FIXME: What even is this? Can we delete this whole thing? +@available(SwiftStdlib 5.7, *) +struct RegexConsumer< R: RegexComponent, Consumed: BidirectionalCollection > where Consumed.SubSequence == Substring { // TODO: Should `Regex` itself implement these protocols? let regex: R - public init(_ regex: R) { + init(_ regex: R) { self.regex = regex } } +@available(SwiftStdlib 5.7, *) extension RegexConsumer { func _matchingConsuming( _ consumed: Substring, in range: Range ) -> (upperBound: String.Index, match: Match)? { - guard let result = try! regex._match( + guard let result = try! regex.regex._match( consumed.base, in: range, mode: .partialFromFront ) else { return nil } @@ -35,10 +38,11 @@ extension RegexConsumer { // TODO: Explicitly implement the non-matching consumer/searcher protocols as // well, taking advantage of the fact that the captures can be ignored +@available(SwiftStdlib 5.7, *) extension RegexConsumer: MatchingCollectionConsumer { - public typealias Match = R.Output + typealias Match = R.RegexOutput - public func matchingConsuming( + func matchingConsuming( _ consumed: Consumed, in range: Range ) -> (upperBound: String.Index, match: Match)? { _matchingConsuming(consumed[...], in: range) @@ -46,8 +50,9 @@ extension RegexConsumer: MatchingCollectionConsumer { } // TODO: We'll want to bake backwards into the engine +@available(SwiftStdlib 5.7, *) extension RegexConsumer: BidirectionalMatchingCollectionConsumer { - public func matchingConsumingBack( + func matchingConsumingBack( _ consumed: Consumed, in range: Range ) -> (lowerBound: String.Index, match: Match)? { var i = range.lowerBound @@ -66,13 +71,14 @@ extension RegexConsumer: BidirectionalMatchingCollectionConsumer { } } +@available(SwiftStdlib 5.7, *) extension RegexConsumer: MatchingStatelessCollectionSearcher { - public typealias Searched = Consumed + typealias Searched = Consumed // TODO: We'll want to bake search into the engine so it can // take advantage of the structure of the regex itself and // its own internal state - public func matchingSearch( + func matchingSearch( _ searched: Searched, in range: Range ) -> (range: Range, match: Match)? { ConsumerSearcher(consumer: self).matchingSearch(searched, in: range) @@ -80,10 +86,11 @@ extension RegexConsumer: MatchingStatelessCollectionSearcher { } // TODO: Bake in search-back to engine too +@available(SwiftStdlib 5.7, *) extension RegexConsumer: BackwardMatchingStatelessCollectionSearcher { - public typealias BackwardSearched = Consumed + typealias BackwardSearched = Consumed - public func matchingSearchBack( + func matchingSearchBack( _ searched: BackwardSearched, in range: Range ) -> (range: Range, match: Match)? { ConsumerSearcher(consumer: self).matchingSearchBack(searched, in: range) diff --git a/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift b/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift index c0699b805..cb527f948 100644 --- a/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift +++ b/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift @@ -12,7 +12,7 @@ // MARK: `CollectionSearcher` algorithms extension Collection { - public func firstMatch( + func firstMatch( of searcher: S ) -> _MatchResult? where S.Searched == Self { var state = searcher.state(for: self, in: startIndex..( + func lastMatch( of searcher: S ) -> _BackwardMatchResult? where S.BackwardSearched == Self @@ -38,15 +38,29 @@ extension BidirectionalCollection { // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { - public func firstMatch( + @available(SwiftStdlib 5.7, *) + func firstMatch( of regex: R ) -> _MatchResult>? { firstMatch(of: RegexConsumer(regex)) } - - public func lastMatch( + + @available(SwiftStdlib 5.7, *) + func lastMatch( of regex: R ) -> _BackwardMatchResult>? { lastMatch(of: RegexConsumer(regex)) } + + /// Returns the first match of the specified regex within the collection. + /// - Parameter regex: The regex to search for. + /// - Returns: The first match of `regex` in the collection, or `nil` if + /// there isn't a match. + @available(SwiftStdlib 5.7, *) + public func firstMatch( + of r: R + ) -> Regex.Match? { + let slice = self[...] + return try? r.regex.firstMatch(in: slice) + } } diff --git a/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift b/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift index f99e525b5..8485182de 100644 --- a/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift +++ b/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift @@ -12,7 +12,7 @@ // MARK: `MatchingCollectionSearcher` algorithms extension RangeReplaceableCollection { - public func replacing< + func replacing< Searcher: MatchingCollectionSearcher, Replacement: Collection >( _ searcher: Searcher, @@ -40,7 +40,7 @@ extension RangeReplaceableCollection { return result } - public func replacing< + func replacing< Searcher: MatchingCollectionSearcher, Replacement: Collection >( _ searcher: Searcher, @@ -56,7 +56,7 @@ extension RangeReplaceableCollection { maxReplacements: maxReplacements) } - public mutating func replace< + mutating func replace< Searcher: MatchingCollectionSearcher, Replacement: Collection >( _ searcher: Searcher, @@ -75,7 +75,8 @@ extension RangeReplaceableCollection { // MARK: Regex algorithms extension RangeReplaceableCollection where SubSequence == Substring { - public func replacing( + @available(SwiftStdlib 5.7, *) + func replacing( _ regex: R, with replacement: (_MatchResult>) throws -> Replacement, subrange: Range, @@ -87,8 +88,9 @@ extension RangeReplaceableCollection where SubSequence == Substring { subrange: subrange, maxReplacements: maxReplacements) } - - public func replacing( + + @available(SwiftStdlib 5.7, *) + func replacing( _ regex: R, with replacement: (_MatchResult>) throws -> Replacement, maxReplacements: Int = .max @@ -99,8 +101,9 @@ extension RangeReplaceableCollection where SubSequence == Substring { subrange: startIndex..( + + @available(SwiftStdlib 5.7, *) + mutating func replace( _ regex: R, with replacement: (_MatchResult>) throws -> Replacement, maxReplacements: Int = .max @@ -110,4 +113,85 @@ extension RangeReplaceableCollection where SubSequence == Substring { with: replacement, maxReplacements: maxReplacements) } + + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another regex match. + /// - Parameters: + /// - regex: A regex describing the sequence to replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - subrange: The range in the collection in which to search for `regex`. + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + @available(SwiftStdlib 5.7, *) + public func replacing( + _ regex: R, + with replacement: (Regex.Match) throws -> Replacement, + subrange: Range, + maxReplacements: Int = .max + ) rethrows -> Self where Replacement.Element == Element { + + precondition(maxReplacements >= 0) + + var index = subrange.lowerBound + var result = Self() + result.append(contentsOf: self[..( + _ regex: R, + with replacement: (Regex.Match) throws -> Replacement, + maxReplacements: Int = .max + ) rethrows -> Self where Replacement.Element == Element { + try replacing( + regex, + with: replacement, + subrange: startIndex..( + _ regex: R, + with replacement: (Regex.Match) throws -> Replacement, + maxReplacements: Int = .max + ) rethrows where Replacement.Element == Element { + self = try replacing( + regex, + with: replacement, + subrange: startIndex.. { - public let match: S.Searched.SubSequence - public let result: S.Match +struct _MatchResult { + let match: S.Searched.SubSequence + let result: S.Match - public var range: Range { + var range: Range { match.startIndex.. { - public let match: S.BackwardSearched.SubSequence - public let result: S.Match +struct _BackwardMatchResult { + let match: S.BackwardSearched.SubSequence + let result: S.Match - public var range: Range { + var range: Range { match.startIndex.. { +struct MatchesCollection { public typealias Base = Searcher.Searched let base: Base @@ -33,7 +33,7 @@ public struct MatchesCollection { } } -public struct MatchesIterator< +struct MatchesIterator< Searcher: MatchingCollectionSearcher >: IteratorProtocol { public typealias Base = Searcher.Searched @@ -64,7 +64,7 @@ extension MatchesCollection: Sequence { extension MatchesCollection: Collection { // TODO: Custom `SubSequence` for the sake of more efficient slice iteration - public struct Index { + struct Index { var match: (range: Range, match: Searcher.Match)? var state: Searcher.State } @@ -122,7 +122,7 @@ extension MatchesCollection.Index: Comparable { // MARK: `ReversedMatchesCollection` // TODO: reversed matches -public struct ReversedMatchesCollection< +struct ReversedMatchesCollection< Searcher: BackwardMatchingCollectionSearcher > { public typealias Base = Searcher.BackwardSearched @@ -137,7 +137,7 @@ public struct ReversedMatchesCollection< } extension ReversedMatchesCollection: Sequence { - public struct Iterator: IteratorProtocol { + struct Iterator: IteratorProtocol { let base: Base let searcher: Searcher var state: Searcher.BackwardState @@ -166,7 +166,7 @@ extension ReversedMatchesCollection: Sequence { // MARK: `CollectionSearcher` algorithms extension Collection { - public func matches( + func matches( of searcher: S ) -> MatchesCollection where S.Searched == Self { MatchesCollection(base: self, searcher: searcher) @@ -174,7 +174,7 @@ extension Collection { } extension BidirectionalCollection { - public func matchesFromBack( + func matchesFromBack( of searcher: S ) -> ReversedMatchesCollection where S.BackwardSearched == Self { ReversedMatchesCollection(base: self, searcher: searcher) @@ -184,15 +184,44 @@ extension BidirectionalCollection { // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { - public func matches( + // FIXME: Replace `MatchesCollection` when SE-0346 is enabled + /// Returns a collection containing all matches of the specified regex. + /// - Parameter regex: The regex to search for. + /// - Returns: A collection of matches of `regex`. + @available(SwiftStdlib 5.7, *) + func matches( of regex: R ) -> MatchesCollection> { matches(of: RegexConsumer(regex)) } - - public func matchesFromBack( + + @available(SwiftStdlib 5.7, *) + func matchesFromBack( of regex: R ) -> ReversedMatchesCollection> { matchesFromBack(of: RegexConsumer(regex)) } + + // FIXME: Replace the returned value as `some Collection.Match> + // when SE-0346 is enabled + @available(SwiftStdlib 5.7, *) + func _matches(of r: R) -> [Regex.Match] { + let slice = self[...] + var start = self.startIndex + let end = self.endIndex + let regex = r.regex + + var result = [Regex.Match]() + while start < end { + guard let match = try? regex._firstMatch( + slice.base, in: start.. ) -> Consumed.Index? { @@ -28,7 +28,7 @@ extension MatchingCollectionConsumer { // MARK: Consuming from the back -public protocol BidirectionalMatchingCollectionConsumer: +protocol BidirectionalMatchingCollectionConsumer: MatchingCollectionConsumer, BidirectionalCollectionConsumer { func matchingConsumingBack( @@ -38,7 +38,7 @@ public protocol BidirectionalMatchingCollectionConsumer: } extension BidirectionalMatchingCollectionConsumer { - public func consumingBack( + func consumingBack( _ consumed: Consumed, in range: Range ) -> Consumed.Index? { diff --git a/Sources/_StringProcessing/Algorithms/Matching/MatchingCollectionSearcher.swift b/Sources/_StringProcessing/Algorithms/Matching/MatchingCollectionSearcher.swift index eadb46f9e..902d94591 100644 --- a/Sources/_StringProcessing/Algorithms/Matching/MatchingCollectionSearcher.swift +++ b/Sources/_StringProcessing/Algorithms/Matching/MatchingCollectionSearcher.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -public protocol MatchingCollectionSearcher: CollectionSearcher { +protocol MatchingCollectionSearcher: CollectionSearcher { associatedtype Match func matchingSearch( _ searched: Searched, @@ -18,7 +18,7 @@ public protocol MatchingCollectionSearcher: CollectionSearcher { } extension MatchingCollectionSearcher { - public func search( + func search( _ searched: Searched, _ state: inout State ) -> Range? { @@ -26,7 +26,7 @@ extension MatchingCollectionSearcher { } } -public protocol MatchingStatelessCollectionSearcher: +protocol MatchingStatelessCollectionSearcher: MatchingCollectionSearcher, StatelessCollectionSearcher { func matchingSearch( @@ -38,14 +38,14 @@ public protocol MatchingStatelessCollectionSearcher: extension MatchingStatelessCollectionSearcher { // for disambiguation between the `MatchingCollectionSearcher` and // `StatelessCollectionSearcher` overloads - public func search( + func search( _ searched: Searched, _ state: inout State ) -> Range? { matchingSearch(searched, &state)?.range } - public func matchingSearch( + func matchingSearch( _ searched: Searched, _ state: inout State ) -> (range: Range, match: Match)? { @@ -69,7 +69,7 @@ extension MatchingStatelessCollectionSearcher { return (range, value) } - public func search( + func search( _ searched: Searched, in range: Range ) -> Range? { @@ -79,7 +79,7 @@ extension MatchingStatelessCollectionSearcher { // MARK: Searching from the back -public protocol BackwardMatchingCollectionSearcher: BackwardCollectionSearcher { +protocol BackwardMatchingCollectionSearcher: BackwardCollectionSearcher { associatedtype Match func matchingSearchBack( _ searched: BackwardSearched, @@ -87,7 +87,7 @@ public protocol BackwardMatchingCollectionSearcher: BackwardCollectionSearcher { ) -> (range: Range, match: Match)? } -public protocol BackwardMatchingStatelessCollectionSearcher: +protocol BackwardMatchingStatelessCollectionSearcher: BackwardMatchingCollectionSearcher, BackwardStatelessCollectionSearcher { func matchingSearchBack( @@ -97,14 +97,14 @@ public protocol BackwardMatchingStatelessCollectionSearcher: } extension BackwardMatchingStatelessCollectionSearcher { - public func searchBack( + func searchBack( _ searched: BackwardSearched, in range: Range ) -> Range? { matchingSearchBack(searched, in: range)?.range } - public func matchingSearchBack( + func matchingSearchBack( _ searched: BackwardSearched, _ state: inout BackwardState) -> (range: Range, match: Match)? { diff --git a/Sources/_StringProcessing/Algorithms/Searchers/CollectionSearcher.swift b/Sources/_StringProcessing/Algorithms/Searchers/CollectionSearcher.swift index 78e4fc925..5eb199086 100644 --- a/Sources/_StringProcessing/Algorithms/Searchers/CollectionSearcher.swift +++ b/Sources/_StringProcessing/Algorithms/Searchers/CollectionSearcher.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -public struct DefaultSearcherState { +struct DefaultSearcherState { enum Position { case index(Searched.Index) case done @@ -19,7 +19,7 @@ public struct DefaultSearcherState { let end: Searched.Index } -public protocol CollectionSearcher { +protocol CollectionSearcher { associatedtype Searched: Collection associatedtype State @@ -30,7 +30,7 @@ public protocol CollectionSearcher { ) -> Range? } -public protocol StatelessCollectionSearcher: CollectionSearcher +protocol StatelessCollectionSearcher: CollectionSearcher where State == DefaultSearcherState { func search( @@ -39,14 +39,14 @@ public protocol StatelessCollectionSearcher: CollectionSearcher } extension StatelessCollectionSearcher { - public func state( + func state( for searched: Searched, in range: Range ) -> State { State(position: .index(range.lowerBound), end: range.upperBound) } - public func search( + func search( _ searched: Searched, _ state: inout State ) -> Range? { @@ -71,7 +71,7 @@ extension StatelessCollectionSearcher { // MARK: Searching from the back -public protocol BackwardCollectionSearcher { +protocol BackwardCollectionSearcher { associatedtype BackwardSearched: BidirectionalCollection associatedtype BackwardState @@ -84,7 +84,7 @@ public protocol BackwardCollectionSearcher { ) -> Range? } -public protocol BackwardStatelessCollectionSearcher: BackwardCollectionSearcher +protocol BackwardStatelessCollectionSearcher: BackwardCollectionSearcher where BackwardState == DefaultSearcherState { func searchBack( @@ -94,14 +94,14 @@ public protocol BackwardStatelessCollectionSearcher: BackwardCollectionSearcher } extension BackwardStatelessCollectionSearcher { - public func backwardState( + func backwardState( for searched: BackwardSearched, in range: Range ) -> BackwardState { BackwardState(position: .index(range.upperBound), end: range.lowerBound) } - public func searchBack( + func searchBack( _ searched: BackwardSearched, _ state: inout BackwardState) -> Range? { guard diff --git a/Sources/_StringProcessing/Algorithms/Searchers/PatternOrEmpty.swift b/Sources/_StringProcessing/Algorithms/Searchers/PatternOrEmpty.swift index ee1b04adf..3b3fe22f9 100644 --- a/Sources/_StringProcessing/Algorithms/Searchers/PatternOrEmpty.swift +++ b/Sources/_StringProcessing/Algorithms/Searchers/PatternOrEmpty.swift @@ -10,14 +10,14 @@ //===----------------------------------------------------------------------===// /// Wraps a searcher that searches for a given pattern. If the pattern is empty, falls back on matching every empty index range exactly once. -public struct PatternOrEmpty { +struct PatternOrEmpty { let searcher: Searcher? } extension PatternOrEmpty: CollectionSearcher { - public typealias Searched = Searcher.Searched + typealias Searched = Searcher.Searched - public struct State { + struct State { enum Representation { case state(Searcher.State) case empty(index: Searched.Index, end: Searched.Index) @@ -27,7 +27,7 @@ extension PatternOrEmpty: CollectionSearcher { let representation: Representation } - public func state( + func state( for searched: Searcher.Searched, in range: Range ) -> State { @@ -40,7 +40,7 @@ extension PatternOrEmpty: CollectionSearcher { } } - public func search( + func search( _ searched: Searched, _ state: inout State ) -> Range? { diff --git a/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift b/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift index 11184f856..5530b4421 100644 --- a/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift +++ b/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -public struct TwoWaySearcher +struct TwoWaySearcher where Searched.Element: Comparable { // TODO: Be generic over the pattern? @@ -36,14 +36,14 @@ public struct TwoWaySearcher } extension TwoWaySearcher: CollectionSearcher { - public struct State { + struct State { let end: Searched.Index var index: Searched.Index var criticalIndex: Searched.Index var memory: (offset: Int, index: Searched.Index)? } - public func state( + func state( for searched: Searched, in range: Range ) -> State { @@ -57,7 +57,7 @@ extension TwoWaySearcher: CollectionSearcher { memory: nil) } - public func search( + func search( _ searched: Searched, _ state: inout State ) -> Range? { diff --git a/Sources/_StringProcessing/Algorithms/Searchers/ZSearcher.swift b/Sources/_StringProcessing/Algorithms/Searchers/ZSearcher.swift index a541dcb7d..e06796e72 100644 --- a/Sources/_StringProcessing/Algorithms/Searchers/ZSearcher.swift +++ b/Sources/_StringProcessing/Algorithms/Searchers/ZSearcher.swift @@ -9,12 +9,12 @@ // //===----------------------------------------------------------------------===// -public struct ZSearcher { +struct ZSearcher { let pattern: [Searched.Element] let z: [Int] let areEquivalent: (Searched.Element, Searched.Element) -> Bool - public init( + init( pattern: [Searched.Element], by areEquivalent: @escaping (Searched.Element, Searched.Element ) -> Bool) { @@ -25,7 +25,7 @@ public struct ZSearcher { } extension ZSearcher: StatelessCollectionSearcher { - public func search( + func search( _ searched: Searched, in range: Range ) -> Range? { diff --git a/Sources/_StringProcessing/ByteCodeGen.swift b/Sources/_StringProcessing/ByteCodeGen.swift index d03a1e382..3cc2d4039 100644 --- a/Sources/_StringProcessing/ByteCodeGen.swift +++ b/Sources/_StringProcessing/ByteCodeGen.swift @@ -1,4 +1,4 @@ -import _RegexParser +@_implementationOnly import _RegexParser extension Compiler { struct ByteCodeGen { @@ -111,30 +111,41 @@ extension Compiler.ByteCodeGen { } case .startOfLine: - builder.buildAssert { (input, pos, bounds) in - pos == input.startIndex || - input[input.index(before: pos)].isNewline + if options.anchorsMatchNewlines { + builder.buildAssert { (input, pos, bounds) in + pos == input.startIndex || input[input.index(before: pos)].isNewline + } + } else { + builder.buildAssert { (input, pos, bounds) in + pos == input.startIndex + } } - + case .endOfLine: - builder.buildAssert { (input, pos, bounds) in - pos == input.endIndex || input[pos].isNewline + if options.anchorsMatchNewlines { + builder.buildAssert { (input, pos, bounds) in + pos == input.endIndex || input[pos].isNewline + } + } else { + builder.buildAssert { (input, pos, bounds) in + pos == input.endIndex + } } case .wordBoundary: // TODO: May want to consider Unicode level - builder.buildAssert { (input, pos, bounds) in + builder.buildAssert { [options] (input, pos, bounds) in // TODO: How should we handle bounds? - CharacterClass.word.isBoundary( - input, at: pos, bounds: bounds) + _CharacterClassModel.word.isBoundary( + input, at: pos, bounds: bounds, with: options) } case .notWordBoundary: // TODO: May want to consider Unicode level - builder.buildAssert { (input, pos, bounds) in + builder.buildAssert { [options] (input, pos, bounds) in // TODO: How should we handle bounds? - !CharacterClass.word.isBoundary( - input, at: pos, bounds: bounds) + !_CharacterClassModel.word.isBoundary( + input, at: pos, bounds: bounds, with: options) } } } @@ -288,7 +299,9 @@ extension Compiler.ByteCodeGen { // not captured. This may mean we should store // an existential instead of a closure... - let matcher = builder.makeMatcherFunction(matcher) + let matcher = builder.makeMatcherFunction { input, start, range in + try matcher(input, start, range) + } let valReg = builder.makeValueRegister() builder.buildMatcher(matcher, into: valReg) @@ -306,7 +319,7 @@ extension Compiler.ByteCodeGen { ) throws { let transform = builder.makeTransformFunction { input, range in - t(input[range]) + try t(input[range]) } builder.buildBeginCapture(cap) try emitNode(child) @@ -348,10 +361,20 @@ extension Compiler.ByteCodeGen { mutating func emitQuantification( _ amount: AST.Quantification.Amount, - _ kind: AST.Quantification.Kind, + _ kind: DSLTree.QuantificationKind, _ child: DSLTree.Node ) throws { - let kind = kind.applying(options) + let updatedKind: AST.Quantification.Kind + switch kind { + case .explicit(let kind): + updatedKind = kind + case .syntax(let kind): + updatedKind = kind.applying(options) + case .default: + updatedKind = options.isReluctantByDefault + ? .reluctant + : .eager + } let (low, high) = amount.bounds switch (low, high) { @@ -480,7 +503,7 @@ extension Compiler.ByteCodeGen { } // Set up a dummy save point for possessive to update - if kind == .possessive { + if updatedKind == .possessive { builder.pushEmptySavePoint() } @@ -526,7 +549,7 @@ extension Compiler.ByteCodeGen { to: exit, ifZeroElseDecrement: extraTripsReg!) } - switch kind { + switch updatedKind { case .eager: builder.buildSplit(to: loopBody, saving: exit) case .possessive: @@ -584,7 +607,15 @@ extension Compiler.ByteCodeGen { try emitQuantification(amt, kind, child) case let .customCharacterClass(ccc): - try emitCustomCharacterClass(ccc) + if ccc.containsAny { + if !ccc.isInverted { + emitAny() + } else { + throw Unsupported("Inverted any") + } + } else { + try emitCustomCharacterClass(ccc) + } case let .atom(a): try emitAtom(a) diff --git a/Sources/_StringProcessing/Capture.swift b/Sources/_StringProcessing/Capture.swift index f7dff424e..51428acee 100644 --- a/Sources/_StringProcessing/Capture.swift +++ b/Sources/_StringProcessing/Capture.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser /// A structured capture struct StructuredCapture { diff --git a/Sources/_StringProcessing/Compiler.swift b/Sources/_StringProcessing/Compiler.swift index 90192bdaf..96476f42b 100644 --- a/Sources/_StringProcessing/Compiler.swift +++ b/Sources/_StringProcessing/Compiler.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser class Compiler { let tree: DSLTree diff --git a/Sources/_StringProcessing/ConsumerInterface.swift b/Sources/_StringProcessing/ConsumerInterface.swift index 0a2d93ff1..600234e0d 100644 --- a/Sources/_StringProcessing/ConsumerInterface.swift +++ b/Sources/_StringProcessing/ConsumerInterface.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser extension DSLTree.Node { /// Attempt to generate a consumer from this AST node @@ -136,7 +136,7 @@ extension AST.Atom { ) { return { input, bounds in // FIXME: should we worry about out of bounds? - cc.matches(in: input, at: bounds.lowerBound) + cc.matches(in: input, at: bounds.lowerBound, with: opts) } } diff --git a/Sources/_StringProcessing/Engine/Consume.swift b/Sources/_StringProcessing/Engine/Consume.swift index 4e00a34b4..bc60ba260 100644 --- a/Sources/_StringProcessing/Engine/Consume.swift +++ b/Sources/_StringProcessing/Engine/Consume.swift @@ -25,6 +25,7 @@ extension Engine { } extension Processor where Input == String { + // TODO: Should we throw here? mutating func consume() -> Input.Index? { while true { switch self.state { diff --git a/Sources/_StringProcessing/Engine/MEBuilder.swift b/Sources/_StringProcessing/Engine/MEBuilder.swift index 2b849874b..7cf94f6ef 100644 --- a/Sources/_StringProcessing/Engine/MEBuilder.swift +++ b/Sources/_StringProcessing/Engine/MEBuilder.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser // For errors +@_implementationOnly import _RegexParser // For errors extension MEProgram where Input.Element: Hashable { struct Builder { diff --git a/Sources/_StringProcessing/Engine/MECapture.swift b/Sources/_StringProcessing/Engine/MECapture.swift index 301212736..390af7d66 100644 --- a/Sources/_StringProcessing/Engine/MECapture.swift +++ b/Sources/_StringProcessing/Engine/MECapture.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser /* diff --git a/Sources/_StringProcessing/Engine/MEProgram.swift b/Sources/_StringProcessing/Engine/MEProgram.swift index a31134cc9..b0f2e6a79 100644 --- a/Sources/_StringProcessing/Engine/MEProgram.swift +++ b/Sources/_StringProcessing/Engine/MEProgram.swift @@ -9,16 +9,16 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser struct MEProgram where Input.Element: Equatable { typealias ConsumeFunction = (Input, Range) -> Input.Index? typealias AssertionFunction = - (Input, Input.Index, Range) -> Bool + (Input, Input.Index, Range) throws -> Bool typealias TransformFunction = - (Input, Range) -> Any? + (Input, Range) throws -> Any? typealias MatcherFunction = - (Input, Input.Index, Range) -> (Input.Index, Any)? + (Input, Input.Index, Range) throws -> (Input.Index, Any)? var instructions: InstructionList diff --git a/Sources/_StringProcessing/Engine/Processor.swift b/Sources/_StringProcessing/Engine/Processor.swift index 343b02c92..8f777ad33 100644 --- a/Sources/_StringProcessing/Engine/Processor.swift +++ b/Sources/_StringProcessing/Engine/Processor.swift @@ -51,6 +51,8 @@ struct Processor< var state: State = .inProgress + var failureReason: Error? = nil + var isTracingEnabled: Bool var storedCaptures: Array<_StoredCapture> @@ -181,6 +183,13 @@ extension Processor { registers.ints = intRegisters } + mutating func abort(_ e: Error? = nil) { + if let e = e { + self.failureReason = e + } + self.state = .fail + } + mutating func tryAccept() { switch (currentPosition, matchMode) { // When reaching the end of the match bounds or when we are only doing a @@ -355,8 +364,13 @@ extension Processor { case .assertBy: let reg = payload.assertion let assertion = registers[reg] - guard assertion(input, currentPosition, bounds) else { - signalFailure() + do { + guard try assertion(input, currentPosition, bounds) else { + signalFailure() + return + } + } catch { + abort(error) return } controller.step() @@ -364,15 +378,20 @@ extension Processor { case .matchBy: let (matcherReg, valReg) = payload.pairedMatcherValue let matcher = registers[matcherReg] - guard let (nextIdx, val) = matcher( - input, currentPosition, bounds - ) else { - signalFailure() + do { + guard let (nextIdx, val) = try matcher( + input, currentPosition, bounds + ) else { + signalFailure() + return + } + registers[valReg] = val + advance(to: nextIdx) + controller.step() + } catch { + abort(error) return } - registers[valReg] = val - advance(to: nextIdx) - controller.step() case .print: // TODO: Debug stream @@ -431,14 +450,18 @@ extension Processor { fatalError( "Unreachable: transforming without a capture") } - // FIXME: Pass input or the slice? - guard let value = transform(input, range) else { - signalFailure() + do { + // FIXME: Pass input or the slice? + guard let value = try transform(input, range) else { + signalFailure() + return + } + storedCaptures[capNum].registerValue(value) + controller.step() + } catch { + abort(error) return } - storedCaptures[capNum].registerValue(value) - - controller.step() case .captureValue: let (val, cap) = payload.pairedValueCapture diff --git a/Sources/_StringProcessing/Engine/Registers.swift b/Sources/_StringProcessing/Engine/Registers.swift index a2a5be104..bc17f1215 100644 --- a/Sources/_StringProcessing/Engine/Registers.swift +++ b/Sources/_StringProcessing/Engine/Registers.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser struct SentinelValue: Hashable, CustomStringConvertible { var description: String { "" } diff --git a/Sources/_StringProcessing/Engine/Structuralize.swift b/Sources/_StringProcessing/Engine/Structuralize.swift index 02a03c09c..12d2e1242 100644 --- a/Sources/_StringProcessing/Engine/Structuralize.swift +++ b/Sources/_StringProcessing/Engine/Structuralize.swift @@ -1,4 +1,4 @@ -import _RegexParser +@_implementationOnly import _RegexParser extension CaptureStructure { var optionalCount: Int { diff --git a/Sources/_StringProcessing/Executor.swift b/Sources/_StringProcessing/Executor.swift index 148ddf468..c7d4527a5 100644 --- a/Sources/_StringProcessing/Executor.swift +++ b/Sources/_StringProcessing/Executor.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser struct Executor { // TODO: consider let, for now lets us toggle tracing @@ -19,6 +19,7 @@ struct Executor { self.engine = Engine(program, enableTracing: enablesTracing) } + @available(SwiftStdlib 5.7, *) func match( _ input: String, in inputRange: Range, @@ -28,6 +29,9 @@ struct Executor { input: input, bounds: inputRange, matchMode: mode) guard let endIdx = cpu.consume() else { + if let e = cpu.failureReason { + throw e + } return nil } @@ -61,6 +65,7 @@ struct Executor { value: value) } + @available(SwiftStdlib 5.7, *) func dynamicMatch( _ input: String, in inputRange: Range, diff --git a/Sources/_StringProcessing/MatchingOptions.swift b/Sources/_StringProcessing/MatchingOptions.swift index 899891184..8213185c1 100644 --- a/Sources/_StringProcessing/MatchingOptions.swift +++ b/Sources/_StringProcessing/MatchingOptions.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser /// A type that represents the current state of regex matching options, with /// stack-based scoping. @@ -67,11 +67,32 @@ extension MatchingOptions { stack.last!.contains(.singleLine) } + var anchorsMatchNewlines: Bool { + stack.last!.contains(.multiline) + } + + var usesASCIIWord: Bool { + stack.last!.contains(.asciiOnlyWord) + || stack.last!.contains(.asciiOnlyPOSIXProps) + } + + var usesASCIIDigits: Bool { + stack.last!.contains(.asciiOnlyDigit) + || stack.last!.contains(.asciiOnlyPOSIXProps) + } + + var usesASCIISpaces: Bool { + stack.last!.contains(.asciiOnlySpace) + || stack.last!.contains(.asciiOnlyPOSIXProps) + } + + var usesSimpleUnicodeBoundaries: Bool { + !stack.last!.contains(.unicodeWordBoundaries) + } + enum SemanticLevel { case graphemeCluster case unicodeScalar - // TODO: include? - // case byte } var semanticLevel: SemanticLevel { @@ -84,7 +105,7 @@ extension MatchingOptions { // Deprecated CharacterClass.MatchLevel API extension MatchingOptions { @available(*, deprecated) - var matchLevel: CharacterClass.MatchLevel { + var matchLevel: _CharacterClassModel.MatchLevel { switch semanticLevel { case .graphemeCluster: return .graphemeCluster diff --git a/Sources/_StringProcessing/PrintAsPattern.swift b/Sources/_StringProcessing/PrintAsPattern.swift index 0cf16ab05..3afc19836 100644 --- a/Sources/_StringProcessing/PrintAsPattern.swift +++ b/Sources/_StringProcessing/PrintAsPattern.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser // TODO: Add an expansion level, both from top to bottom. // After `printAsCanonical` is fleshed out, these two @@ -17,8 +17,10 @@ import _RegexParser // incremental conversion, such that leaves remain // as canonical regex literals. +@_spi(PatternConverter) extension AST { /// Render as a Pattern DSL + @_spi(PatternConverter) public func renderAsBuilderDSL( maxTopDownLevels: Int? = nil, minBottomUpLevels: Int? = nil @@ -390,3 +392,14 @@ extension AST.Quantification.Kind { } } } + +extension DSLTree.QuantificationKind { + var _patternBase: String { + switch self { + case .explicit(let kind), .syntax(let kind): + return kind._patternBase + case .default: + return ".eager" + } + } +} diff --git a/Sources/_StringProcessing/Regex/ASTConversion.swift b/Sources/_StringProcessing/Regex/ASTConversion.swift index 5336a1892..e00dcd806 100644 --- a/Sources/_StringProcessing/Regex/ASTConversion.swift +++ b/Sources/_StringProcessing/Regex/ASTConversion.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser extension AST { var dslTree: DSLTree { @@ -123,7 +123,7 @@ extension AST.Node { case let .quantification(v): let child = v.child.dslTreeNode return .quantification( - v.amount.value, v.kind.value, child) + v.amount.value, .syntax(v.kind.value), child) case let .quote(v): return .quotedLiteral(v.literal) diff --git a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift index cac0e46c3..7b8a5ff32 100644 --- a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift +++ b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift @@ -9,25 +9,28 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser +@available(SwiftStdlib 5.7, *) extension Regex where Output == AnyRegexOutput { /// Parse and compile `pattern`, resulting in an existentially-typed capture list. - public init(compiling pattern: String) throws { + public init(_ pattern: String) throws { self.init(ast: try parse(pattern, .traditional)) } } +@available(SwiftStdlib 5.7, *) extension Regex { /// Parse and compile `pattern`, resulting in a strongly-typed capture list. public init( - compiling pattern: String, + _ pattern: String, as: Output.Type = Output.self ) throws { self.init(ast: try parse(pattern, .traditional)) } } +@available(SwiftStdlib 5.7, *) extension Regex.Match where Output == AnyRegexOutput { // Ensures `.0` always refers to the whole match. public subscript( @@ -37,6 +40,8 @@ extension Regex.Match where Output == AnyRegexOutput { } } +/// A type-erased regex output +@available(SwiftStdlib 5.7, *) public struct AnyRegexOutput { let input: String fileprivate let _elements: [ElementRepresentation] @@ -52,6 +57,7 @@ public struct AnyRegexOutput { } } +@available(SwiftStdlib 5.7, *) extension AnyRegexOutput { /// Creates a type-erased regex output from an existing output. /// @@ -70,6 +76,7 @@ extension AnyRegexOutput { /// Returns a typed output by converting the underlying value to the specified /// type. + /// /// - Parameter type: The expected output type. /// - Returns: The output, if the underlying value can be converted to the /// output type, or nil otherwise. @@ -84,6 +91,7 @@ extension AnyRegexOutput { } } +@available(SwiftStdlib 5.7, *) extension AnyRegexOutput { internal init( input: String, elements: C @@ -92,6 +100,7 @@ extension AnyRegexOutput { } } +@available(SwiftStdlib 5.7, *) extension AnyRegexOutput.ElementRepresentation { init(_ element: StructuredCapture) { self.init( @@ -114,18 +123,26 @@ extension AnyRegexOutput.ElementRepresentation { } } +@available(SwiftStdlib 5.7, *) extension AnyRegexOutput: RandomAccessCollection { public struct Element { fileprivate let representation: ElementRepresentation let input: String + /// The range over which a value was captured. `nil` for no-capture. public var range: Range? { representation.bounds } + /// The slice of the input over which a value was captured. `nil` for no-capture. public var substring: Substring? { range.map { input[$0] } } + + /// The captured value, `nil` for no-capture + public var value: Any? { + fatalError() + } } public var startIndex: Int { @@ -152,3 +169,24 @@ extension AnyRegexOutput: RandomAccessCollection { .init(representation: _elements[position], input: input) } } + +@available(SwiftStdlib 5.7, *) +extension Regex.Match where Output == AnyRegexOutput { + /// Creates a type-erased regex match from an existing match. + /// + /// Use this initializer to fit a regex match with strongly typed captures into the + /// use site of a dynamic regex match, i.e. one that was created from a string. + public init(_ match: Regex.Match) { + fatalError("FIXME: Not implemented") + } + + /// Returns a typed match by converting the underlying values to the specified + /// types. + /// + /// - Parameter type: The expected output type. + /// - Returns: A match generic over the output type if the underlying values can be converted to the + /// output type. Returns `nil` otherwise. + public func `as`(_ type: Output.Type) -> Regex.Match? { + fatalError("FIXME: Not implemented") + } +} diff --git a/Sources/_StringProcessing/Regex/Core.swift b/Sources/_StringProcessing/Regex/Core.swift index 265a7868c..d77784df4 100644 --- a/Sources/_StringProcessing/Regex/Core.swift +++ b/Sources/_StringProcessing/Regex/Core.swift @@ -9,22 +9,24 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser /// A type that represents a regular expression. +@available(SwiftStdlib 5.7, *) public protocol RegexComponent { - associatedtype Output - var regex: Regex { get } + associatedtype RegexOutput + var regex: Regex { get } } /// A regex represents a string processing algorithm. /// -/// let regex = try Regex(compiling: "a(.*)b") +/// let regex = try Regex("a(.*)b") /// let match = "cbaxb".firstMatch(of: regex) /// print(match.0) // "axb" /// print(match.1) // "x" /// +@available(SwiftStdlib 5.7, *) public struct Regex: RegexComponent { let program: Program @@ -59,6 +61,7 @@ public struct Regex: RegexComponent { } } +@available(SwiftStdlib 5.7, *) extension Regex { /// A program representation that caches any lowered representation for /// execution. @@ -83,6 +86,7 @@ extension Regex { } } +@available(SwiftStdlib 5.7, *) extension Regex { @_spi(RegexBuilder) public var root: DSLTree.Node { @@ -93,60 +97,4 @@ extension Regex { public init(node: DSLTree.Node) { self.program = Program(tree: .init(node, options: nil)) } - -} - -// MARK: - Primitive regex components - -extension String: RegexComponent { - public typealias Output = Substring - - public var regex: Regex { - .init(node: .quotedLiteral(self)) - } -} - -extension Substring: RegexComponent { - public typealias Output = Substring - - public var regex: Regex { - .init(node: .quotedLiteral(String(self))) - } -} - -extension Character: RegexComponent { - public typealias Output = Substring - - public var regex: Regex { - .init(node: .atom(.char(self))) - } -} - -extension UnicodeScalar: RegexComponent { - public typealias Output = Substring - - public var regex: Regex { - .init(node: .atom(.scalar(self))) - } -} - -// MARK: - Testing - -public struct MockRegexLiteral: RegexComponent { - public typealias MatchValue = Substring - public let regex: Regex - - public init( - _ string: String, - _ syntax: SyntaxOptions = .traditional, - matching: Output.Type = Output.self - ) throws { - regex = Regex(ast: try parse(string, syntax)) - } -} - -public func r( - _ s: String, matching matchType: Output.Type = Output.self -) -> MockRegexLiteral { - try! MockRegexLiteral(s, matching: matchType) } diff --git a/Sources/_StringProcessing/Regex/DSLConsumers.swift b/Sources/_StringProcessing/Regex/DSLConsumers.swift index 8d64f8355..ea46c789b 100644 --- a/Sources/_StringProcessing/Regex/DSLConsumers.swift +++ b/Sources/_StringProcessing/Regex/DSLConsumers.swift @@ -9,18 +9,22 @@ // //===----------------------------------------------------------------------===// -public protocol CustomRegexComponent: RegexComponent { +@available(SwiftStdlib 5.7, *) +public protocol CustomMatchingRegexComponent: RegexComponent { func match( _ input: String, startingAt index: String.Index, in bounds: Range - ) -> (upperBound: String.Index, output: Output)? + ) throws -> (upperBound: String.Index, output: RegexOutput)? } -extension CustomRegexComponent { - public var regex: Regex { - Regex(node: .matcher(.init(Output.self), { input, index, bounds in - match(input, startingAt: index, in: bounds) - })) +@available(SwiftStdlib 5.7, *) +extension CustomMatchingRegexComponent { + public var regex: Regex { + + let node: DSLTree.Node = .matcher(.init(RegexOutput.self), { input, index, bounds in + try match(input, startingAt: index, in: bounds) + }) + return Regex(node: node) } } diff --git a/Sources/_StringProcessing/Regex/DSLTree.swift b/Sources/_StringProcessing/Regex/DSLTree.swift index bd3b37a3d..7b2ecd515 100644 --- a/Sources/_StringProcessing/Regex/DSLTree.swift +++ b/Sources/_StringProcessing/Regex/DSLTree.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser @_spi(RegexBuilder) public struct DSLTree { @@ -56,7 +56,7 @@ extension DSLTree { case quantification( AST.Quantification.Amount, - AST.Quantification.Kind, + QuantificationKind, Node) case customCharacterClass(CustomCharacterClass) @@ -103,12 +103,45 @@ extension DSLTree { } extension DSLTree { + @_spi(RegexBuilder) + public enum QuantificationKind { + /// The default quantification kind, as set by options. + case `default` + /// An explicitly chosen kind, overriding any options. + case explicit(AST.Quantification.Kind) + /// A kind set via syntax, which can be affected by options. + case syntax(AST.Quantification.Kind) + } + @_spi(RegexBuilder) public struct CustomCharacterClass { var members: [Member] var isInverted: Bool + + var containsAny: Bool { + members.contains { member in + switch member { + case .atom(.any): return true + case .custom(let ccc): return ccc.containsAny + default: + return false + } + } + } + + public init(members: [DSLTree.CustomCharacterClass.Member], isInverted: Bool = false) { + self.members = members + self.isInverted = isInverted + } + + public var inverted: CustomCharacterClass { + var result = self + result.isInverted.toggle() + return result + } - enum Member { + @_spi(RegexBuilder) + public enum Member { case atom(Atom) case range(Atom, Atom) case custom(CustomCharacterClass) @@ -141,14 +174,14 @@ extension DSLTree { @_spi(RegexBuilder) public typealias _ConsumerInterface = ( String, Range -) -> String.Index? +) throws -> String.Index? // Type producing consume // TODO: better name @_spi(RegexBuilder) public typealias _MatcherInterface = ( String, String.Index, Range -) -> (String.Index, Any)? +) throws -> (String.Index, Any)? // Character-set (post grapheme segmentation) @_spi(RegexBuilder) @@ -361,3 +394,62 @@ public struct ReferenceID: Hashable, Equatable { Self.counter += 1 } } + +@_spi(RegexBuilder) +public struct CaptureTransform: Hashable, CustomStringConvertible { + public enum Closure { + case failable((Substring) throws -> Any?) + case nonfailable((Substring) throws -> Any) + } + public let resultType: Any.Type + public let closure: Closure + + public init(resultType: Any.Type, closure: Closure) { + self.resultType = resultType + self.closure = closure + } + + public init( + resultType: Any.Type, + _ closure: @escaping (Substring) throws -> Any + ) { + self.init(resultType: resultType, closure: .nonfailable(closure)) + } + + public init( + resultType: Any.Type, + _ closure: @escaping (Substring) throws -> Any? + ) { + self.init(resultType: resultType, closure: .failable(closure)) + } + + public func callAsFunction(_ input: Substring) throws -> Any? { + switch closure { + case .nonfailable(let closure): + let result = try closure(input) + assert(type(of: result) == resultType) + return result + case .failable(let closure): + guard let result = try closure(input) else { + return nil + } + assert(type(of: result) == resultType) + return result + } + } + + public static func == (lhs: CaptureTransform, rhs: CaptureTransform) -> Bool { + unsafeBitCast(lhs.closure, to: (Int, Int).self) == + unsafeBitCast(rhs.closure, to: (Int, Int).self) + } + + public func hash(into hasher: inout Hasher) { + let (fn, ctx) = unsafeBitCast(closure, to: (Int, Int).self) + hasher.combine(fn) + hasher.combine(ctx) + } + + public var description: String { + "" + } +} diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 45d33f03e..a86899041 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -9,6 +9,7 @@ // //===----------------------------------------------------------------------===// +@available(SwiftStdlib 5.7, *) extension Regex { /// The result of matching a regex against a string. /// @@ -29,6 +30,7 @@ extension Regex { } } +@available(SwiftStdlib 5.7, *) extension Regex.Match { /// The produced output from the match operation public var output: Output { @@ -81,18 +83,19 @@ extension Regex.Match { } } -extension RegexComponent { +@available(SwiftStdlib 5.7, *) +extension Regex { /// Match a string in its entirety. /// /// Returns `nil` if no match and throws on abort - public func matchWhole(_ s: String) throws -> Regex.Match? { + public func wholeMatch(in s: String) throws -> Regex.Match? { try _match(s, in: s.startIndex.. Regex.Match? { + public func prefixMatch(in s: String) throws -> Regex.Match? { try _match(s, in: s.startIndex.. Regex.Match? { + public func wholeMatch(in s: Substring) throws -> Regex.Match? { try _match(s.base, in: s.startIndex.. Regex.Match? { + public func prefixMatch(in s: Substring) throws -> Regex.Match? { try _match(s.base, in: s.startIndex.. Regex.Match? { + public func firstMatch(in s: Substring) throws -> Regex.Match? { try _firstMatch(s.base, in: s.startIndex.. Regex.Match? { let executor = Executor(program: regex.program.loweredProgram) - return try executor.match(input, in: inputRange, mode) + return try executor.match(input, in: inputRange, mode) } func _firstMatch( @@ -152,19 +155,32 @@ extension RegexComponent { } } +@available(SwiftStdlib 5.7, *) extension String { - public func matchWhole(_ regex: R) -> Regex.Match? { - try? regex.matchWhole(self) + public func wholeMatch( + of r: R + ) -> Regex.Match? { + try? r.regex.wholeMatch(in: self) } - public func matchPrefix(_ regex: R) -> Regex.Match? { - try? regex.matchPrefix(self) + + public func prefixMatch( + of r: R + ) -> Regex.Match? { + try? r.regex.prefixMatch(in: self) } } + +@available(SwiftStdlib 5.7, *) extension Substring { - public func matchWhole(_ regex: R) -> Regex.Match? { - try? regex.matchWhole(self) + public func wholeMatch( + of r: R + ) -> Regex.Match? { + try? r.regex.wholeMatch(in: self) } - public func matchPrefix(_ regex: R) -> Regex.Match? { - try? regex.matchPrefix(self) + + public func prefixMatch( + of r: R + ) -> Regex.Match? { + try? r.regex.prefixMatch(in: self) } } diff --git a/Sources/_StringProcessing/Regex/Options.swift b/Sources/_StringProcessing/Regex/Options.swift index 04be79c6e..6f38956e7 100644 --- a/Sources/_StringProcessing/Regex/Options.swift +++ b/Sources/_StringProcessing/Regex/Options.swift @@ -9,20 +9,193 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser +@available(SwiftStdlib 5.7, *) extension RegexComponent { - public func caseSensitive(_ isCaseSensitive: Bool) -> Regex { - // The API is "case sensitive = true or false", so as to avoid the - // double negatives inherent in setting "case insensitive" to a Boolean - // value. The internal version of this option, on the other hand, is - // `.caseInsensitive`, derived from the `(?i)` regex literal option. - let sequence = isCaseSensitive - ? AST.MatchingOptionSequence(removing: [.init(.caseInsensitive, location: .fake)]) - : AST.MatchingOptionSequence(adding: [.init(.caseInsensitive, location: .fake)]) + /// Returns a regular expression that ignores casing when matching. + public func ignoresCase(_ ignoresCase: Bool = true) -> Regex { + wrapInOption(.caseInsensitive, addingIf: ignoresCase) + } + + /// Returns a regular expression that only matches ASCII characters as "word + /// characters". + public func asciiOnlyWordCharacters(_ useASCII: Bool = true) -> Regex { + wrapInOption(.asciiOnlyWord, addingIf: useASCII) + } + + /// Returns a regular expression that only matches ASCII characters as digits. + public func asciiOnlyDigits(_ useASCII: Bool = true) -> Regex { + wrapInOption(.asciiOnlyDigit, addingIf: useASCII) + } + + /// Returns a regular expression that only matches ASCII characters as space + /// characters. + public func asciiOnlyWhitespace(_ useASCII: Bool = true) -> Regex { + wrapInOption(.asciiOnlySpace, addingIf: useASCII) + } + + /// Returns a regular expression that only matches ASCII characters when + /// matching character classes. + public func asciiOnlyCharacterClasses(_ useASCII: Bool = true) -> Regex { + wrapInOption(.asciiOnlyPOSIXProps, addingIf: useASCII) + } + + /// Returns a regular expression that uses the specified word boundary algorithm. + public func wordBoundaryKind(_ wordBoundaryKind: RegexWordBoundaryKind) -> Regex { + wrapInOption(.unicodeWordBoundaries, addingIf: wordBoundaryKind == .unicodeLevel2) + } + + /// Returns a regular expression where the start and end of input + /// anchors (`^` and `$`) also match against the start and end of a line. + /// + /// - Parameter dotMatchesNewlines: A Boolean value indicating whether `.` + /// should match a newline character. + public func dotMatchesNewlines(_ dotMatchesNewlines: Bool = true) -> Regex { + wrapInOption(.singleLine, addingIf: dotMatchesNewlines) + } + + /// Returns a regular expression where the start and end of input + /// anchors (`^` and `$`) also match against the start and end of a line. + /// + /// This method corresponds to applying the `m` option in a regular + /// expression literal. For this behavior in the `RegexBuilder` syntax, see + /// ``Anchor.startOfLine``, ``Anchor.endOfLine``, ``Anchor.startOfInput``, + /// and ``Anchor.endOfInput``. + /// + /// - Parameter matchLineEndings: A Boolean value indicating whether `^` and + /// `$` should match the start and end of lines, respectively. + public func anchorsMatchLineEndings(_ matchLineEndings: Bool = true) -> Regex { + wrapInOption(.multiline, addingIf: matchLineEndings) + } + + /// Returns a regular expression where quantifiers are reluctant by default + /// instead of eager. + /// + /// This method corresponds to applying the `U` option in a regular + /// expression literal. + /// + /// - Parameter useReluctantQuantifiers: A Boolean value indicating whether + /// quantifiers should be reluctant by default. + public func reluctantQuantifiers(_ useReluctantQuantifiers: Bool = true) -> Regex { + wrapInOption(.reluctantByDefault, addingIf: useReluctantQuantifiers) + } + + /// Returns a regular expression that matches with the specified semantic + /// level. + /// + /// When matching with grapheme cluster semantics (the default), + /// metacharacters like `.` and `\w`, custom character classes, and character + /// class instances like `.any` match a grapheme cluster when possible, + /// corresponding with the default string representation. In addition, + /// matching with grapheme cluster semantics compares characters using their + /// canonical representation, corresponding with how strings comparison works. + /// + /// When matching with Unicode scalar semantics, metacharacters and character + /// classes always match a single Unicode scalar value, even if that scalar + /// comprises part of a grapheme cluster. + /// + /// These semantic levels can lead to different results, especially when + /// working with strings that have decomposed characters. In the following + /// example, `queRegex` matches any 3-character string that begins with `"q"`. + /// + /// let composed = "qué" + /// let decomposed = "que\u{301}" + /// + /// let queRegex = /^q..$/ + /// + /// print(composed.contains(queRegex)) + /// // Prints "true" + /// print(decomposed.contains(queRegex)) + /// // Prints "true" + /// + /// When using Unicode scalar semantics, however, the regular expression only + /// matches the composed version of the string, because each `.` matches a + /// single Unicode scalar value. + /// + /// let queRegexScalar = queRegex.matchingSemantics(.unicodeScalar) + /// print(composed.contains(queRegexScalar)) + /// // Prints "true" + /// print(decomposed.contains(queRegexScalar)) + /// // Prints "false" + public func matchingSemantics(_ semanticLevel: RegexSemanticLevel) -> Regex { + switch semanticLevel.base { + case .graphemeCluster: + return wrapInOption(.graphemeClusterSemantics, addingIf: true) + case .unicodeScalar: + return wrapInOption(.unicodeScalarSemantics, addingIf: true) + } + } +} + +@available(SwiftStdlib 5.7, *) +/// A semantic level to use during regex matching. +public struct RegexSemanticLevel: Hashable { + internal enum Representation { + case graphemeCluster + case unicodeScalar + } + + internal var base: Representation + + /// Match at the default semantic level of a string, where each matched + /// element is a `Character`. + public static var graphemeCluster: RegexSemanticLevel { + .init(base: .graphemeCluster) + } + + /// Match at the semantic level of a string's `UnicodeScalarView`, where each + /// matched element is a `UnicodeScalar` value. + public static var unicodeScalar: RegexSemanticLevel { + .init(base: .unicodeScalar) + } +} + +@available(SwiftStdlib 5.7, *) +/// A word boundary algorithm to use during regex matching. +public struct RegexWordBoundaryKind: Hashable { + internal enum Representation { + case unicodeLevel1 + case unicodeLevel2 + } + + internal var base: Representation + + /// A word boundary algorithm that implements the "simple word boundary" + /// Unicode recommendation. + /// + /// A simple word boundary is a position in the input between two characters + /// that match `/\w\W/` or `/\W\w/`, or between the start or end of the input + /// and a `\w` character. Word boundaries therefore depend on the option- + /// defined behavior of `\w`. + public static var unicodeLevel1: Self { + .init(base: .unicodeLevel1) + } + + /// A word boundary algorithm that implements the "default word boundary" + /// Unicode recommendation. + /// + /// Default word boundaries use a Unicode algorithm that handles some cases + /// better than simple word boundaries, such as words with internal + /// punctuation, changes in script, and Emoji. + public static var unicodeLevel2: Self { + .init(base: .unicodeLevel2) + } +} + +// MARK: - Helper method + +@available(SwiftStdlib 5.7, *) +extension RegexComponent { + fileprivate func wrapInOption( + _ option: AST.MatchingOption.Kind, + addingIf shouldAdd: Bool) -> Regex + { + let sequence = shouldAdd + ? AST.MatchingOptionSequence(adding: [.init(option, location: .fake)]) + : AST.MatchingOptionSequence(removing: [.init(option, location: .fake)]) return Regex(node: .nonCapturingGroup( .changeMatchingOptions(sequence, isIsolated: false), regex.root)) } } - diff --git a/Sources/_StringProcessing/Utility/ASTBuilder.swift b/Sources/_StringProcessing/Utility/ASTBuilder.swift index 8a9af8111..be9f61517 100644 --- a/Sources/_StringProcessing/Utility/ASTBuilder.swift +++ b/Sources/_StringProcessing/Utility/ASTBuilder.swift @@ -25,7 +25,7 @@ AST. */ -import _RegexParser +@_implementationOnly import _RegexParser func alt(_ asts: [AST.Node]) -> AST.Node { return .alternation( @@ -106,16 +106,16 @@ func negativeLookahead(_ child: AST.Node) -> AST.Node { func negativeLookbehind(_ child: AST.Node) -> AST.Node { group(.negativeLookbehind, child) } -public func nonAtomicLookahead(_ child: AST.Node) -> AST.Node { +func nonAtomicLookahead(_ child: AST.Node) -> AST.Node { group(.nonAtomicLookahead, child) } -public func nonAtomicLookbehind(_ child: AST.Node) -> AST.Node { +func nonAtomicLookbehind(_ child: AST.Node) -> AST.Node { group(.nonAtomicLookbehind, child) } -public func scriptRun(_ child: AST.Node) -> AST.Node { +func scriptRun(_ child: AST.Node) -> AST.Node { group(.scriptRun, child) } -public func atomicScriptRun(_ child: AST.Node) -> AST.Node { +func atomicScriptRun(_ child: AST.Node) -> AST.Node { group(.atomicScriptRun, child) } func changeMatchingOptions( diff --git a/Sources/_StringProcessing/CharacterClass.swift b/Sources/_StringProcessing/_CharacterClassModel.swift similarity index 71% rename from Sources/_StringProcessing/CharacterClass.swift rename to Sources/_StringProcessing/_CharacterClassModel.swift index d44fa9fb2..c9762f00e 100644 --- a/Sources/_StringProcessing/CharacterClass.swift +++ b/Sources/_StringProcessing/_CharacterClassModel.swift @@ -9,13 +9,14 @@ // //===----------------------------------------------------------------------===// -import _RegexParser +@_implementationOnly import _RegexParser // NOTE: This is a model type. We want to be able to get one from // an AST, but this isn't a natural thing to produce in the context // of parsing or to store in an AST -public struct CharacterClass: Hashable { +@_spi(RegexBuilder) +public struct _CharacterClassModel: Hashable { /// The actual character class to match. var cc: Representation @@ -27,7 +28,7 @@ public struct CharacterClass: Hashable { var isInverted: Bool = false // TODO: Split out builtin character classes into their own type? - public enum Representation: Hashable { + public enum Representation: Hashable { /// Any character case any /// Any grapheme cluster @@ -54,29 +55,29 @@ public struct CharacterClass: Hashable { public typealias SetOperator = AST.CustomCharacterClass.SetOp /// A binary set operation that forms a character class component. - public struct SetOperation: Hashable { + public struct SetOperation: Hashable { var lhs: CharacterSetComponent var op: SetOperator var rhs: CharacterSetComponent - public func matches(_ c: Character) -> Bool { + func matches(_ c: Character, with options: MatchingOptions) -> Bool { switch op { case .intersection: - return lhs.matches(c) && rhs.matches(c) + return lhs.matches(c, with: options) && rhs.matches(c, with: options) case .subtraction: - return lhs.matches(c) && !rhs.matches(c) + return lhs.matches(c, with: options) && !rhs.matches(c, with: options) case .symmetricDifference: - return lhs.matches(c) != rhs.matches(c) + return lhs.matches(c, with: options) != rhs.matches(c, with: options) } } } - public enum CharacterSetComponent: Hashable { + public enum CharacterSetComponent: Hashable { case character(Character) case range(ClosedRange) /// A nested character class. - case characterClass(CharacterClass) + case characterClass(_CharacterClassModel) /// A binary set operation of character class components. indirect case setOperation(SetOperation) @@ -87,32 +88,46 @@ public struct CharacterClass: Hashable { .setOperation(.init(lhs: lhs, op: op, rhs: rhs)) } - public func matches(_ character: Character) -> Bool { + func matches(_ character: Character, with options: MatchingOptions) -> Bool { switch self { - case .character(let c): return c == character - case .range(let range): return range.contains(character) + case .character(let c): + if options.isCaseInsensitive { + return c.lowercased() == character.lowercased() + } else { + return c == character + } + case .range(let range): + if options.isCaseInsensitive { + let newLower = range.lowerBound.lowercased() + let newUpper = range.upperBound.lowercased() + // FIXME: Is failing this possible? Is this the right behavior if so? + guard newLower <= newUpper else { return false } + return (newLower...newUpper).contains(character.lowercased()) + } else { + return range.contains(character) + } case .characterClass(let custom): let str = String(character) - return custom.matches(in: str, at: str.startIndex) != nil - case .setOperation(let op): return op.matches(character) + return custom.matches(in: str, at: str.startIndex, with: options) != nil + case .setOperation(let op): return op.matches(character, with: options) } } } - public enum MatchLevel { + enum MatchLevel { /// Match at the extended grapheme cluster level. case graphemeCluster /// Match at the Unicode scalar level. case unicodeScalar } - public var scalarSemantic: Self { + var scalarSemantic: Self { var result = self result.matchLevel = .unicodeScalar return result } - public var graphemeClusterSemantic: Self { + var graphemeClusterSemantic: Self { var result = self result.matchLevel = .graphemeCluster return result @@ -120,7 +135,7 @@ public struct CharacterClass: Hashable { /// Returns an inverted character class if true is passed, otherwise the /// same character class is returned. - public func withInversion(_ invertion: Bool) -> Self { + func withInversion(_ invertion: Bool) -> Self { var copy = self if invertion { copy.isInverted.toggle() @@ -135,21 +150,26 @@ public struct CharacterClass: Hashable { /// Returns the end of the match of this character class in `str`, if /// it matches. - public func matches(in str: String, at i: String.Index) -> String.Index? { + func matches(in str: String, at i: String.Index, with options: MatchingOptions) -> String.Index? { switch matchLevel { case .graphemeCluster: let c = str[i] var matched: Bool switch cc { case .any, .anyGrapheme: matched = true - case .digit: matched = c.isNumber - case .hexDigit: matched = c.isHexDigit + case .digit: + matched = c.isNumber && (c.isASCII || !options.usesASCIIDigits) + case .hexDigit: + matched = c.isHexDigit && (c.isASCII || !options.usesASCIIDigits) case .horizontalWhitespace: fatalError("Not implemented") - case .newlineSequence: matched = c.isNewline + case .newlineSequence: + matched = c.isNewline && (c.isASCII || !options.usesASCIISpaces) case .verticalWhitespace: fatalError("Not implemented") - case .whitespace: matched = c.isWhitespace - case .word: matched = c.isWordCharacter - case .custom(let set): matched = set.any { $0.matches(c) } + case .whitespace: + matched = c.isWhitespace && (c.isASCII || !options.usesASCIISpaces) + case .word: + matched = c.isWordCharacter && (c.isASCII || !options.usesASCIIWord) + case .custom(let set): matched = set.any { $0.matches(c, with: options) } } if isInverted { matched.toggle() @@ -161,13 +181,17 @@ public struct CharacterClass: Hashable { switch cc { case .any: matched = true case .anyGrapheme: fatalError("Not matched in this mode") - case .digit: matched = c.properties.numericType != nil - case .hexDigit: matched = Character(c).isHexDigit + case .digit: + matched = c.properties.numericType != nil && (c.isASCII || !options.usesASCIIDigits) + case .hexDigit: + matched = Character(c).isHexDigit && (c.isASCII || !options.usesASCIIDigits) case .horizontalWhitespace: fatalError("Not implemented") case .newlineSequence: fatalError("Not implemented") case .verticalWhitespace: fatalError("Not implemented") - case .whitespace: matched = c.properties.isWhitespace - case .word: matched = c.properties.isAlphabetic || c == "_" + case .whitespace: + matched = c.properties.isWhitespace && (c.isASCII || !options.usesASCIISpaces) + case .word: + matched = (c.properties.isAlphabetic || c == "_") && (c.isASCII || !options.usesASCIIWord) case .custom: fatalError("Not supported") } if isInverted { @@ -178,10 +202,11 @@ public struct CharacterClass: Hashable { } } -extension CharacterClass: RegexComponent { - public typealias Output = Substring +@available(SwiftStdlib 5.7, *) +extension _CharacterClassModel: RegexComponent { + public typealias RegexOutput = Substring - public var regex: Regex { + public var regex: Regex { guard let ast = self.makeAST() else { fatalError("FIXME: extended AST?") } @@ -189,51 +214,52 @@ extension CharacterClass: RegexComponent { } } -extension RegexComponent where Self == CharacterClass { - public static var any: CharacterClass { +@_spi(RegexBuilder) +extension _CharacterClassModel { + public static var any: _CharacterClassModel { .init(cc: .any, matchLevel: .graphemeCluster) } - public static var anyGrapheme: CharacterClass { + public static var anyGrapheme: _CharacterClassModel { .init(cc: .anyGrapheme, matchLevel: .graphemeCluster) } - public static var whitespace: CharacterClass { + public static var whitespace: _CharacterClassModel { .init(cc: .whitespace, matchLevel: .graphemeCluster) } - public static var digit: CharacterClass { + public static var digit: _CharacterClassModel { .init(cc: .digit, matchLevel: .graphemeCluster) } - public static var hexDigit: CharacterClass { + public static var hexDigit: _CharacterClassModel { .init(cc: .hexDigit, matchLevel: .graphemeCluster) } - public static var horizontalWhitespace: CharacterClass { + public static var horizontalWhitespace: _CharacterClassModel { .init(cc: .horizontalWhitespace, matchLevel: .graphemeCluster) } - public static var newlineSequence: CharacterClass { + public static var newlineSequence: _CharacterClassModel { .init(cc: .newlineSequence, matchLevel: .graphemeCluster) } - public static var verticalWhitespace: CharacterClass { + public static var verticalWhitespace: _CharacterClassModel { .init(cc: .verticalWhitespace, matchLevel: .graphemeCluster) } - public static var word: CharacterClass { + public static var word: _CharacterClassModel { .init(cc: .word, matchLevel: .graphemeCluster) } public static func custom( - _ components: [CharacterClass.CharacterSetComponent] - ) -> CharacterClass { + _ components: [_CharacterClassModel.CharacterSetComponent] + ) -> _CharacterClassModel { .init(cc: .custom(components), matchLevel: .graphemeCluster) } } -extension CharacterClass.CharacterSetComponent: CustomStringConvertible { +extension _CharacterClassModel.CharacterSetComponent: CustomStringConvertible { public var description: String { switch self { case .range(let range): return "" @@ -244,7 +270,7 @@ extension CharacterClass.CharacterSetComponent: CustomStringConvertible { } } -extension CharacterClass.Representation: CustomStringConvertible { +extension _CharacterClassModel.Representation: CustomStringConvertible { public var description: String { switch self { case .any: return "" @@ -261,13 +287,13 @@ extension CharacterClass.Representation: CustomStringConvertible { } } -extension CharacterClass: CustomStringConvertible { +extension _CharacterClassModel: CustomStringConvertible { public var description: String { return "\(isInverted ? "not " : "")\(cc)" } } -extension CharacterClass { +extension _CharacterClassModel { public func makeAST() -> AST.Node? { let inv = isInverted @@ -320,7 +346,7 @@ extension CharacterClass { } extension DSLTree.Node { - var characterClass: CharacterClass? { + var characterClass: _CharacterClassModel? { switch self { case let .customCharacterClass(ccc): return ccc.modelCharacterClass @@ -335,10 +361,10 @@ extension DSLTree.Node { } } -extension CharacterClass { - public func withMatchLevel( - _ level: CharacterClass.MatchLevel - ) -> CharacterClass { +extension _CharacterClassModel { + func withMatchLevel( + _ level: _CharacterClassModel.MatchLevel + ) -> _CharacterClassModel { var cc = self cc.matchLevel = level return cc @@ -346,7 +372,7 @@ extension CharacterClass { } extension DSLTree.Atom { - var characterClass: CharacterClass? { + var characterClass: _CharacterClassModel? { switch self { case let .unconverted(a): return a.characterClass @@ -357,7 +383,7 @@ extension DSLTree.Atom { } extension AST.Atom { - var characterClass: CharacterClass? { + var characterClass: _CharacterClassModel? { switch kind { case let .escaped(b): return b.characterClass @@ -383,7 +409,7 @@ extension AST.Atom { } extension AST.Atom.EscapedBuiltin { - var characterClass: CharacterClass? { + var characterClass: _CharacterClassModel? { switch self { case .decimalDigit: return .digit case .notDecimalDigit: return .digit.inverted @@ -414,9 +440,9 @@ extension AST.Atom.EscapedBuiltin { extension DSLTree.CustomCharacterClass { // TODO: Refactor a bit, and... can we drop this type? - var modelCharacterClass: CharacterClass? { + var modelCharacterClass: _CharacterClassModel? { var result = - Array() + Array<_CharacterClassModel.CharacterSetComponent>() for m in members { switch m { case let .atom(a): @@ -482,12 +508,12 @@ extension DSLTree.CustomCharacterClass { break } } - let cc = CharacterClass.custom(result) + let cc = _CharacterClassModel.custom(result) return isInverted ? cc.inverted : cc } } -extension CharacterClass { +extension _CharacterClassModel { // FIXME: Calling on inverted sets wont be the same as the // inverse of a boundary if at the start or end of the // string. (Think through what we want: do it ourselves or @@ -495,21 +521,22 @@ extension CharacterClass { func isBoundary( _ input: String, at pos: String.Index, - bounds: Range + bounds: Range, + with options: MatchingOptions ) -> Bool { // FIXME: How should we handle bounds? // We probably need two concepts if input.isEmpty { return false } if pos == input.startIndex { - return self.matches(in: input, at: pos) != nil + return self.matches(in: input, at: pos, with: options) != nil } let priorIdx = input.index(before: pos) if pos == input.endIndex { - return self.matches(in: input, at: priorIdx) != nil + return self.matches(in: input, at: priorIdx, with: options) != nil } - let prior = self.matches(in: input, at: priorIdx) != nil - let current = self.matches(in: input, at: pos) != nil + let prior = self.matches(in: input, at: priorIdx, with: options) != nil + let current = self.matches(in: input, at: pos, with: options) != nil return prior != current } diff --git a/Tests/RegexBuilderTests/AlgorithmsTests.swift b/Tests/RegexBuilderTests/AlgorithmsTests.swift index 183d247a7..cf117690a 100644 --- a/Tests/RegexBuilderTests/AlgorithmsTests.swift +++ b/Tests/RegexBuilderTests/AlgorithmsTests.swift @@ -13,19 +13,22 @@ import XCTest import _StringProcessing @testable import RegexBuilder +@available(SwiftStdlib 5.7, *) class RegexConsumerTests: XCTestCase { - func testMatches() { - let regex = Capture(OneOrMore(.digit)) { 2 * Int($0)! } - let str = "foo 160 bar 99 baz" - XCTAssertEqual(str.matches(of: regex).map(\.result.1), [320, 198]) - } + // FIXME: enable this test when we update the return type of `matches(of:)` + // when SE-0346 is available + // func testMatches() { + // let regex = Capture(OneOrMore(.digit)) { 2 * Int($0)! } + // let str = "foo 160 bar 99 baz" + // XCTAssertEqual(str.matches(of: regex).map(\.result.1), [320, 198]) + // } func testMatchReplace() { func replaceTest( _ regex: R, input: String, result: String, - _ replace: (_MatchResult>) -> String, + _ replace: (Regex.Match) -> String, file: StaticString = #file, line: UInt = #line ) { @@ -38,13 +41,13 @@ class RegexConsumerTests: XCTestCase { int, input: "foo 160 bar 99 baz", result: "foo 240 bar 143 baz", - { match in String(match.result.1, radix: 8) }) + { match in String(match.output.1, radix: 8) }) replaceTest( Regex { int; "+"; int }, input: "9+16, 0+3, 5+5, 99+1", result: "25, 3, 10, 100", - { match in "\(match.result.1 + match.result.2)" }) + { match in "\(match.output.1 + match.output.2)" }) // TODO: Need to support capture history // replaceTest( @@ -57,6 +60,6 @@ class RegexConsumerTests: XCTestCase { Regex { int; "x"; int; Optionally { "x"; int } }, input: "2x3 5x4x3 6x0 1x2x3x4", result: "6 60 0 6x4", - { match in "\(match.result.1 * match.result.2 * (match.result.3 ?? 1))" }) + { match in "\(match.output.1 * match.output.2 * (match.output.3 ?? 1))" }) } } diff --git a/Tests/RegexBuilderTests/CustomTests.swift b/Tests/RegexBuilderTests/CustomTests.swift index 7be95c28c..0a7d6fc59 100644 --- a/Tests/RegexBuilderTests/CustomTests.swift +++ b/Tests/RegexBuilderTests/CustomTests.swift @@ -14,8 +14,8 @@ import _StringProcessing @testable import RegexBuilder // A nibbler processes a single character from a string -private protocol Nibbler: CustomRegexComponent { - func nibble(_: Character) -> Output? +private protocol Nibbler: CustomMatchingRegexComponent { + func nibble(_: Character) -> RegexOutput? } extension Nibbler { @@ -24,7 +24,7 @@ extension Nibbler { _ input: String, startingAt index: String.Index, in bounds: Range - ) -> (upperBound: String.Index, output: Output)? { + ) throws -> (upperBound: String.Index, output: RegexOutput)? { guard index != bounds.upperBound, let res = nibble(input[index]) else { return nil } @@ -35,7 +35,7 @@ extension Nibbler { // A number nibbler private struct Numbler: Nibbler { - typealias Output = Int + typealias RegexOutput = Int func nibble(_ c: Character) -> Int? { c.wholeNumberValue } @@ -43,12 +43,75 @@ private struct Numbler: Nibbler { // An ASCII value nibbler private struct Asciibbler: Nibbler { - typealias Output = UInt8 + typealias RegexOutput = UInt8 func nibble(_ c: Character) -> UInt8? { c.asciiValue } } +private struct IntParser: CustomMatchingRegexComponent { + struct ParseError: Error, Hashable {} + typealias RegexOutput = Int + func match(_ input: String, + startingAt index: String.Index, + in bounds: Range + ) throws -> (upperBound: String.Index, output: Int)? { + guard index != bounds.upperBound else { return nil } + + let r = Regex { + Capture(OneOrMore(.digit)) { Int($0) } + } + + guard let match = input[index.. + ) throws -> (upperBound: String.Index, output: Currency)? { + + guard index != bounds.upperBound else { return nil } + + let substr = input[index..( let result: Match? switch call { case .match: - result = input.matchWhole(regex)?.output + result = input.wholeMatch(of: regex)?.output case .firstMatch: - result = input.firstMatch(of: regex)?.result + result = input.firstMatch(of: regex)?.output } XCTAssertEqual(result, match) } @@ -120,9 +183,9 @@ class CustomRegexComponentTests: XCTestCase { return } - XCTAssertEqual(res3.match, "123") - XCTAssertEqual(res3.result.0, "123") - XCTAssertEqual(res3.result.1, "123") + XCTAssertEqual(res3.range, "ab123c".index(atOffset: 2)..<"ab123c".index(atOffset: 5)) + XCTAssertEqual(res3.output.0, "123") + XCTAssertEqual(res3.output.1, "123") let regex4 = Regex { OneOrMore { @@ -135,7 +198,274 @@ class CustomRegexComponentTests: XCTestCase { return } - XCTAssertEqual(res4.result.0, "123") - XCTAssertEqual(res4.result.1, 3) + XCTAssertEqual(res4.output.0, "123") + XCTAssertEqual(res4.output.1, 3) + } + + func testRegexAbort() { + + enum Radix: Hashable { + case dot + case comma + } + struct Abort: Error, Hashable {} + + let hexRegex = Regex { + Capture { OneOrMore(.hexDigit) } + TryCapture { CharacterClass.any } transform: { c -> Radix? in + switch c { + case ".": return Radix.dot + case ",": return Radix.comma + case "❗️": + // Malicious! Toxic levels of emphasis detected. + throw Abort() + default: + // Not a radix + return nil + } + } + Capture { OneOrMore(.hexDigit) } + } + // hexRegex: Regex<(Substring, Substring, Radix?, Substring)> + // TODO: Why is Radix optional? + + do { + guard let m = try hexRegex.wholeMatch(in: "123aef.345") else { + XCTFail() + return + } + XCTAssertEqual(m.0, "123aef.345") + XCTAssertEqual(m.1, "123aef") + XCTAssertEqual(m.2, .dot) + XCTAssertEqual(m.3, "345") + } catch { + XCTFail() + } + + do { + _ = try hexRegex.wholeMatch(in: "123aef❗️345") + XCTFail() + } catch let e as Abort { + XCTAssertEqual(e, Abort()) + } catch { + XCTFail() + } + + struct Poison: Error, Hashable {} + + let addressRegex = Regex { + "0x" + Capture(Repeat(.hexDigit, count: 8)) { hex -> Int in + let i = Int(hex, radix: 16)! + if i == 0xdeadbeef { + throw Poison() + } + return i + } + } + + do { + guard let m = try addressRegex.wholeMatch(in: "0x1234567f") else { + XCTFail() + return + } + XCTAssertEqual(m.0, "0x1234567f") + XCTAssertEqual(m.1, 0x1234567f) + } catch { + XCTFail() + } + + do { + _ = try addressRegex.wholeMatch(in: "0xdeadbeef") + XCTFail() + } catch let e as Poison { + XCTAssertEqual(e, Poison()) + } catch { + XCTFail() + } + + + } + + func testCustomRegexThrows() { + + func customTest( + _ regex: Regex, + _ tests: (input: String, match: Match?, expectError: E?)..., + file: StaticString = #file, + line: UInt = #line + ) { + for (input, match, expectError) in tests { + do { + let result = try regex.wholeMatch(in: input)?.output + XCTAssertEqual(result, match) + } catch let e as E { + XCTAssertEqual(e, expectError) + } catch { + XCTFail() + } + } + } + + func customTest( + _ regex: Regex, + _ tests: (input: String, match: Match?, expectError1: Error1?, expectError2: Error2?)..., + file: StaticString = #file, + line: UInt = #line + ) { + for (input, match, expectError1, expectError2) in tests { + do { + let result = try regex.wholeMatch(in: input)?.output + XCTAssertEqual(result, match) + } catch let e as Error1 { + XCTAssertEqual(e, expectError1, input, file: file, line: line) + } catch let e as Error2 { + XCTAssertEqual(e, expectError2, input, file: file, line: line) + } catch { + XCTFail("caught error: \(error.localizedDescription)") + } + } + } + + func customTest( + _ regex: Regex<(Substring, Capture)>, + _ tests: (input: String, match: (Substring, Capture)?, expectError1: Error1?, expectError2: Error2?)..., + file: StaticString = #file, + line: UInt = #line + ) { + for (input, match, expectError1, expectError2) in tests { + do { + let result = try regex.wholeMatch(in: input)?.output + XCTAssertEqual(result?.0, match?.0, file: file, line: line) + XCTAssertEqual(result?.1, match?.1, file: file, line: line) + } catch let e as Error1 { + XCTAssertEqual(e, expectError1, input, file: file, line: line) + } catch let e as Error2 { + XCTAssertEqual(e, expectError2, input, file: file, line: line) + } catch { + XCTFail("caught error: \(error.localizedDescription)") + } + } + } + + func customTest( + _ regex: Regex<(Substring, Capture1, Capture2)>, + _ tests: (input: String, match: (Substring, Capture1, Capture2)?, expectError1: Error1?, expectError2: Error2?)..., + file: StaticString = #file, + line: UInt = #line + ) { + for (input, match, expectError1, expectError2) in tests { + do { + let result = try regex.wholeMatch(in: input)?.output + XCTAssertEqual(result?.0, match?.0, file: file, line: line) + XCTAssertEqual(result?.1, match?.1, file: file, line: line) + XCTAssertEqual(result?.2, match?.2, file: file, line: line) + } catch let e as Error1 { + XCTAssertEqual(e, expectError1, input, file: file, line: line) + } catch let e as Error2 { + XCTAssertEqual(e, expectError2, input, file: file, line: line) + } catch { + XCTFail("caught error: \(error.localizedDescription)") + } + } + } + + // No capture, one error + customTest( + Regex { + IntParser() + }, + ("zzz", nil, IntParser.ParseError()), + ("x10x", nil, IntParser.ParseError()), + ("30", 30, nil) + ) + + customTest( + Regex { + CurrencyParser() + }, + ("USD", .usd, nil), + ("NTD", .ntd, nil), + ("NTD USD", nil, nil), + ("DEM", nil, CurrencyParser.ParseError.deprecated), + ("XXX", nil, CurrencyParser.ParseError.unrecognized) + ) + + // No capture, two errors + customTest( + Regex { + IntParser() + " " + IntParser() + }, + ("20304 100", "20304 100", nil, nil), + ("20304.445 200", nil, IntParser.ParseError(), nil), + ("20304 200.123", nil, nil, IntParser.ParseError()), + ("20304.445 200.123", nil, IntParser.ParseError(), IntParser.ParseError()) + ) + + customTest( + Regex { + CurrencyParser() + IntParser() + }, + ("USD100", "USD100", nil, nil), + ("XXX100", nil, CurrencyParser.ParseError.unrecognized, nil), + ("USD100.000", nil, nil, IntParser.ParseError()), + ("XXX100.0000", nil, CurrencyParser.ParseError.unrecognized, IntParser.ParseError()) + ) + + // One capture, two errors: One error is thrown from inside a capture, + // while the other one is thrown from outside + customTest( + Regex { + Capture { CurrencyParser() } + IntParser() + }, + ("USD100", ("USD100", .usd), nil, nil), + ("NTD305.5", nil, nil, IntParser.ParseError()), + ("DEM200", ("DEM200", .dem), CurrencyParser.ParseError.deprecated, nil), + ("XXX", nil, CurrencyParser.ParseError.unrecognized, IntParser.ParseError()) + ) + + customTest( + Regex { + CurrencyParser() + Capture { IntParser() } + }, + ("USD100", ("USD100", 100), nil, nil), + ("NTD305.5", nil, nil, IntParser.ParseError()), + ("DEM200", ("DEM200", 200), CurrencyParser.ParseError.deprecated, nil), + ("XXX", nil, CurrencyParser.ParseError.unrecognized, IntParser.ParseError()) + ) + + // One capture, two errors: Both errors are thrown from inside the capture + customTest( + Regex { + Capture { + CurrencyParser() + IntParser() + } + }, + ("USD100", ("USD100", "USD100"), nil, nil), + ("NTD305.5", nil, nil, IntParser.ParseError()), + ("DEM200", ("DEM200", "DEM200"), CurrencyParser.ParseError.deprecated, nil), + ("XXX", nil, CurrencyParser.ParseError.unrecognized, IntParser.ParseError()) + ) + + // Two captures, two errors: Different erros are thrown from inside captures + customTest( + Regex { + Capture(CurrencyParser()) + Capture(IntParser()) + }, + ("USD100", ("USD100", .usd, 100), nil, nil), + ("NTD500", ("NTD500", .ntd, 500), nil, nil), + ("XXX20", nil, CurrencyParser.ParseError.unrecognized, IntParser.ParseError()), + ("DEM500", nil, CurrencyParser.ParseError.deprecated, nil), + ("DEM500.345", nil, CurrencyParser.ParseError.deprecated, IntParser.ParseError()), + ("NTD100.345", nil, nil, IntParser.ParseError()) + ) + } } diff --git a/Tests/RegexBuilderTests/MotivationTests.swift b/Tests/RegexBuilderTests/MotivationTests.swift index 882ba6448..22e790e2d 100644 --- a/Tests/RegexBuilderTests/MotivationTests.swift +++ b/Tests/RegexBuilderTests/MotivationTests.swift @@ -139,7 +139,7 @@ private func processWithRuntimeDynamicRegex( _ line: String ) -> Transaction? { // FIXME: Shouldn't this init throw? - let regex = try! Regex(compiling: pattern) + let regex = try! Regex(pattern) // guard let result = line.match(regex) else { return nil } // @@ -156,7 +156,7 @@ private func processWithRuntimeDynamicRegex( @available(macOS 12.0, *) private func processWithRuntimeStaticRegex(_ line: String) -> Transaction? { let regex: Regex<(Substring, Substring, Substring, Substring, Substring)> - = try! Regex(compiling: pattern) + = try! Regex(pattern) return process(line, using: regex) } @@ -199,7 +199,7 @@ private func process( _ line: String, using regex: Regex<(Substring, Substring, Substring, Substring, Substring)> ) -> Transaction? { - guard let output = try? regex.matchWhole(line), + guard let output = try? regex.wholeMatch(in: line), let kind = Transaction.Kind(output.1) else { return nil diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift index 50358734d..03fc21d49 100644 --- a/Tests/RegexBuilderTests/RegexDSLTests.swift +++ b/Tests/RegexBuilderTests/RegexDSLTests.swift @@ -24,14 +24,14 @@ class RegexDSLTests: XCTestCase { ) throws { let regex = content() for (input, maybeExpectedCaptures) in tests { - let maybeMatch = input.matchWhole(regex) + let maybeMatch = input.wholeMatch(of: regex) if let expectedCaptures = maybeExpectedCaptures { let match = try XCTUnwrap(maybeMatch, file: file, line: line) XCTAssertTrue( - type(of: regex).Output.self == MatchType.self, + type(of: regex).RegexOutput.self == MatchType.self, """ Expected match type: \(MatchType.self) - Actual match type: \(type(of: regex).Output.self) + Actual match type: \(type(of: regex).RegexOutput.self) """) let captures = try XCTUnwrap(match.output as? MatchType, file: file, line: line) XCTAssertTrue( @@ -51,13 +51,13 @@ class RegexDSLTests: XCTestCase { TryCapture("1") { Int($0) } // Int } // Assert the inferred capture type. - let _: (Substring, Substring, Int).Type = type(of: regex).Output.self - let maybeMatch = "ab1".matchWhole(regex) + let _: (Substring, Substring, Int).Type = type(of: regex).RegexOutput.self + let maybeMatch = "ab1".wholeMatch(of: regex) let match = try XCTUnwrap(maybeMatch) XCTAssertTrue(match.output == ("ab1", "b", 1)) let substring = "ab1"[...] - let substringMatch = try XCTUnwrap(substring.matchWhole(regex)) + let substringMatch = try XCTUnwrap(substring.wholeMatch(of: regex)) XCTAssertTrue(match.output == substringMatch.output) } @@ -70,10 +70,63 @@ class RegexDSLTests: XCTestCase { Capture(.whitespace) // Substring Capture("c") // Substring } + + try _testDSLCaptures( + ("abc1def2", "abc1def2"), + matchType: Substring.self, ==) + { + // First group + OneOrMore { + CharacterClass("a"..."z", .digit) + } + + // Second group + OneOrMore { + ChoiceOf { + "a"..."z" + CharacterClass.hexDigit + } + } + } + + try _testDSLCaptures( + ("abc1def2", ("abc1def2", "abc1")), + matchType: (Substring, Substring).self, ==) + { + Capture { + OneOrMore(.digit.inverted) + ("a"..."z").inverted + } + + OneOrMore { + CharacterClass.whitespace.inverted + } + } + } + + func testCharacterClassOperations() throws { + try _testDSLCaptures( + ("bcdefn1a", "bcdefn1a"), + ("nbcdef1a", nil), // fails symmetric difference lookahead + ("abcdef1a", nil), // fails union + ("bcdef3a", nil), // fails subtraction + ("bcdef1z", nil), // fails intersection + matchType: Substring.self, ==) + { + let disallowedChars = CharacterClass.hexDigit + .symmetricDifference("a"..."z") + Lookahead(disallowedChars, negative: true) // No: 0-9 + g-z + + OneOrMore(("b"..."g").union("d"..."n")) // b-n + + CharacterClass.digit.subtracting("3"..."9") // 1, 2, non-ascii digits + + CharacterClass.hexDigit.intersection("a"..."z") // a-f + } } func testMatchResultDotZeroWithoutCapture() throws { - let match = try XCTUnwrap("aaa".matchWhole { OneOrMore { "a" } }) + let match = try XCTUnwrap("aaa".wholeMatch { OneOrMore { "a" } }) XCTAssertEqual(match.0, "aaa") } @@ -82,8 +135,8 @@ class RegexDSLTests: XCTestCase { let regex = ChoiceOf { "aaa" } - XCTAssertTrue("aaa".matchWhole(regex)?.output == "aaa") - XCTAssertNil("aab".matchWhole(regex)?.output) + XCTAssertTrue("aaa".wholeMatch(of: regex)?.output == "aaa") + XCTAssertNil("aab".wholeMatch(of: regex)?.output) } do { let regex = ChoiceOf { @@ -91,10 +144,10 @@ class RegexDSLTests: XCTestCase { "bbb" "ccc" } - XCTAssertTrue("aaa".matchWhole(regex)?.output == "aaa") - XCTAssertNil("aab".matchWhole(regex)?.output) - XCTAssertTrue("bbb".matchWhole(regex)?.output == "bbb") - XCTAssertTrue("ccc".matchWhole(regex)?.output == "ccc") + XCTAssertTrue("aaa".wholeMatch(of: regex)?.output == "aaa") + XCTAssertNil("aab".wholeMatch(of: regex)?.output) + XCTAssertTrue("bbb".wholeMatch(of: regex)?.output == "bbb") + XCTAssertTrue("ccc".wholeMatch(of: regex)?.output == "ccc") } do { let regex = Regex { @@ -109,7 +162,7 @@ class RegexDSLTests: XCTestCase { } } XCTAssertTrue( - try XCTUnwrap("abc".matchWhole(regex)?.output) == ("abc", "c")) + try XCTUnwrap("abc".wholeMatch(of: regex)?.output) == ("abc", "c")) } do { let regex = ChoiceOf { @@ -117,18 +170,18 @@ class RegexDSLTests: XCTestCase { "bbb" "ccc" } - XCTAssertTrue("aaa".matchWhole(regex)?.output == "aaa") - XCTAssertNil("aab".matchWhole(regex)?.output) - XCTAssertTrue("bbb".matchWhole(regex)?.output == "bbb") - XCTAssertTrue("ccc".matchWhole(regex)?.output == "ccc") + XCTAssertTrue("aaa".wholeMatch(of: regex)?.output == "aaa") + XCTAssertNil("aab".wholeMatch(of: regex)?.output) + XCTAssertTrue("bbb".wholeMatch(of: regex)?.output == "bbb") + XCTAssertTrue("ccc".wholeMatch(of: regex)?.output == "ccc") } do { let regex = ChoiceOf { Capture("aaa") } XCTAssertTrue( - try XCTUnwrap("aaa".matchWhole(regex)?.output) == ("aaa", "aaa")) - XCTAssertNil("aab".matchWhole(regex)?.output) + try XCTUnwrap("aaa".wholeMatch(of: regex)?.output) == ("aaa", "aaa")) + XCTAssertNil("aab".wholeMatch(of: regex)?.output) } do { let regex = ChoiceOf { @@ -137,12 +190,12 @@ class RegexDSLTests: XCTestCase { Capture("ccc") } XCTAssertTrue( - try XCTUnwrap("aaa".matchWhole(regex)?.output) == ("aaa", "aaa", nil, nil)) + try XCTUnwrap("aaa".wholeMatch(of: regex)?.output) == ("aaa", "aaa", nil, nil)) XCTAssertTrue( - try XCTUnwrap("bbb".matchWhole(regex)?.output) == ("bbb", nil, "bbb", nil)) + try XCTUnwrap("bbb".wholeMatch(of: regex)?.output) == ("bbb", nil, "bbb", nil)) XCTAssertTrue( - try XCTUnwrap("ccc".matchWhole(regex)?.output) == ("ccc", nil, nil, "ccc")) - XCTAssertNil("aab".matchWhole(regex)?.output) + try XCTUnwrap("ccc".wholeMatch(of: regex)?.output) == ("ccc", nil, nil, "ccc")) + XCTAssertNil("aab".wholeMatch(of: regex)?.output) } } @@ -175,7 +228,7 @@ class RegexDSLTests: XCTestCase { matchType: Substring.self, ==) { OneOrMore { "abc" - }.caseSensitive(false) + }.ignoresCase(true) } // Multiple options on one component wrap successively, but do not @@ -189,8 +242,8 @@ class RegexDSLTests: XCTestCase { OneOrMore { "abc" } - .caseSensitive(false) - .caseSensitive(true) + .ignoresCase(true) + .ignoresCase(false) } // An option on an outer component doesn't override an option set on an @@ -204,10 +257,64 @@ class RegexDSLTests: XCTestCase { ("abcdeABCdeaBcde", "abcdeABCdeaBcde"), matchType: Substring.self, ==) { OneOrMore { - "abc".caseSensitive(false) + "abc".ignoresCase(true) Optionally("de") } - .caseSensitive(true) + .ignoresCase(false) + } + +#if os(macOS) + try XCTExpectFailure("Implement level 2 word boundaries") { + try _testDSLCaptures( + ("can't stop won't stop", ("can't stop won't stop", "can't", "won")), + matchType: (Substring, Substring, Substring).self, ==) { + Capture { + OneOrMore(.word) + Anchor.wordBoundary + } + OneOrMore(.any, .reluctantly) + "stop" + " " + + Capture { + OneOrMore(.word) + Anchor.wordBoundary + } + .wordBoundaryKind(.unicodeLevel1) + OneOrMore(.any, .reluctantly) + "stop" + } + } +#endif + + try _testDSLCaptures( + ("abcdef123", ("abcdef123", "a", "123")), + matchType: (Substring, Substring, Substring).self, ==) { + Capture { + // Reluctant behavior due to option + OneOrMore(.anyOf("abcd")) + .reluctantQuantifiers() + } + ZeroOrMore("a"..."z") + + Capture { + // Eager behavior due to explicit parameter, despite option + OneOrMore(.digit, .eagerly) + .reluctantQuantifiers() + } + ZeroOrMore(.digit) + } + + try _testDSLCaptures( + ("abcdefg", ("abcdefg", "abcdefg")), + ("abcdéfg", ("abcdéfg", "abcd")), + matchType: (Substring, Substring).self, ==) { + Capture { + OneOrMore(.word) + } + .asciiOnlyWordCharacters() + + ZeroOrMore(.any) } } @@ -216,32 +323,44 @@ class RegexDSLTests: XCTestCase { ("abc1def2", ("abc1def2", "2")), matchType: (Substring, Substring).self, ==) { - OneOrMore { - OneOrMore(.word) - Capture(.digit) - } + OneOrMore(.word) + Capture(.digit) + ZeroOrMore(.any) } try _testDSLCaptures( - ("abc1def2", ("abc1def2", "2")), + ("abc1def2", ("abc1def2", "1")), matchType: (Substring, Substring).self, ==) { - OneOrMore { - OneOrMore(.word, .reluctantly) - Capture(.digit) - } + OneOrMore(.word, .reluctantly) + Capture(.digit) + ZeroOrMore(.any) } - + +#if os(macOS) + try XCTExpectFailure("'relucantCaptures()' API should only affect regex literals") { + try _testDSLCaptures( + ("abc1def2", ("abc1def2", "2")), + matchType: (Substring, Substring).self, ==) + { + Regex { + OneOrMore(.word) + Capture(.digit) + ZeroOrMore(.any) + }.reluctantQuantifiers() + } + } +#endif + try _testDSLCaptures( - ("abc1def2", ("abc1def2", "2")), + ("abc1def2", ("abc1def2", "1")), matchType: (Substring, Substring).self, ==) { - OneOrMore { - OneOrMore(.reluctantly) { - .word - } - Capture(.digit) + OneOrMore(.reluctantly) { + .word } + Capture(.digit) + ZeroOrMore(.any) } try _testDSLCaptures( @@ -340,9 +459,9 @@ class RegexDSLTests: XCTestCase { // void. let regex = ZeroOrMore(.digit) // Assert the inferred capture type. - let _: Substring.Type = type(of: regex).Output.self + let _: Substring.Type = type(of: regex).RegexOutput.self let input = "123123" - let match = try XCTUnwrap(input.matchWhole(regex)?.output) + let match = try XCTUnwrap(input.wholeMatch(of: regex)?.output) XCTAssertTrue(match == input) } @@ -389,7 +508,7 @@ class RegexDSLTests: XCTestCase { } } let _: (Substring, Substring, Substring).Type - = type(of: regex1).Output.self + = type(of: regex1).RegexOutput.self let regex2 = Regex { OneOrMore("a") Capture { @@ -400,7 +519,7 @@ class RegexDSLTests: XCTestCase { } } let _: (Substring, Substring, Int?).Type - = type(of: regex2).Output.self + = type(of: regex2).RegexOutput.self let regex3 = Regex { OneOrMore("a") Capture { @@ -412,7 +531,7 @@ class RegexDSLTests: XCTestCase { } } let _: (Substring, Substring, Int, Double?).Type - = type(of: regex3).Output.self + = type(of: regex3).RegexOutput.self let regex4 = Regex { OneOrMore("a") Capture { @@ -426,7 +545,7 @@ class RegexDSLTests: XCTestCase { } let _: ( Substring, Substring, Substring, Substring, Substring?).Type - = type(of: regex4).Output.self + = type(of: regex4).RegexOutput.self } func testUnicodeScalarPostProcessing() throws { @@ -465,11 +584,11 @@ class RegexDSLTests: XCTestCase { } // Assert the inferred capture type. - let _: (Substring, Substring).Type = type(of: unicodeData).Output.self + let _: (Substring, Substring).Type = type(of: unicodeData).RegexOutput.self let unicodeLine = "1BCA0..1BCA3 ; Control # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP" - let match = try XCTUnwrap(unicodeLine.matchWhole(unicodeData)) + let match = try XCTUnwrap(unicodeLine.wholeMatch(of: unicodeData)) XCTAssertEqual(match.0, Substring(unicodeLine)) XCTAssertEqual(match.1, "Control") } @@ -500,8 +619,8 @@ class RegexDSLTests: XCTestCase { typealias ExpectedMatch = ( Substring, Unicode.Scalar?, Unicode.Scalar??, Substring ) - let _: ExpectedMatch.Type = type(of: regexWithCapture).Output.self - let maybeMatchResult = line.matchWhole(regexWithCapture) + let _: ExpectedMatch.Type = type(of: regexWithCapture).RegexOutput.self + let maybeMatchResult = line.wholeMatch(of: regexWithCapture) let matchResult = try XCTUnwrap(maybeMatchResult) let (wholeMatch, lower, upper, propertyString) = matchResult.output XCTAssertEqual(wholeMatch, Substring(line)) @@ -535,8 +654,8 @@ class RegexDSLTests: XCTestCase { typealias ExpectedMatch = ( Substring, Unicode.Scalar, Unicode.Scalar?, Substring ) - let _: ExpectedMatch.Type = type(of: regexWithTryCapture).Output.self - let maybeMatchResult = line.matchWhole(regexWithTryCapture) + let _: ExpectedMatch.Type = type(of: regexWithTryCapture).RegexOutput.self + let maybeMatchResult = line.wholeMatch(of: regexWithTryCapture) let matchResult = try XCTUnwrap(maybeMatchResult) let (wholeMatch, lower, upper, propertyString) = matchResult.output XCTAssertEqual(wholeMatch, Substring(line)) @@ -546,10 +665,10 @@ class RegexDSLTests: XCTestCase { } do { - let regexLiteral = try MockRegexLiteral( - #"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+).*"#, - matching: (Substring, Substring, Substring?, Substring).self) - let maybeMatchResult = line.matchWhole(regexLiteral) + let regexLiteral = try Regex( + #"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+).*"#, + as: (Substring, Substring, Substring?, Substring).self) + let maybeMatchResult = line.wholeMatch(of: regexLiteral) let matchResult = try XCTUnwrap(maybeMatchResult) let (wholeMatch, lower, upper, propertyString) = matchResult.output XCTAssertEqual(wholeMatch, Substring(line)) @@ -561,21 +680,21 @@ class RegexDSLTests: XCTestCase { func testDynamicCaptures() throws { do { - let regex = try Regex(compiling: "aabcc.") + let regex = try Regex("aabcc.") let line = "aabccd" - let match = try XCTUnwrap(line.matchWhole(regex)) + let match = try XCTUnwrap(line.wholeMatch(of: regex)) XCTAssertEqual(match.0, line[...]) let output = match.output XCTAssertEqual(output[0].substring, line[...]) } do { let regex = try Regex( - compiling: #"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+).*"#) + #"([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+).*"#) let line = """ A6F0..A6F1 ; Extend # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM \ COMBINING MARK TUKWENTIS """ - let match = try XCTUnwrap(line.matchWhole(regex)) + let match = try XCTUnwrap(line.wholeMatch(of: regex)) XCTAssertEqual(match.0, line[...]) let output = match.output XCTAssertEqual(output[0].substring, line[...]) @@ -640,7 +759,7 @@ class RegexDSLTests: XCTestCase { } } let input = "abc#41#42abc#42#42" - let result = try XCTUnwrap(input.matchWhole(regex)) + let result = try XCTUnwrap(input.wholeMatch(of: regex)) XCTAssertEqual(result[a], "abc") XCTAssertEqual(result[b], 42) } @@ -678,13 +797,13 @@ class RegexDSLTests: XCTestCase { var patch: Int var dev: String? } - struct SemanticVersionParser: CustomRegexComponent { - typealias Output = SemanticVersion + struct SemanticVersionParser: CustomMatchingRegexComponent { + typealias RegexOutput = SemanticVersion func match( _ input: String, startingAt index: String.Index, in bounds: Range - ) -> (upperBound: String.Index, output: SemanticVersion)? { + ) throws -> (upperBound: String.Index, output: SemanticVersion)? { let regex = Regex { TryCapture(OneOrMore(.digit)) { Int($0) } "." @@ -704,23 +823,23 @@ class RegexDSLTests: XCTestCase { else { return nil } let result = SemanticVersion( - major: match.result.1, - minor: match.result.2, - patch: match.result.3 ?? 0, - dev: match.result.4.map(String.init)) + major: match.output.1, + minor: match.output.2, + patch: match.output.3 ?? 0, + dev: match.output.4.map(String.init)) return (match.range.upperBound, result) } } - + let versions = [ ("1.0", SemanticVersion(major: 1, minor: 0, patch: 0)), ("1.0.1", SemanticVersion(major: 1, minor: 0, patch: 1)), ("12.100.5-dev", SemanticVersion(major: 12, minor: 100, patch: 5, dev: "dev")), ] - + let parser = SemanticVersionParser() for (str, version) in versions { - XCTAssertEqual(str.matchWhole(parser)?.output, version) + XCTAssertEqual(str.wholeMatch(of: parser)?.output, version) } } } diff --git a/Tests/RegexTests/AlgorithmsTests.swift b/Tests/RegexTests/AlgorithmsTests.swift index bc80746c6..5c3c34f89 100644 --- a/Tests/RegexTests/AlgorithmsTests.swift +++ b/Tests/RegexTests/AlgorithmsTests.swift @@ -32,21 +32,13 @@ class RegexConsumerTests: XCTestCase { _ expected: [Range], file: StaticString = #file, line: UInt = #line ) { - let regex = try! Regex(compiling: regex) + let regex = try! Regex(regex) - let actualSeq: [Range] = string[...].ranges(of: regex).map { - let start = string.offset(ofIndex: $0.lowerBound) - let end = string.offset(ofIndex: $0.upperBound) - return start..] = string[...].ranges(of: regex).map(string.offsets(of:)) XCTAssertEqual(actualSeq, expected, file: file, line: line) // `IndexingIterator` tests the collection conformance - let actualCol: [Range] = string[...].ranges(of: regex)[...].map { - let start = string.offset(ofIndex: $0.lowerBound) - let end = string.offset(ofIndex: $0.upperBound) - return start..] = string[...].ranges(of: regex)[...].map(string.offsets(of:)) XCTAssertEqual(actualCol, expected, file: file, line: line) } @@ -77,7 +69,7 @@ class RegexConsumerTests: XCTestCase { _ expected: [Substring], file: StaticString = #file, line: UInt = #line ) { - let regex = try! Regex(compiling: regex) + let regex = try! Regex(regex) let actual = Array(string.split(by: regex)) XCTAssertEqual(actual, expected, file: file, line: line) } @@ -97,7 +89,7 @@ class RegexConsumerTests: XCTestCase { _ expected: String, file: StaticString = #file, line: UInt = #line ) { - let regex = try! Regex(compiling: regex) + let regex = try! Regex(regex) let actual = string.replacing(regex, with: replacement) XCTAssertEqual(actual, expected, file: file, line: line) } @@ -116,7 +108,7 @@ class RegexConsumerTests: XCTestCase { } func testAdHoc() { - let r = try! Regex(compiling: "a|b+") + let r = try! Regex("a|b+") XCTAssert("palindrome".contains(r)) XCTAssert("botany".contains(r)) @@ -145,4 +137,39 @@ class RegexConsumerTests: XCTestCase { XCTAssertEqual("x", "axb".trimming(r)) XCTAssertEqual("x", "axbb".trimming(r)) } + + func testSubstring() throws { + let s = "aaa | aaaaaa | aaaaaaaaaa" + let s1 = s.dropFirst(6) // "aaaaaa | aaaaaaaaaa" + let s2 = s1.dropLast(17) // "aa" + let regex = try! Regex("a+") + + XCTAssertEqual(s.firstMatch(of: regex)?.0, "aaa") + XCTAssertEqual(s1.firstMatch(of: regex)?.0, "aaaaaa") + XCTAssertEqual(s2.firstMatch(of: regex)?.0, "aa") + + XCTAssertEqual( + s.ranges(of: regex).map(s.offsets(of:)), + [0..<3, 6..<12, 15..<25]) + XCTAssertEqual( + s1.ranges(of: regex).map(s.offsets(of:)), + [6..<12, 15..<25]) + XCTAssertEqual( + s2.ranges(of: regex).map(s.offsets(of:)), + [6..<8]) + + XCTAssertEqual(s.replacing(regex, with: ""), " | | ") + XCTAssertEqual(s1.replacing(regex, with: ""), " | ") + XCTAssertEqual(s2.replacing(regex, with: ""), "") + + XCTAssertEqual( + s._matches(of: regex).map(\.0), + ["aaa", "aaaaaa", "aaaaaaaaaa"]) + XCTAssertEqual( + s1._matches(of: regex).map(\.0), + ["aaaaaa", "aaaaaaaaaa"]) + XCTAssertEqual( + s2._matches(of: regex).map(\.0), + ["aa"]) + } } diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index 67412d262..b1287fc8b 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -869,15 +869,15 @@ extension RegexTests { ("123", "123"), (" 123", nil), ("123 456", "123"), - (" 123 \n456", "456"), - (" \n123 \n456", "123")) + (" 123 \n456", nil), + (" \n123 \n456", nil)) firstMatchTests( #"\d+$"#, ("123", "123"), (" 123", "123"), (" 123 \n456", "456"), - (" 123\n456", "123"), + (" 123\n456", "456"), ("123 456", "456")) firstMatchTests( @@ -1197,6 +1197,89 @@ extension RegexTests { ("cafe", true), ("CaFe", true), ("EfAc", true)) + matchTest( + #"(?i)[a-f]{4}"#, + ("cafe", true), + ("CaFe", true), + ("EfAc", true)) + } + + func testASCIIClasses() { + // 'D' ASCII-only digits + matchTest( + #"\d+"#, + ("123", true), + ("¹೨¾", true)) + matchTest( + #"(?D)\d+"#, + ("123", true), + ("¹೨¾", false)) + matchTest( + #"(?P)\d+"#, + ("123", true), + ("¹೨¾", false)) + + // 'W' ASCII-only word characters (and word boundaries) + matchTest( + #"\w+"#, + ("aeiou", true), + ("åe\u{301}ïôú", true)) + matchTest( + #"(?W)\w+"#, + ("aeiou", true), + ("åe\u{301}ïôú", false)) + matchTest( + #"(?P)\w+"#, + ("aeiou", true), + ("åe\u{301}ïôú", false)) + + matchTest( + #"abcd\b.+"#, + ("abcd ef", true), + ("abcdef", false), + ("abcdéf", false)) + matchTest( + #"(?W)abcd\b.+"#, + ("abcd ef", true), + ("abcdef", false), + ("abcdéf", true)) // "dé" matches /d\b./ because "é" isn't ASCII + matchTest( + #"(?P)abcd\b.+"#, + ("abcd ef", true), + ("abcdef", false), + ("abcdéf", true)) // "dé" matches /d\b./ because "é" isn't ASCII + + // 'S' ASCII-only spaces + matchTest( + #"a\sb"#, + ("a\tb", true), + ("a\u{202f}b", true)) // NARROW NO-BREAK SPACE + matchTest( + #"(?S)a\sb"#, + ("a\tb", true), + ("a\u{202f}b", false)) + matchTest( + #"(?P)a\sb"#, + ("a\tb", true), + ("a\u{202f}b", false)) + } + + func testAnchorMatching() throws { + let string = """ + 01: Alabama + 02: Alaska + 03: Arizona + 04: Arkansas + 05: California + """ + XCTAssertTrue(string.contains(try Regex(#"^\d+"#))) + XCTAssertEqual(string.ranges(of: try Regex(#"^\d+"#)).count, 1) + XCTAssertEqual(string.ranges(of: try Regex(#"(?m)^\d+"#)).count, 5) + + let regex = try Regex(#"^\d+: [\w ]+$"#) + XCTAssertFalse(string.contains(regex)) + let allRanges = string.ranges(of: regex.anchorsMatchLineEndings()) + XCTAssertEqual(allRanges.count, 5) } func testMatchingOptionsScope() { @@ -1220,6 +1303,16 @@ extension RegexTests { firstMatchTest(#"(?s)((?-s)((?i)a)).b"#, input: "a\nb", match: "a\nb") } + func testOptionMethods() throws { + let regex = try Regex("c.f.") + XCTAssertTrue ("cafe".contains(regex)) + XCTAssertFalse("CaFe".contains(regex)) + + let caseInsensitiveRegex = regex.ignoresCase() + XCTAssertTrue("cafe".contains(caseInsensitiveRegex)) + XCTAssertTrue("CaFe".contains(caseInsensitiveRegex)) + } + // MARK: Character Semantics var eComposed: String { "é" }