From 1f99047dfc1e6ae9c567d7f5449e247fcb01b0d6 Mon Sep 17 00:00:00 2001 From: Tina Liu <49205802+itingliu@users.noreply.github.com> Date: Fri, 22 Apr 2022 15:18:36 -0700 Subject: [PATCH 01/30] Rename CustomPrefixMatchRegexComponent to CustomConsumingRegexComponent (#326) --- Documentation/Evolution/ProposalOverview.md | 2 +- Documentation/Evolution/RegexTypeOverview.md | 8 ++++---- .../Evolution/StringProcessingAlgorithms.md | 12 ++++++------ .../_StringProcessing/Regex/CustomComponents.swift | 4 ++-- Tests/RegexBuilderTests/CustomTests.swift | 6 +++--- Tests/RegexBuilderTests/RegexDSLTests.swift | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Documentation/Evolution/ProposalOverview.md b/Documentation/Evolution/ProposalOverview.md index 898e0db20..7656526a6 100644 --- a/Documentation/Evolution/ProposalOverview.md +++ b/Documentation/Evolution/ProposalOverview.md @@ -39,7 +39,7 @@ Covers the "interior" syntax, extended syntaxes, run-time construction of a rege Proposes a slew of Regex-powered algorithms. -Introduces `CustomPrefixMatchRegexComponent`, which is a monadic-parser style interface for external parsers to be used as components of a regex. +Introduces `CustomConsumingRegexComponent`, which is a monadic-parser style interface for external parsers to be used as components of a regex. ## Unicode for String Processing diff --git a/Documentation/Evolution/RegexTypeOverview.md b/Documentation/Evolution/RegexTypeOverview.md index 68dd6ccc7..94230d724 100644 --- a/Documentation/Evolution/RegexTypeOverview.md +++ b/Documentation/Evolution/RegexTypeOverview.md @@ -231,7 +231,7 @@ The result builder allows for inline failable value construction, which particip 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"). -`CustomPrefixMatchRegexComponent`, 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: +`CustomConsumingRegexComponent`, 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: ```swift func processEntry(_ line: String) -> Transaction? { @@ -431,7 +431,7 @@ Regular expressions have a deservedly mixed reputation, owing to their historica * "Regular expressions are bad because you should use a real parser" - In other systems, you're either in or you're out, leading to a gravitational pull to stay in when... you should get out - - Our remedy is interoperability with real parsers via `CustomPrefixMatchRegexComponent` + - Our remedy is interoperability with real parsers via `CustomConsumingRegexComponent` - Literals with refactoring actions provide an incremental off-ramp from regex syntax to result builders and real parsers * "Regular expressions are bad because ugly unmaintainable syntax" - We propose literals with source tools support, allowing for better syntax highlighting and analysis @@ -516,7 +516,7 @@ Regex are compiled into an intermediary representation and fairly simple analysi ### Future work: parser combinators -What we propose here is an incremental step towards better parsing support in Swift using parser-combinator style libraries. The underlying execution engine supports recursive function calls and mechanisms for library extensibility. `CustomPrefixMatchRegexComponent`'s protocol requirement is effectively a [monadic parser](https://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf), meaning `Regex` provides a regex-flavored combinator-like system. +What we propose here is an incremental step towards better parsing support in Swift using parser-combinator style libraries. The underlying execution engine supports recursive function calls and mechanisms for library extensibility. `CustomConsumingRegexComponent`'s protocol requirement is effectively a [monadic parser](https://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf), meaning `Regex` provides a regex-flavored combinator-like system. An issues with traditional parser combinator libraries are the compilation barriers between call-site and definition, resulting in excessive and overly-cautious backtracking traffic. These can be eliminated through better [compilation techniques](https://core.ac.uk/download/pdf/148008325.pdf). As mentioned above, Swift's support for custom static compilation is still under development. @@ -565,7 +565,7 @@ Regexes are often used for tokenization and tokens can be represented with Swift ### Future work: baked-in localized processing -- `CustomPrefixMatchRegexComponent` gives an entry point for localized processors +- `CustomConsumingRegexComponent` gives an entry point for localized processors - Future work includes (sub?)protocols to communicate localization intent --> diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index edefbd19b..263c00d3b 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -8,7 +8,7 @@ We propose: 1. New regex-powered algorithms over strings, bringing the standard library up to parity with scripting languages 2. Generic `Collection` equivalents of these algorithms in terms of subsequences -3. `protocol CustomPrefixMatchRegexComponent`, which allows 3rd party libraries to provide their industrial-strength parsers as intermixable components of regexes +3. `protocol CustomConsumingRegexComponent`, which allows 3rd party libraries to provide their industrial-strength parsers as intermixable components of regexes This proposal is part of a larger [regex-powered string processing initiative](https://github.com/apple/swift-evolution/blob/main/proposals/0350-regex-type-overview.md), the status of each proposal is tracked [here](https://github.com/apple/swift-experimental-string-processing/blob/main/Documentation/Evolution/ProposalOverview.md). Further discussion of regex specifics is out of scope of this proposal and better discussed in their relevant reviews. @@ -132,7 +132,7 @@ Parsing a currency string such as `$3,020.85` with regex is also tricky, as it c ### Complex string processing -We propose a `CustomPrefixMatchRegexComponent` protocol which allows types from outside the standard library participate in regex builders and `RegexComponent` algorithms. This allows types, such as `Date.ParseStrategy` and `FloatingPointFormatStyle.Currency`, to be used directly within a regex: +We propose a `CustomConsumingRegexComponent` protocol which allows types from outside the standard library participate in regex builders and `RegexComponent` algorithms. This allows types, such as `Date.ParseStrategy` and `FloatingPointFormatStyle.Currency`, to be used directly within a regex: ```swift let dateRegex = Regex { @@ -169,14 +169,14 @@ We also propose the following regex-powered algorithms as well as their generic ## Detailed design -### `CustomPrefixMatchRegexComponent` +### `CustomConsumingRegexComponent` -`CustomPrefixMatchRegexComponent` inherits from `RegexComponent` and satisfies its sole requirement. Conformers can be used with all of the string algorithms generic over `RegexComponent`. +`CustomConsumingRegexComponent` inherits from `RegexComponent` and satisfies its sole requirement. Conformers can be used with all of the string algorithms generic over `RegexComponent`. ```swift /// A protocol allowing custom types to function as regex components by /// providing the raw functionality backing `prefixMatch`. -public protocol CustomPrefixMatchRegexComponent: RegexComponent { +public protocol CustomConsumingRegexComponent: RegexComponent { /// Process the input string within the specified bounds, beginning at the given index, and return /// the end position (upper bound) of the match and the produced output. /// - Parameters: @@ -199,7 +199,7 @@ public protocol CustomPrefixMatchRegexComponent: RegexComponent { We use Foundation `FloatingPointFormatStyle.Currency` as an example for protocol conformance. It would implement the `match` function with `Match` being a `Decimal`. It could also add a static function `.localizedCurrency(code:)` as a member of `RegexComponent`, so it can be referred as `.localizedCurrency(code:)` in the `Regex` result builder: ```swift -extension FloatingPointFormatStyle.Currency : CustomPrefixMatchRegexComponent { +extension FloatingPointFormatStyle.Currency : CustomConsumingRegexComponent { public func consuming( _ input: String, startingAt index: String.Index, diff --git a/Sources/_StringProcessing/Regex/CustomComponents.swift b/Sources/_StringProcessing/Regex/CustomComponents.swift index e8111555c..d675c3ae7 100644 --- a/Sources/_StringProcessing/Regex/CustomComponents.swift +++ b/Sources/_StringProcessing/Regex/CustomComponents.swift @@ -12,7 +12,7 @@ @available(SwiftStdlib 5.7, *) /// A protocol allowing custom types to function as regex components by /// providing the raw functionality backing `prefixMatch`. -public protocol CustomPrefixMatchRegexComponent: RegexComponent { +public protocol CustomConsumingRegexComponent: RegexComponent { /// Process the input string within the specified bounds, beginning at the given index, and return /// the end position (upper bound) of the match and the produced output. /// - Parameters: @@ -29,7 +29,7 @@ public protocol CustomPrefixMatchRegexComponent: RegexComponent { } @available(SwiftStdlib 5.7, *) -extension CustomPrefixMatchRegexComponent { +extension CustomConsumingRegexComponent { public var regex: Regex { let node: DSLTree.Node = .matcher(RegexOutput.self, { input, index, bounds in try consuming(input, startingAt: index, in: bounds) diff --git a/Tests/RegexBuilderTests/CustomTests.swift b/Tests/RegexBuilderTests/CustomTests.swift index 269f9ebaa..bc71f2363 100644 --- a/Tests/RegexBuilderTests/CustomTests.swift +++ b/Tests/RegexBuilderTests/CustomTests.swift @@ -14,7 +14,7 @@ import _StringProcessing @testable import RegexBuilder // A nibbler processes a single character from a string -private protocol Nibbler: CustomPrefixMatchRegexComponent { +private protocol Nibbler: CustomConsumingRegexComponent { func nibble(_: Character) -> RegexOutput? } @@ -49,7 +49,7 @@ private struct Asciibbler: Nibbler { } } -private struct IntParser: CustomPrefixMatchRegexComponent { +private struct IntParser: CustomConsumingRegexComponent { struct ParseError: Error, Hashable {} typealias RegexOutput = Int func consuming(_ input: String, @@ -71,7 +71,7 @@ private struct IntParser: CustomPrefixMatchRegexComponent { } } -private struct CurrencyParser: CustomPrefixMatchRegexComponent { +private struct CurrencyParser: CustomConsumingRegexComponent { enum Currency: String, Hashable { case usd = "USD" case ntd = "NTD" diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift index cd1c94657..7c06fd6c3 100644 --- a/Tests/RegexBuilderTests/RegexDSLTests.swift +++ b/Tests/RegexBuilderTests/RegexDSLTests.swift @@ -863,7 +863,7 @@ class RegexDSLTests: XCTestCase { var patch: Int var dev: String? } - struct SemanticVersionParser: CustomPrefixMatchRegexComponent { + struct SemanticVersionParser: CustomConsumingRegexComponent { typealias RegexOutput = SemanticVersion func consuming( _ input: String, From 563d6c2220b26c1ba368352c2a98bb02e7e83670 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 22 Apr 2022 17:43:48 -0700 Subject: [PATCH 02/30] Remove String.Index evils --- .../_StringProcessing/Unicode/NecessaryEvils.swift | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Sources/_StringProcessing/Unicode/NecessaryEvils.swift b/Sources/_StringProcessing/Unicode/NecessaryEvils.swift index a9ae24429..672a731bd 100644 --- a/Sources/_StringProcessing/Unicode/NecessaryEvils.swift +++ b/Sources/_StringProcessing/Unicode/NecessaryEvils.swift @@ -88,14 +88,3 @@ extension UTF16 { (UInt32(lead & 0x03ff) &<< 10 | UInt32(trail & 0x03ff))) } } - -extension String.Index { - internal var _encodedOffset: Int { - // The encoded offset is found in the top 48 bits. - Int(unsafeBitCast(self, to: UInt64.self) >> 16) - } - - internal init(_encodedOffset offset: Int) { - self = unsafeBitCast(offset << 16, to: Self.self) - } -} From 571e259acb96c915a2a3e55deb22b58beda345f8 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 22 Apr 2022 22:13:01 -0500 Subject: [PATCH 03/30] More updates for algorithms proposal (#324) * Update Sequence/Collection polarity * Add a note about new generics features * Update split methods, catch some inconsistencies * Adopt opaque parameter types where possible today Also includes some generic naming updates and typo fixes. * Update documentation parameters * split(by:) -> split(separator:) --- .../Evolution/StringProcessingAlgorithms.md | 148 +++++++++++------- 1 file changed, 93 insertions(+), 55 deletions(-) diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index 263c00d3b..6c591c268 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -14,7 +14,7 @@ This proposal is part of a larger [regex-powered string processing initiative](h ## Motivation -A number of common string processing APIs are missing from the Swift standard library. While most of the desired functionalities can be accomplished through a series of API calls, every gap adds a burden to developers doing frequent or complex string processing. For example, here's one approach to find the number of occurrences a substring ("banana") within a string: +A number of common string processing APIs are missing from the Swift standard library. While most of the desired functionalities can be accomplished through a series of API calls, every gap adds a burden to developers doing frequent or complex string processing. For example, here's one approach to find the number of occurrences of a substring ("banana") within a string: ```swift let str = "A banana a day keeps the doctor away. I love bananas; banana are my favorite fruit." @@ -216,10 +216,10 @@ Matching and extracting a localized currency amount, such as `"$3,020.85"`, can ```swift let regex = Regex { - capture(.localizedCurreny(code: "USD")) + Capture(.localizedCurrency(code: "USD")) } ``` - + @@ -234,7 +234,7 @@ extension Collection where Element: Equatable { /// - Parameter other: A sequence to search for within this collection. /// - Returns: `true` if the collection contains the specified sequence, /// otherwise `false`. - public func contains(_ other: S) -> Bool + public func contains(_ other: C) -> Bool where S.Element == Element } @@ -244,7 +244,7 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Parameter regex: A regex to search for within this collection. /// - Returns: `true` if the regex was found in the collection, otherwise /// `false`. - public func contains(_ regex: R) -> Bool + public func contains(_ regex: some RegexComponent) -> Bool } ``` @@ -257,7 +257,7 @@ extension BidirectionalCollection where SubSequence == Substring { /// - 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 + public func starts(with regex: some RegexComponent) -> Bool } ``` @@ -281,7 +281,7 @@ extension Collection where SubSequence == Self { /// - 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. - public mutating func trimPrefix(while predicate: (Element) throws -> Bool) + public mutating func trimPrefix(while predicate: (Element) throws -> Bool) rethrows } extension RangeReplaceableCollection { @@ -290,7 +290,7 @@ extension RangeReplaceableCollection { /// - 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. - public mutating func trimPrefix(while predicate: (Element) throws -> Bool) + public mutating func trimPrefix(while predicate: (Element) throws -> Bool) rethrows } extension Collection where Element: Equatable { @@ -299,21 +299,21 @@ extension Collection where Element: Equatable { /// - Parameter prefix: The collection to remove from this collection. /// - Returns: A collection containing the elements that does not match /// `prefix` from the start. - public func trimmingPrefix(_ prefix: Prefix) -> SubSequence + public func trimmingPrefix(_ prefix: Prefix) -> SubSequence where Prefix.Element == Element } extension Collection where SubSequence == Self, Element: Equatable { /// Removes the initial elements that matches `prefix` from the start. /// - Parameter prefix: The collection to remove from this collection. - public mutating func trimPrefix(_ prefix: Prefix) + public mutating func trimPrefix(_ prefix: Prefix) where Prefix.Element == Element } extension RangeReplaceableCollection where Element: Equatable { /// Removes the initial elements that matches `prefix` from the start. /// - Parameter prefix: The collection to remove from this collection. - public mutating func trimPrefix(_ prefix: Prefix) + public mutating func trimPrefix(_ prefix: Prefix) where Prefix.Element == Element } @@ -323,7 +323,7 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Parameter regex: The regex to remove from this collection. /// - Returns: A new subsequence containing the elements of the collection /// that does not match `prefix` from the start. - public func trimmingPrefix(_ regex: R) -> SubSequence + public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence } extension RangeReplaceableCollection @@ -331,7 +331,7 @@ extension RangeReplaceableCollection { /// Removes the initial elements that matches the given regex. /// - Parameter regex: The regex to remove from this collection. - public mutating func trimPrefix(_ regex: R) + public mutating func trimPrefix(_ regex: some RegexComponent) } ``` @@ -344,8 +344,8 @@ extension Collection where Element: Equatable { /// - Parameter sequence: The sequence to search for. /// - Returns: A range in the collection of the first occurrence of `sequence`. /// Returns nil if `sequence` is not found. - public func firstRange(of sequence: S) -> Range? - where S.Element == Element + public func firstRange(of other: C) -> Range? + where C.Element == Element } extension BidirectionalCollection where Element: Comparable { @@ -354,8 +354,8 @@ extension BidirectionalCollection where Element: Comparable { /// - 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. - public func firstRange(of other: S) -> Range? - where S.Element == Element + public func firstRange(of other: C) -> Range? + where C.Element == Element } extension BidirectionalCollection where SubSequence == Substring { @@ -364,7 +364,7 @@ extension BidirectionalCollection where SubSequence == Substring { /// - 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. - public func firstRange(of regex: R) -> Range? + public func firstRange(of regex: some RegexComponent) -> Range? } ``` @@ -377,8 +377,8 @@ extension Collection where Element: Equatable { /// - Parameter other: The sequence to search for. /// - Returns: A collection of ranges of all occurrences of `other`. Returns /// an empty collection if `other` is not found. - public func ranges(of other: S) -> some Collection> - where S.Element == Element + public func ranges(of other: C) -> some Collection> + where C.Element == Element } extension BidirectionalCollection where SubSequence == Substring { @@ -387,7 +387,7 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Parameter regex: The regex to search for. /// - Returns: A collection or ranges in the receiver of all occurrences of /// `regex`. Returns an empty collection if `regex` is not found. - public func ranges(of regex: R) -> some Collection> + public func ranges(of regex: some RegexComponent) -> some Collection> } ``` @@ -399,17 +399,17 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Parameter regex: The regex to search for. /// - Returns: The first match of `regex` in the collection, or `nil` if /// there isn't a match. - public func firstMatch(of regex: R) -> RegexMatch? + public func firstMatch(of regex: R) -> Regex.Match? /// Match a regex in its entirety. - /// - Parameter r: The regex to match against. + /// - Parameter regex: The regex to match against. /// - Returns: The match if there is one, or `nil` if none. - public func wholeMatch(of r: R) -> Regex.Match? + public func wholeMatch(of regex: R) -> Regex.Match? /// Match part of the regex, starting at the beginning. - /// - Parameter r: The regex to match against. + /// - Parameter regex: The regex to match against. /// - Returns: The match if there is one, or `nil` if none. - public func prefixMatch(of r: R) -> Regex.Match? + public func prefixMatch(of regex: R) -> Regex.Match? } ``` @@ -420,7 +420,7 @@ extension BidirectionalCollection where SubSequence == Substring { /// Returns a collection containing all matches of the specified regex. /// - Parameter regex: The regex to search for. /// - Returns: A collection of matches of `regex`. - public func matches(of regex: R) -> some Collection> + public func matches(of regex: R) -> some Collection.Match> } ``` @@ -438,12 +438,12 @@ extension RangeReplaceableCollection where Element: Equatable { /// 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`. - public func replacing( - _ other: S, + public func replacing( + _ other: C, with replacement: Replacement, subrange: Range, maxReplacements: Int = .max - ) -> Self where S.Element == Element, Replacement.Element == Element + ) -> Self where C.Element == Element, Replacement.Element == Element /// Returns a new collection in which all occurrences of a target sequence /// are replaced by another collection. @@ -454,11 +454,11 @@ extension RangeReplaceableCollection where Element: Equatable { /// 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`. - public func replacing( - _ other: S, + public func replacing( + _ other: C, with replacement: Replacement, maxReplacements: Int = .max - ) -> Self where S.Element == Element, Replacement.Element == Element + ) -> Self where C.Element == Element, Replacement.Element == Element /// Replaces all occurrences of a target sequence with a given collection /// - Parameters: @@ -466,11 +466,11 @@ extension RangeReplaceableCollection where Element: Equatable { /// - replacement: The new elements to add to the collection. /// - maxReplacements: A number specifying how many occurrences of `other` /// to replace. Default is `Int.max`. - public mutating func replace( - _ other: S, + public mutating func replace( + _ other: C, with replacement: Replacement, maxReplacements: Int = .max - ) where S.Element == Element, Replacement.Element == Element + ) where C.Element == Element, Replacement.Element == Element } extension RangeReplaceableCollection where SubSequence == Substring { @@ -484,8 +484,8 @@ extension RangeReplaceableCollection where SubSequence == Substring { /// 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`. - public func replacing( - _ r: R, + public func replacing( + _ r: some RegexComponent, with replacement: Replacement, subrange: Range, maxReplacements: Int = .max @@ -500,8 +500,8 @@ extension RangeReplaceableCollection where SubSequence == Substring { /// 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`. - public func replacing( - _ r: R, + public func replacing( + _ r: some RegexComponent, with replacement: Replacement, maxReplacements: Int = .max ) -> Self where Replacement.Element == Element @@ -513,8 +513,8 @@ extension RangeReplaceableCollection where SubSequence == Substring { /// - 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`. - public mutating func replace( - _ r: R, + public mutating func replace( + _ r: some RegexComponent, with replacement: Replacement, maxReplacements: Int = .max ) where Replacement.Element == Element @@ -534,7 +534,7 @@ extension RangeReplaceableCollection where SubSequence == Substring { _ regex: R, subrange: Range, maxReplacements: Int = .max, - with replacement: (RegexMatch) throws -> Replacement + with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element /// Returns a new collection in which all occurrences of a sequence matching @@ -550,7 +550,7 @@ extension RangeReplaceableCollection where SubSequence == Substring { public func replacing( _ regex: R, maxReplacements: Int = .max, - with replacement: (RegexMatch) throws -> Replacement + with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element /// Replaces all occurrences of the sequence matching the given regex with @@ -564,7 +564,7 @@ extension RangeReplaceableCollection where SubSequence == Substring { public mutating func replace( _ regex: R, maxReplacements: Int = .max, - with replacement: (RegexMatch) throws -> Replacement + with replacement: (Regex.Match) throws -> Replacement ) rethrows where Replacement.Element == Element } ``` @@ -574,27 +574,65 @@ extension RangeReplaceableCollection where SubSequence == Substring { ```swift extension Collection where Element: Equatable { /// 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. + /// around elements equal to the given separator collection. + /// + /// - Parameters: + /// - separator: A collection of elements to be split upon. + /// - maxSplits: The maximum number of times to split the collection, + /// or one less than the number of subsequences to return. + /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// returned in the result for each consecutive pair of separator + /// sequences in the collection and for each instance of separator + /// sequences at the start or end of the collection. If `true`, only + /// nonempty subsequences are returned. /// - Returns: A collection of subsequences, split from this collection's - /// elements. - public func split(by separator: S) -> some Collection - where S.Element == Element + /// elements. + public func split( + separator: C, + maxSplits: Int = Int.max, + omittingEmptySubsequences: Bool = true + ) -> some Collection where C.Element == Element } extension BidirectionalCollection where SubSequence == Substring { /// 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. + /// around subsequence that match the given separator regex. + /// + /// - Parameters: + /// - separator: A regex to be split upon. + /// - maxSplits: The maximum number of times to split the collection, + /// or one less than the number of subsequences to return. + /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// returned in the result for each consecutive pair of matches + /// and for each match at the start or end of the collection. If + /// `true`, only nonempty subsequences are returned. /// - Returns: A collection of substrings, split from this collection's - /// elements. - public func split(by separator: R) -> some Collection + /// elements. + public func split( + separator: some RegexComponent, + maxSplits: Int = Int.max, + omittingEmptySubsequences: Bool = true + ) -> some Collection } ``` +**Note:** We plan to adopt the new generics features enabled by [SE-0346][] for these proposed methods when the standard library adopts primary associated types, [pending a forthcoming proposal][stdlib-pitch]. For example, the first method in the _Replacement_ section above would instead be: +```swift +extension RangeReplaceableCollection where Element: Equatable { + /// Returns a new collection in which all occurrences of a target sequence + /// are replaced by another collection. + public func replacing( + _ other: some Collection, + with replacement: some Collection, + subrange: Range, + maxReplacements: Int = .max + ) -> Self +} +``` - +[SE-0346]: https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md +[stdlib-pitch]: https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426 ## Alternatives considered From 2df0f2457fc4daac875b9ef2c3f823a64b5ce097 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Sat, 23 Apr 2022 12:13:12 -0600 Subject: [PATCH 04/30] Add ~= overloads (#335) --- Sources/_StringProcessing/Regex/Match.swift | 12 ++++++++++++ Tests/RegexTests/AlgorithmsTests.swift | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index e38af43f8..39ff7ece9 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -185,3 +185,15 @@ extension Regex { self.init(node: .quotedLiteral(string)) } } + +@available(SwiftStdlib 5.7, *) +public func ~=(regex: Regex, input: String) -> Bool { + guard let _ = try? regex.wholeMatch(in: input) else { return false } + return true +} + +@available(SwiftStdlib 5.7, *) +public func ~=(regex: Regex, input: Substring) -> Bool { + guard let _ = try? regex.wholeMatch(in: input) else { return false } + return true +} diff --git a/Tests/RegexTests/AlgorithmsTests.swift b/Tests/RegexTests/AlgorithmsTests.swift index a788ad13c..d19d6c43d 100644 --- a/Tests/RegexTests/AlgorithmsTests.swift +++ b/Tests/RegexTests/AlgorithmsTests.swift @@ -172,4 +172,19 @@ class RegexConsumerTests: XCTestCase { s2.matches(of: regex).map(\.0), ["aa"]) } + + func testSwitches() { + switch "abcde" { + case try! Regex("a.*f"): + XCTFail() + case try! Regex("abc"): + XCTFail() + + case try! Regex("a.*e"): + break // success + + default: + XCTFail() + } + } } From dfa4ea1cefb35fd0269dbc534cf7cca50c42aadc Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sat, 23 Apr 2022 15:50:49 -0500 Subject: [PATCH 05/30] Fix a missed type name change --- Sources/VariadicsGenerator/VariadicsGenerator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VariadicsGenerator/VariadicsGenerator.swift b/Sources/VariadicsGenerator/VariadicsGenerator.swift index c5c7dec97..85c298c20 100644 --- a/Sources/VariadicsGenerator/VariadicsGenerator.swift +++ b/Sources/VariadicsGenerator/VariadicsGenerator.swift @@ -517,7 +517,7 @@ struct VariadicsGenerator: ParsableCommand { \(params.disfavored)\ public init<\(params.genericParams), R: RangeExpression>( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @\(concatBuilderName) _ component: () -> Component ) \(params.repeatingWhereClause) { self.init(node: .repeating(expression.relative(to: 0.. Date: Sat, 23 Apr 2022 15:51:17 -0500 Subject: [PATCH 06/30] Add a default arity and an flag for silencing logs --- .../VariadicsGenerator.swift | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/Sources/VariadicsGenerator/VariadicsGenerator.swift b/Sources/VariadicsGenerator/VariadicsGenerator.swift index 85c298c20..f57cd8caa 100644 --- a/Sources/VariadicsGenerator/VariadicsGenerator.swift +++ b/Sources/VariadicsGenerator/VariadicsGenerator.swift @@ -101,8 +101,17 @@ let defaultAvailableAttr = "@available(SwiftStdlib 5.7, *)" @main struct VariadicsGenerator: ParsableCommand { @Option(help: "The maximum arity of declarations to generate.") - var maxArity: Int + var maxArity: Int = 10 + + @Flag(help: "Suppress status messages while generating.") + var silent: Bool = false + func log(_ message: String, terminator: String = "\n") { + if !silent { + print(message, terminator: terminator, to: &standardError) + } + } + func run() throws { precondition(maxArity > 1) precondition(maxArity < Counter.bitWidth) @@ -126,14 +135,12 @@ struct VariadicsGenerator: ParsableCommand { """) - print("Generating concatenation overloads...", to: &standardError) + log("Generating concatenation overloads...") for (leftArity, rightArity) in Permutations(totalArity: maxArity) { guard rightArity != 0 else { continue } - print( - " Left arity: \(leftArity) Right arity: \(rightArity)", - to: &standardError) + log(" Left arity: \(leftArity) Right arity: \(rightArity)") emitConcatenation(leftArity: leftArity, rightArity: rightArity) } @@ -143,42 +150,40 @@ struct VariadicsGenerator: ParsableCommand { output("\n\n") - print("Generating quantifiers...", to: &standardError) + log("Generating quantifiers...") for arity in 0...maxArity { - print(" Arity \(arity): ", terminator: "", to: &standardError) + log(" Arity \(arity): ", terminator: "") for kind in QuantifierKind.allCases { - print("\(kind.rawValue) ", terminator: "", to: &standardError) + log("\(kind.rawValue) ", terminator: "") emitQuantifier(kind: kind, arity: arity) } - print("repeating ", terminator: "", to: &standardError) + log("repeating ", terminator: "") emitRepeating(arity: arity) - print(to: &standardError) + log("") } - print("Generating atomic groups...", to: &standardError) + log("Generating atomic groups...") for arity in 0...maxArity { - print(" Arity \(arity): ", terminator: "", to: &standardError) + log(" Arity \(arity): ", terminator: "") emitAtomicGroup(arity: arity) - print(to: &standardError) + log("") } - print("Generating alternation overloads...", to: &standardError) + log("Generating alternation overloads...") for (leftArity, rightArity) in Permutations(totalArity: maxArity) { - print( - " Left arity: \(leftArity) Right arity: \(rightArity)", - to: &standardError) + log(" Left arity: \(leftArity) Right arity: \(rightArity)") emitAlternation(leftArity: leftArity, rightArity: rightArity) } - print("Generating 'AlternationBuilder.buildBlock(_:)' overloads...", to: &standardError) + log("Generating 'AlternationBuilder.buildBlock(_:)' overloads...") for arity in 1...maxArity { - print(" Capture arity: \(arity)", to: &standardError) + log(" Capture arity: \(arity)") emitUnaryAlternationBuildBlock(arity: arity) } - print("Generating 'capture' and 'tryCapture' overloads...", to: &standardError) + log("Generating 'capture' and 'tryCapture' overloads...") for arity in 0...maxArity { - print(" Capture arity: \(arity)", to: &standardError) + log(" Capture arity: \(arity)") emitCapture(arity: arity) } @@ -186,7 +191,7 @@ struct VariadicsGenerator: ParsableCommand { output("// END AUTO-GENERATED CONTENT\n") - print("Done!", to: &standardError) + log("Done!") } func tupleType(arity: Int, genericParameters: () -> String) -> String { From 7b737e3659a7431024ad2558a3b8413bcfe571b5 Mon Sep 17 00:00:00 2001 From: Tina Liu <49205802+itingliu@users.noreply.github.com> Date: Sun, 24 Apr 2022 14:09:31 -0700 Subject: [PATCH 07/30] Add `@RegexComponentBuilder` overloads for string processing algorithm. (#334) * Add `@RegexComponentBuilder` overloads for string processing algorithm. These overloads will allow you to write, e.g. ```swift let _ = str.wholeMatch { OneOrMore("a") "+" OneOrMore("a") } ``` instead of ```swift let _ = str.wholeMatch(of: Regex { OneOrMore("a") "+" OneOrMore("a") }) ``` --- .../Evolution/StringProcessingAlgorithms.md | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index 6c591c268..0539d46ca 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -245,6 +245,16 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: `true` if the regex was found in the collection, otherwise /// `false`. public func contains(_ regex: some RegexComponent) -> Bool + + /// Returns a Boolean value indicating whether the collection contains the + /// given regex. + /// - Parameter content: A closure to produce a `RegexComponent` to search for + /// within this collection. + /// - Returns: `true` if the regex was found in the collection, otherwise + /// `false`. + public func contains( + @RegexComponentBuilder _ content: () -> some RegexComponent + ) -> Bool } ``` @@ -258,6 +268,15 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: `true` if the initial elements of the sequence matches the /// beginning of `regex`; otherwise, `false`. public func starts(with regex: some RegexComponent) -> Bool + + /// Returns a Boolean value indicating whether the initial elements of the + /// sequence are the same as the elements in the specified regex. + /// - Parameter content: A closure to produce a `RegexComponent` to compare. + /// - Returns: `true` if the initial elements of the sequence matches the + /// beginning of `regex`; otherwise, `false`. + public func starts( + @RegexComponentBuilder with content: () -> some RegexComponent + ) -> Bool } ``` @@ -324,6 +343,15 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: A new subsequence containing the elements of the collection /// that does not match `prefix` from the start. public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence + + /// Returns a new collection of the same type by removing `prefix` from the + /// start. + /// - Parameter _content A closure to produce a `RegexComponent` to be removed. + /// - Returns: A collection containing the elements that does not match + /// `prefix` from the start. + public func trimmingPrefix( + @RegexComponentBuilder _ content: () -> some RegexComponent + ) -> SubSequence } extension RangeReplaceableCollection @@ -332,6 +360,12 @@ extension RangeReplaceableCollection /// Removes the initial elements that matches the given regex. /// - Parameter regex: The regex to remove from this collection. public mutating func trimPrefix(_ regex: some RegexComponent) + + /// Removes the initial elements that matches the given regex. + /// - Parameter content: A closure to produce a `RegexComponent` to be removed. + public mutating func trimPrefix( + @RegexComponentBuilder _ content: () -> some RegexComponent + ) } ``` @@ -365,6 +399,16 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: A range in the collection of the first occurrence of `regex`. /// Returns `nil` if `regex` is not found. public func firstRange(of regex: some RegexComponent) -> Range? + + /// Finds and returns the range of the first occurrence of a given regex + /// within the collection. + /// - Parameter content: A closure to produce a `RegexComponent` to search for + /// within this collection. + /// - Returns: A range in the collection of the first occurrence of regex. + /// Returns `nil` if not found. + public func firstRange( + @RegexComponentBuilder of content: () -> some RegexComponent + ) -> Range? } ``` @@ -388,6 +432,16 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: A collection or ranges in the receiver of all occurrences of /// `regex`. Returns an empty collection if `regex` is not found. public func ranges(of regex: some RegexComponent) -> some Collection> + + /// Finds and returns the ranges of the all occurrences of a given sequence + /// within the collection. + /// - Parameter content: A closure to produce a `RegexComponent` to search for + /// within this collection. + /// - Returns: A collection or ranges in the receiver of all occurrences of + /// regex. Returns an empty collection if not found. + public func ranges( + @RegexComponentBuilder of content: () -> some RegexComponent + ) -> some Collection> } ``` @@ -401,15 +455,37 @@ extension BidirectionalCollection where SubSequence == Substring { /// there isn't a match. public func firstMatch(of regex: R) -> Regex.Match? + /// Returns the first match of the specified regex within the collection. + /// - Parameter content: A closure to produce a `RegexComponent` to search for. + /// - Returns: The first match of regex in the collection, or `nil` if + /// there isn't a match. + public func firstMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? + /// Match a regex in its entirety. /// - Parameter regex: The regex to match against. /// - Returns: The match if there is one, or `nil` if none. public func wholeMatch(of regex: R) -> Regex.Match? + /// Match a regex in its entirety. + /// - Parameter content: A closure to produce a `RegexComponent` to match against. + /// - Returns: The match if there is one, or `nil` if none. + public func wholeMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? + /// Match part of the regex, starting at the beginning. /// - Parameter regex: The regex to match against. /// - Returns: The match if there is one, or `nil` if none. public func prefixMatch(of regex: R) -> Regex.Match? + + /// Match part of the regex, starting at the beginning. + /// - Parameter content: A closure to produce a `RegexComponent` to match against. + /// - Returns: The match if there is one, or `nil` if none. + public func prefixMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? } ``` @@ -421,6 +497,13 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Parameter regex: The regex to search for. /// - Returns: A collection of matches of `regex`. public func matches(of regex: R) -> some Collection.Match> + + /// Returns a collection containing all matches of the specified regex. + /// - Parameter content: A closure to produce a `RegexComponent` to search for. + /// - Returns: A collection of matches of `regex`. + public func matches( + @RegexComponentBuilder of content: () -> R + ) -> some Collection.Match> } ``` @@ -490,6 +573,23 @@ extension RangeReplaceableCollection where SubSequence == Substring { subrange: Range, maxReplacements: Int = .max ) -> Self where Replacement.Element == Element + + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another collection. + /// - Parameters: + /// - 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`. + /// - content: A closure to produce a `RegexComponent` to replace. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` in `subrange` are replaced by `replacement`. + public func replacing( + with replacement: Replacement, + subrange: Range, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> some RegexComponent + ) -> Self where Replacement.Element == Element /// Returns a new collection in which all occurrences of a sequence matching /// the given regex are replaced by another collection. @@ -506,6 +606,21 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max ) -> Self where Replacement.Element == Element + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another collection. + /// - Parameters: + /// - 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`. + /// - content: A closure to produce a `RegexComponent` to replace. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + public func replacing( + with replacement: Replacement, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> some RegexComponent + ) -> Self where Replacement.Element == Element + /// Replaces all occurrences of the sequence matching the given regex with /// a given collection. /// - Parameters: @@ -518,6 +633,19 @@ extension RangeReplaceableCollection where SubSequence == Substring { with replacement: Replacement, maxReplacements: Int = .max ) where Replacement.Element == Element + + /// Replaces all occurrences of the sequence matching the given regex with + /// a given collection. + /// - Parameters: + /// - 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`. + /// - content: A closure to produce a `RegexComponent` to replace. + public mutating func replace( + with replacement: Replacement, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> some RegexComponent + ) -> Self where Replacement.Element == Element /// Returns a new collection in which all occurrences of a sequence matching /// the given regex are replaced by another regex match. @@ -536,6 +664,24 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max, with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element + + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another regex match. + /// - Parameters: + /// - 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`. + /// - content: A closure to produce a `RegexComponent` to replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + public func replacing( + subrange: Range, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> R, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows -> Self where Replacement.Element == Element /// Returns a new collection in which all occurrences of a sequence matching /// the given regex are replaced by another collection. @@ -552,6 +698,22 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max, with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element + + /// Returns a new collection in which all occurrences of a sequence matching + /// the given regex are replaced by another collection. + /// - Parameters: + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - content: A closure to produce a `RegexComponent` to replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + public func replacing( + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> R, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows -> Self where Replacement.Element == Element /// Replaces all occurrences of the sequence matching the given regex with /// a given collection. @@ -566,6 +728,20 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max, with replacement: (Regex.Match) throws -> Replacement ) rethrows where Replacement.Element == Element + + /// Replaces all occurrences of the sequence matching the given regex with + /// a given collection. + /// - Parameters: + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - content: A closure to produce a `RegexComponent` to replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + public mutating func replace( + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> R, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows where Replacement.Element == Element } ``` @@ -613,6 +789,25 @@ extension BidirectionalCollection where SubSequence == Substring { maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true ) -> some Collection + + /// Returns the longest possible subsequences of the collection, in order, + /// around subsequence that match the given separator regex. + /// + /// - Parameters: + /// - maxSplits: The maximum number of times to split the collection, + /// or one less than the number of subsequences to return. + /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// returned in the result for each consecutive pair of matches + /// and for each match at the start or end of the collection. If + /// `true`, only nonempty subsequences are returned. + /// - separator: A closure to produce a `RegexComponent` to be split upon. + /// - Returns: A collection of substrings, split from this collection's + /// elements. + public func split( + maxSplits: Int = Int.max, + omittingEmptySubsequences: Bool = true, + @RegexComponentBuilder separator: () -> some RegexComponent + ) -> some Collection } ``` From c56dc7673a1e28b7807e0682a525046a7a535651 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 22 Apr 2022 16:24:36 -0500 Subject: [PATCH 08/30] Remove @testable annotations where possible --- Tests/RegexBuilderTests/RegexDSLTests.swift | 2 +- .../RegexTests/AlgorithmsInternalsTests.swift | 47 +++++++++++++++++++ Tests/RegexTests/AlgorithmsTests.swift | 33 +------------ Tests/RegexTests/AllScalarsTests.swift | 2 +- Tests/RegexTests/CompileTests.swift | 1 - 5 files changed, 50 insertions(+), 35 deletions(-) create mode 100644 Tests/RegexTests/AlgorithmsInternalsTests.swift diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift index 7c06fd6c3..42cb9c52e 100644 --- a/Tests/RegexBuilderTests/RegexDSLTests.swift +++ b/Tests/RegexBuilderTests/RegexDSLTests.swift @@ -11,7 +11,7 @@ import XCTest import _StringProcessing -@testable import RegexBuilder +import RegexBuilder class RegexDSLTests: XCTestCase { func _testDSLCaptures( diff --git a/Tests/RegexTests/AlgorithmsInternalsTests.swift b/Tests/RegexTests/AlgorithmsInternalsTests.swift new file mode 100644 index 000000000..f0d556744 --- /dev/null +++ b/Tests/RegexTests/AlgorithmsInternalsTests.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +@testable import _StringProcessing +import XCTest + +// TODO: Protocol-powered testing +extension AlgorithmTests { + func testAdHoc() { + let r = try! Regex("a|b+") + + XCTAssert("palindrome".contains(r)) + XCTAssert("botany".contains(r)) + XCTAssert("antiquing".contains(r)) + XCTAssertFalse("cdef".contains(r)) + + let str = "a string with the letter b in it" + let first = str.firstRange(of: r) + let last = str.lastRange(of: r) + let (expectFirst, expectLast) = ( + str.index(atOffset: 0).. Date: Fri, 22 Apr 2022 19:05:50 -0500 Subject: [PATCH 09/30] Switch FixedPatternConsumer to be over Sequence --- .../Consumers/FixedPatternConsumer.swift | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Sources/_StringProcessing/Algorithms/Consumers/FixedPatternConsumer.swift b/Sources/_StringProcessing/Algorithms/Consumers/FixedPatternConsumer.swift index e611f477a..8312c247a 100644 --- a/Sources/_StringProcessing/Algorithms/Consumers/FixedPatternConsumer.swift +++ b/Sources/_StringProcessing/Algorithms/Consumers/FixedPatternConsumer.swift @@ -9,7 +9,7 @@ // //===----------------------------------------------------------------------===// -struct FixedPatternConsumer +struct FixedPatternConsumer where Consumed.Element: Equatable, Pattern.Element == Consumed.Element { let pattern: Pattern @@ -21,20 +21,17 @@ extension FixedPatternConsumer: CollectionConsumer { in range: Range ) -> Consumed.Index? { var index = range.lowerBound - var patternIndex = pattern.startIndex + var patternIterator = pattern.makeIterator() - while true { - if patternIndex == pattern.endIndex { - return index - } - - if index == range.upperBound || consumed[index] != pattern[patternIndex] { + while let element = patternIterator.next() { + if index == range.upperBound || consumed[index] != element { return nil } consumed.formIndex(after: &index) - pattern.formIndex(after: &patternIndex) } + + return index } } From caad657fe300cee414979093387955480c310969 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 22 Apr 2022 19:19:08 -0500 Subject: [PATCH 10/30] Update Sequence/Collection constraints --- .../Algorithms/Algorithms/Contains.swift | 8 ++--- .../Algorithms/Algorithms/FirstRange.swift | 28 ++++++++------- .../Algorithms/Algorithms/Ranges.swift | 19 +++++----- .../Algorithms/Algorithms/Replace.swift | 36 +++++++++---------- .../Algorithms/Algorithms/Split.swift | 6 ++-- .../Algorithms/Algorithms/Trim.swift | 6 ++-- 6 files changed, 53 insertions(+), 50 deletions(-) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift index 1d4332ad0..96414423a 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift @@ -28,16 +28,16 @@ extension Collection where Element: Equatable { /// - 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 + public func contains(_ other: C) -> Bool + where C.Element == Element { firstRange(of: other) != nil } } extension BidirectionalCollection where Element: Comparable { - func contains(_ other: S) -> Bool - where S.Element == Element + func contains(_ other: C) -> Bool + where C.Element == Element { if #available(SwiftStdlib 5.7, *) { return firstRange(of: other) != nil diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift b/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift index 508c04663..42703827e 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift @@ -32,31 +32,33 @@ extension BidirectionalCollection { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { - /// Finds and returns the range of the first occurrence of a given sequence - /// within the collection. - /// - Parameter sequence: The sequence to search for. + /// Finds and returns the range of the first occurrence of a given collection + /// within this collection. + /// + /// - Parameter other: The collection 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 sequence: S - ) -> Range? where S.Element == Element { + public func firstRange( + of other: C + ) -> Range? where C.Element == Element { // TODO: Use a more efficient search algorithm - let searcher = ZSearcher(pattern: Array(sequence), by: ==) + let searcher = ZSearcher(pattern: Array(other), by: ==) return searcher.search(self[...], in: startIndex..( - of other: S - ) -> Range? where S.Element == Element { + public func firstRange( + of other: C + ) -> Range? where C.Element == Element { let searcher = PatternOrEmpty( searcher: TwoWaySearcher(pattern: Array(other))) let slice = self[...] diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift index 853c73271..33a9748ac 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift @@ -175,9 +175,9 @@ extension BidirectionalCollection { // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { - func ranges( - of other: S - ) -> RangesCollection> where S.Element == Element { + func ranges( + of other: C + ) -> RangesCollection> where C.Element == Element { ranges(of: ZSearcher(pattern: Array(other), by: ==)) } @@ -188,9 +188,9 @@ extension Collection where Element: Equatable { /// - Returns: A collection of ranges of all occurrences of `other`. Returns /// an empty collection if `other` is not found. @available(SwiftStdlib 5.7, *) - public func ranges( - of other: S - ) -> [Range] where S.Element == Element { + public func ranges( + of other: C + ) -> [Range] where C.Element == Element { ranges(of: ZSearcher(pattern: Array(other), by: ==)).map { $0 } } } @@ -207,10 +207,10 @@ extension BidirectionalCollection where Element: Equatable { } extension BidirectionalCollection where Element: Comparable { - func ranges( - of other: S + func ranges( + of other: C ) -> RangesCollection>> - where S.Element == Element + where C.Element == Element { ranges(of: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other)))) } @@ -247,6 +247,7 @@ extension BidirectionalCollection where SubSequence == Substring { // FIXME: Return `some Collection>` for SE-0346 /// Finds and returns the ranges of the all occurrences of a given sequence /// within the collection. + /// /// - Parameter regex: The regex to search for. /// - Returns: A collection or ranges in the receiver of all occurrences of /// `regex`. Returns an empty collection if `regex` is not found. diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift index 4a6da6c10..217fb90d6 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift @@ -78,12 +78,12 @@ extension RangeReplaceableCollection where Element: Equatable { /// - 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, + public func replacing( + _ other: C, with replacement: Replacement, subrange: Range, maxReplacements: Int = .max - ) -> Self where S.Element == Element, Replacement.Element == Element { + ) -> Self where C.Element == Element, Replacement.Element == Element { replacing( ZSearcher(pattern: Array(other), by: ==), with: replacement, @@ -101,11 +101,11 @@ extension RangeReplaceableCollection where Element: Equatable { /// - 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, + public func replacing( + _ other: C, with replacement: Replacement, maxReplacements: Int = .max - ) -> Self where S.Element == Element, Replacement.Element == Element { + ) -> Self where C.Element == Element, Replacement.Element == Element { replacing( other, with: replacement, @@ -120,11 +120,11 @@ extension RangeReplaceableCollection where Element: Equatable { /// - maxReplacements: A number specifying how many occurrences of `other` /// to replace. Default is `Int.max`. @available(SwiftStdlib 5.7, *) - public mutating func replace( - _ other: S, + public mutating func replace( + _ other: C, with replacement: Replacement, maxReplacements: Int = .max - ) where S.Element == Element, Replacement.Element == Element { + ) where C.Element == Element, Replacement.Element == Element { self = replacing( other, with: replacement, @@ -136,12 +136,12 @@ extension RangeReplaceableCollection where Element: Equatable { extension RangeReplaceableCollection where Self: BidirectionalCollection, Element: Comparable { - func replacing( - _ other: S, + func replacing( + _ other: C, with replacement: Replacement, subrange: Range, maxReplacements: Int = .max - ) -> Self where S.Element == Element, Replacement.Element == Element { + ) -> Self where C.Element == Element, Replacement.Element == Element { replacing( PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other))), with: replacement, @@ -149,11 +149,11 @@ extension RangeReplaceableCollection maxReplacements: maxReplacements) } - func replacing( - _ other: S, + func replacing( + _ other: C, with replacement: Replacement, maxReplacements: Int = .max - ) -> Self where S.Element == Element, Replacement.Element == Element { + ) -> Self where C.Element == Element, Replacement.Element == Element { replacing( other, with: replacement, @@ -161,11 +161,11 @@ extension RangeReplaceableCollection maxReplacements: maxReplacements) } - mutating func replace( - _ other: S, + mutating func replace( + _ other: C, with replacement: Replacement, maxReplacements: Int = .max - ) where S.Element == Element, Replacement.Element == Element { + ) where C.Element == Element, Replacement.Element == Element { self = replacing( other, with: replacement, diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 8c7a9832d..4fd0081bb 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -266,10 +266,10 @@ extension BidirectionalCollection where Element: Equatable { } extension BidirectionalCollection where Element: Comparable { - func split( - by separator: S + func split( + by separator: C ) -> SplitCollection>> - where S.Element == Element + where C.Element == Element { split( by: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(separator)))) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift index 73a5cd554..0d7bde56b 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift @@ -188,7 +188,7 @@ extension Collection where Element: Equatable { /// - Returns: A collection containing the elements of the collection that are /// not removed by `predicate`. @available(SwiftStdlib 5.7, *) - public func trimmingPrefix( + public func trimmingPrefix( _ prefix: Prefix ) -> SubSequence where Prefix.Element == Element { trimmingPrefix(FixedPatternConsumer(pattern: prefix)) @@ -202,7 +202,7 @@ extension Collection where SubSequence == Self, Element: Equatable { /// 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( + public mutating func trimPrefix( _ prefix: Prefix ) where Prefix.Element == Element { trimPrefix(FixedPatternConsumer(pattern: prefix)) @@ -217,7 +217,7 @@ extension RangeReplaceableCollection where Element: Equatable { /// 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( + public mutating func trimPrefix( _ prefix: Prefix ) where Prefix.Element == Element { trimPrefix(FixedPatternConsumer(pattern: prefix)) From b7a021fdfa69b98879ddec371125c7675b66688e Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 22 Apr 2022 19:20:27 -0500 Subject: [PATCH 11/30] Update trim(while:) - rethrowing and nonescaping This eliminates PredicateConsumer from the implementation so that the closure can throw. --- .../Algorithms/Algorithms/Trim.swift | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift index 0d7bde56b..7411236da 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift @@ -102,21 +102,26 @@ extension RangeReplaceableCollection where Self: BidirectionalCollection { // MARK: Predicate algorithms extension Collection { - // TODO: Non-escaping and throwing - func trimmingPrefix( - while predicate: @escaping (Element) -> Bool - ) -> SubSequence { - trimmingPrefix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) + fileprivate func endOfPrefix(while predicate: (Element) throws -> Bool) rethrows -> Index { + try firstIndex(where: { try !predicate($0) }) ?? endIndex + } + + @available(SwiftStdlib 5.7, *) + public func trimmingPrefix( + while predicate: (Element) throws -> Bool + ) rethrows -> SubSequence { + let end = try endOfPrefix(while: predicate) + return self[end...] } } extension Collection where SubSequence == Self { @available(SwiftStdlib 5.7, *) public mutating func trimPrefix( - while predicate: @escaping (Element) -> Bool - ) { - trimPrefix(ManyConsumer( - base: PredicateConsumer(predicate: predicate))) + while predicate: (Element) throws -> Bool + ) throws { + let end = try endOfPrefix(while: predicate) + self = self[end...] } } @@ -124,9 +129,10 @@ extension RangeReplaceableCollection { @_disfavoredOverload @available(SwiftStdlib 5.7, *) public mutating func trimPrefix( - while predicate: @escaping (Element) -> Bool - ) { - trimPrefix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) + while predicate: (Element) throws -> Bool + ) rethrows { + let end = try endOfPrefix(while: predicate) + removeSubrange(startIndex.. Date: Fri, 22 Apr 2022 19:21:34 -0500 Subject: [PATCH 12/30] Add tests for trim methods --- Tests/RegexTests/AlgorithmsTests.swift | 55 ++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Tests/RegexTests/AlgorithmsTests.swift b/Tests/RegexTests/AlgorithmsTests.swift index 21095b4c3..b5f197950 100644 --- a/Tests/RegexTests/AlgorithmsTests.swift +++ b/Tests/RegexTests/AlgorithmsTests.swift @@ -24,6 +24,14 @@ func output(_ s: @autoclosure () -> T) { } } +func makeSingleUseSequence(element: T, count: Int) -> UnfoldSequence { + var count = count + return sequence(state: ()) { _ in + defer { count -= 1 } + return count > 0 ? element : nil + } +} + class RegexConsumerTests: XCTestCase { func testRanges() { func expectRanges( @@ -79,6 +87,53 @@ class RegexConsumerTests: XCTestCase { expectSplit("a", "", ["", "a", ""]) expectSplit("a", "x", ["a"]) expectSplit("a", "a", ["", ""]) + + func testTrim() { + func expectTrim( + _ string: String, + _ regex: String, + _ expected: Substring, + file: StaticString = #file, line: UInt = #line + ) { + let regex = try! Regex(regex) + let actual = string.trimmingPrefix(regex) + XCTAssertEqual(actual, expected, file: file, line: line) + } + + expectTrim("", "", "") + expectTrim("", "x", "") + expectTrim("a", "", "a") + expectTrim("a", "x", "a") + expectTrim("___a", "_", "__a") + expectTrim("___a", "_+", "a") + + XCTAssertEqual("".trimmingPrefix("a"), "") + XCTAssertEqual("a".trimmingPrefix("a"), "") + XCTAssertEqual("b".trimmingPrefix("a"), "b") + XCTAssertEqual("a".trimmingPrefix(""), "a") + XCTAssertEqual("___a".trimmingPrefix("_"), "__a") + XCTAssertEqual("___a".trimmingPrefix("___"), "a") + XCTAssertEqual("___a".trimmingPrefix("____"), "___a") + XCTAssertEqual("___a".trimmingPrefix("___a"), "") + + do { + let prefix = makeSingleUseSequence(element: "_" as Character, count: 5) + XCTAssertEqual("_____a".trimmingPrefix(prefix), "a") + XCTAssertEqual("_____a".trimmingPrefix(prefix), "_____a") + } + do { + let prefix = makeSingleUseSequence(element: "_" as Character, count: 5) + XCTAssertEqual("a".trimmingPrefix(prefix), "a") + // The result of this next call is technically undefined, so this + // is just to test that it doesn't crash. + XCTAssertNotEqual("_____a".trimmingPrefix(prefix), "") + } + + XCTAssertEqual("".trimmingPrefix(while: \.isWhitespace), "") + XCTAssertEqual("a".trimmingPrefix(while: \.isWhitespace), "a") + XCTAssertEqual(" ".trimmingPrefix(while: \.isWhitespace), "") + XCTAssertEqual(" a".trimmingPrefix(while: \.isWhitespace), "a") + XCTAssertEqual("a ".trimmingPrefix(while: \.isWhitespace), "a ") } func testReplace() { From d6a01e7b2e7c9df4b10a94001e07f7599cf97198 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sat, 23 Apr 2022 00:56:45 -0500 Subject: [PATCH 13/30] Add maxSplits and omitEmpty to split methods This plumbs those parameters down into the SplitCollection type, and removes Collection conformance for now because (a) we aren't using it, and (b) it looks tricky to implement properly. --- .../Algorithms/Algorithms/Split.swift | 266 +++++++++++------- Tests/RegexTests/AlgorithmsTests.swift | 84 +++++- 2 files changed, 251 insertions(+), 99 deletions(-) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 4fd0081bb..97d8c80dd 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -15,13 +15,28 @@ struct SplitCollection { public typealias Base = Searcher.Searched let ranges: RangesCollection - - init(ranges: RangesCollection) { + var maxSplits: Int + var omittingEmptySubsequences: Bool + + init( + ranges: RangesCollection, + maxSplits: Int, + omittingEmptySubsequences: Bool) + { self.ranges = ranges + self.maxSplits = maxSplits + self.omittingEmptySubsequences = omittingEmptySubsequences } - init(base: Base, searcher: Searcher) { + init( + base: Base, + searcher: Searcher, + maxSplits: Int, + omittingEmptySubsequences: Bool) + { self.ranges = base.ranges(of: searcher) + self.maxSplits = maxSplits + self.omittingEmptySubsequences = omittingEmptySubsequences } } @@ -30,97 +45,127 @@ extension SplitCollection: Sequence { let base: Base var index: Base.Index var ranges: RangesCollection.Iterator - var isDone: Bool - - init(ranges: RangesCollection) { + var maxSplits: Int + var omittingEmptySubsequences: Bool + + var splitCounter = 0 + var isDone = false + + init( + ranges: RangesCollection, + maxSplits: Int, + omittingEmptySubsequences: Bool + ) { self.base = ranges.base self.index = base.startIndex self.ranges = ranges.makeIterator() - self.isDone = false + self.maxSplits = maxSplits + self.omittingEmptySubsequences = omittingEmptySubsequences } public mutating func next() -> Base.SubSequence? { guard !isDone else { return nil } - guard let range = ranges.next() else { + /// Return the rest of base if it's non-empty or we're including + /// empty subsequences. + func finish() -> Base.SubSequence? { isDone = true - return base[index...] + return index == base.endIndex && omittingEmptySubsequences + ? nil + : base[index...] + } + + if splitCounter >= maxSplits { + return finish() } - defer { index = range.upperBound } - return base[index.. Iterator { - Iterator(ranges: ranges) - } -} - -extension SplitCollection: Collection { - public struct Index { - var start: Base.Index - var base: RangesCollection.Index - var isEndIndex: Bool - } - - public var startIndex: Index { - let base = ranges.startIndex - return Index(start: ranges.base.startIndex, base: base, isEndIndex: false) - } - - public var endIndex: Index { - Index(start: ranges.base.endIndex, base: ranges.endIndex, isEndIndex: true) - } - - public func formIndex(after index: inout Index) { - guard !index.isEndIndex else { fatalError("Cannot advance past endIndex") } - - if let range = index.base.range { - let newStart = range.upperBound - ranges.formIndex(after: &index.base) - index.start = newStart - } else { - index.isEndIndex = true - } - } - - public func index(after index: Index) -> Index { - var index = index - formIndex(after: &index) - return index - } - - public subscript(index: Index) -> Base.SubSequence { - guard !index.isEndIndex else { - fatalError("Cannot subscript using endIndex") - } - let end = index.base.range?.lowerBound ?? ranges.base.endIndex - return ranges.base[index.start.. Bool { - switch (lhs.isEndIndex, rhs.isEndIndex) { - case (false, false): - return lhs.start == rhs.start - case (let lhs, let rhs): - return lhs == rhs - } - } - - static func < (lhs: Self, rhs: Self) -> Bool { - switch (lhs.isEndIndex, rhs.isEndIndex) { - case (true, _): - return false - case (_, true): - return true - case (false, false): - return lhs.start < rhs.start - } - } -} +//extension SplitCollection: Collection { +// public struct Index { +// var start: Base.Index +// var base: RangesCollection.Index +// var isEndIndex: Bool +// } +// +// public var startIndex: Index { +// let base = ranges.startIndex +// return Index(start: ranges.base.startIndex, base: base, isEndIndex: false) +// } +// +// public var endIndex: Index { +// Index(start: ranges.base.endIndex, base: ranges.endIndex, isEndIndex: true) +// } +// +// public func formIndex(after index: inout Index) { +// guard !index.isEndIndex else { fatalError("Cannot advance past endIndex") } +// +// if let range = index.base.range { +// let newStart = range.upperBound +// ranges.formIndex(after: &index.base) +// index.start = newStart +// } else { +// index.isEndIndex = true +// } +// } +// +// public func index(after index: Index) -> Index { +// var index = index +// formIndex(after: &index) +// return index +// } +// +// public subscript(index: Index) -> Base.SubSequence { +// guard !index.isEndIndex else { +// fatalError("Cannot subscript using endIndex") +// } +// let end = index.base.range?.lowerBound ?? ranges.base.endIndex +// return ranges.base[index.start.. Bool { +// switch (lhs.isEndIndex, rhs.isEndIndex) { +// case (false, false): +// return lhs.start == rhs.start +// case (let lhs, let rhs): +// return lhs == rhs +// } +// } +// +// static func < (lhs: Self, rhs: Self) -> Bool { +// switch (lhs.isEndIndex, rhs.isEndIndex) { +// case (true, _): +// return false +// case (_, true): +// return true +// case (false, false): +// return lhs.start < rhs.start +// } +// } +//} // MARK: `ReversedSplitCollection` @@ -176,10 +221,15 @@ extension ReversedSplitCollection: Sequence { extension Collection { func split( - by separator: Searcher + by separator: Searcher, + maxSplits: Int, + omittingEmptySubsequences: Bool ) -> SplitCollection where Searcher.Searched == Self { - // TODO: `maxSplits`, `omittingEmptySubsequences`? - SplitCollection(base: self, searcher: separator) + SplitCollection( + base: self, + searcher: separator, + maxSplits: maxSplits, + omittingEmptySubsequences: omittingEmptySubsequences) } } @@ -198,9 +248,11 @@ extension BidirectionalCollection { extension Collection { // TODO: Non-escaping and throwing func split( - whereSeparator predicate: @escaping (Element) -> Bool + whereSeparator predicate: @escaping (Element) -> Bool, + maxSplits: Int, + omittingEmptySubsequences: Bool ) -> SplitCollection> { - split(by: PredicateConsumer(predicate: predicate)) + split(by: PredicateConsumer(predicate: predicate), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) } } @@ -216,9 +268,11 @@ extension BidirectionalCollection where Element: Equatable { extension Collection where Element: Equatable { func split( - by separator: Element + by separator: Element, + maxSplits: Int, + omittingEmptySubsequences: Bool ) -> SplitCollection> { - split(whereSeparator: { $0 == separator }) + split(whereSeparator: { $0 == separator }, maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) } } @@ -234,10 +288,12 @@ extension BidirectionalCollection where Element: Equatable { extension Collection where Element: Equatable { @_disfavoredOverload - func split( - by separator: S - ) -> SplitCollection> where S.Element == Element { - split(by: ZSearcher(pattern: Array(separator), by: ==)) + func split( + by separator: C, + maxSplits: Int, + omittingEmptySubsequences: Bool + ) -> SplitCollection> where C.Element == Element { + split(by: ZSearcher(pattern: Array(separator), by: ==), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) } // FIXME: Return `some Collection` for SE-0346 @@ -247,10 +303,12 @@ extension Collection where Element: Equatable { /// - Returns: A collection of subsequences, split from this collection's /// elements. @available(SwiftStdlib 5.7, *) - public func split( - by separator: S - ) -> [SubSequence] where S.Element == Element { - Array(split(by: ZSearcher(pattern: Array(separator), by: ==))) + public func split( + separator: C, + maxSplits: Int = .max, + omittingEmptySubsequences: Bool = true + ) -> [SubSequence] where C.Element == Element { + Array(split(by: ZSearcher(pattern: Array(separator), by: ==), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences)) } } @@ -267,12 +325,15 @@ extension BidirectionalCollection where Element: Equatable { extension BidirectionalCollection where Element: Comparable { func split( - by separator: C + by separator: C, + maxSplits: Int, + omittingEmptySubsequences: Bool ) -> SplitCollection>> where C.Element == Element { split( - by: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(separator)))) + by: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(separator))), + maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) } // FIXME @@ -292,9 +353,11 @@ extension BidirectionalCollection where Element: Comparable { extension BidirectionalCollection where SubSequence == Substring { @_disfavoredOverload func split( - by separator: R + by separator: R, + maxSplits: Int, + omittingEmptySubsequences: Bool ) -> SplitCollection> { - split(by: RegexConsumer(separator)) + split(by: RegexConsumer(separator), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) } func splitFromBack( @@ -303,15 +366,22 @@ extension BidirectionalCollection where SubSequence == Substring { splitFromBack(by: RegexConsumer(separator)) } - // FIXME: Return `some Collection` for SE-0346 + // TODO: Is this @_disfavoredOverload necessary? + // It prevents split(separator: String) from choosing this overload instead + // of the collection-based version when String has RegexComponent conformance + + // FIXME: Return `some Collection` for SE-0346 /// 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. + @_disfavoredOverload public func split( - by separator: R + separator: R, + maxSplits: Int = .max, + omittingEmptySubsequences: Bool = true ) -> [SubSequence] { - Array(split(by: RegexConsumer(separator))) + Array(split(by: RegexConsumer(separator), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences)) } } diff --git a/Tests/RegexTests/AlgorithmsTests.swift b/Tests/RegexTests/AlgorithmsTests.swift index b5f197950..8e424aa13 100644 --- a/Tests/RegexTests/AlgorithmsTests.swift +++ b/Tests/RegexTests/AlgorithmsTests.swift @@ -78,7 +78,7 @@ class RegexConsumerTests: XCTestCase { file: StaticString = #file, line: UInt = #line ) { let regex = try! Regex(regex) - let actual = Array(string.split(by: regex)) + let actual = Array(string.split(separator: regex, omittingEmptySubsequences: false)) XCTAssertEqual(actual, expected, file: file, line: line) } @@ -87,6 +87,88 @@ class RegexConsumerTests: XCTestCase { expectSplit("a", "", ["", "a", ""]) expectSplit("a", "x", ["a"]) expectSplit("a", "a", ["", ""]) + expectSplit("a____a____a", "_+", ["a", "a", "a"]) + expectSplit("____a____a____a____", "_+", ["", "a", "a", "a", ""]) + } + + func testSplitPermutations() throws { + let splitRegex = try Regex(#"\|"#) + XCTAssertEqual( + "a|a|||a|a".split(separator: splitRegex), + ["a", "a", "a", "a"]) + XCTAssertEqual( + "a|a|||a|a".split(separator: splitRegex, omittingEmptySubsequences: false), + ["a", "a", "", "", "a", "a"]) + XCTAssertEqual( + "a|a|||a|a".split(separator: splitRegex, maxSplits: 2), + ["a", "a", "||a|a"]) + + XCTAssertEqual( + "a|a|||a|a|||a|a|||".split(separator: "|||"), + ["a|a", "a|a", "a|a"]) + XCTAssertEqual( + "a|a|||a|a|||a|a|||".split(separator: "|||", omittingEmptySubsequences: false), + ["a|a", "a|a", "a|a", ""]) + XCTAssertEqual( + "a|a|||a|a|||a|a|||".split(separator: "|||", maxSplits: 2), + ["a|a", "a|a", "a|a|||"]) + + XCTAssertEqual( + "aaaa".split(separator: ""), + ["a", "a", "a", "a"]) + XCTAssertEqual( + "aaaa".split(separator: "", omittingEmptySubsequences: false), + ["", "a", "a", "a", "a", ""]) + XCTAssertEqual( + "aaaa".split(separator: "", maxSplits: 2), + ["a", "a", "aa"]) + XCTAssertEqual( + "aaaa".split(separator: "", maxSplits: 2, omittingEmptySubsequences: false), + ["", "a", "aaa"]) + + // Fuzzing the input and parameters + for _ in 1...1_000 { + // Make strings that look like: + // "aaaaaaa" + // "|||aaaa||||" + // "a|a|aa|aa|" + // "|a||||aaa|a|||" + // "a|aa" + let keepCount = Int.random(in: 0...10) + let splitCount = Int.random(in: 0...10) + let str = [repeatElement("a", count: keepCount), repeatElement("|", count: splitCount)] + .joined() + .shuffled() + .joined() + + let omitEmpty = Bool.random() + let maxSplits = Bool.random() ? Int.max : Int.random(in: 0...10) + + // Use the stdlib behavior as the expected outcome + let expected = str.split( + separator: "|" as Character, + maxSplits: maxSplits, + omittingEmptySubsequences: omitEmpty) + let regexActual = str.split( + separator: splitRegex, + maxSplits: maxSplits, + omittingEmptySubsequences: omitEmpty) + let stringActual = str.split( + separator: "|" as String, + maxSplits: maxSplits, + omittingEmptySubsequences: omitEmpty) + XCTAssertEqual(regexActual, expected, """ + Mismatch in regex split of '\(str)', maxSplits: \(maxSplits), omitEmpty: \(omitEmpty) + expected: \(expected.map(String.init)) + actual: \(regexActual.map(String.init)) + """) + XCTAssertEqual(stringActual, expected, """ + Mismatch in string split of '\(str)', maxSplits: \(maxSplits), omitEmpty: \(omitEmpty) + expected: \(expected.map(String.init)) + actual: \(regexActual.map(String.init)) + """) + } + } func testTrim() { func expectTrim( From e81a8bd2a9395abf3180c6826272113078202bfb Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sat, 23 Apr 2022 12:22:55 -0500 Subject: [PATCH 14/30] Add tests / fixes for contains / firstRange(of:) Better test coverage for both the regex and collection variants of these two methods, plus overloads for contains(_:) to win over Foundation's version from the overlay. Also fixes an error in TwoWaySearcher that tried to offset past the searched string's endIndex; might be a sign of something awry, but tests seem to be otherwise succeeding. --- .../Algorithms/Algorithms/Contains.swift | 14 ++++++ .../Algorithms/Searchers/TwoWaySearcher.swift | 9 +++- Tests/RegexTests/AlgorithmsTests.swift | 50 ++++++++++++++++++- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift index 96414423a..2a1ef72a2 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift @@ -46,6 +46,20 @@ extension BidirectionalCollection where Element: Comparable { } } +// Overload breakers + +extension StringProtocol { + @available(SwiftStdlib 5.7, *) + public func contains(_ other: String) -> Bool { + firstRange(of: other) != nil + } + + @available(SwiftStdlib 5.7, *) + public func contains(_ other: Substring) -> Bool { + firstRange(of: other) != nil + } +} + // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { diff --git a/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift b/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift index 5530b4421..ae613cfd7 100644 --- a/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift +++ b/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift @@ -47,8 +47,10 @@ extension TwoWaySearcher: CollectionSearcher { for searched: Searched, in range: Range ) -> State { + // FIXME: Is this 'limitedBy' requirement a sign of error? let criticalIndex = searched.index( - range.lowerBound, offsetBy: criticalIndex) + range.lowerBound, offsetBy: criticalIndex, limitedBy: range.upperBound) + ?? range.upperBound return State( end: range.upperBound, index: range.lowerBound, @@ -66,7 +68,10 @@ extension TwoWaySearcher: CollectionSearcher { let start = _searchLeft(searched, &state, end) { state.index = end - state.criticalIndex = searched.index(end, offsetBy: criticalIndex) + // FIXME: Is this 'limitedBy' requirement a sign of error? + state.criticalIndex = searched.index( + end, offsetBy: criticalIndex, limitedBy: searched.endIndex) + ?? searched.endIndex state.memory = nil return start..(element: T, count: Int) -> UnfoldSequence } } -class RegexConsumerTests: XCTestCase { +class AlgorithmTests: XCTestCase { + func testContains() { + XCTAssertTrue("".contains("")) + XCTAssertTrue("abcde".contains("")) + XCTAssertTrue("abcde".contains("abcd")) + XCTAssertTrue("abcde".contains("bcde")) + XCTAssertTrue("abcde".contains("bcd")) + XCTAssertTrue("ababacabababa".contains("abababa")) + + XCTAssertFalse("".contains("abcd")) + + for start in 0..<9 { + for end in start..<9 { + XCTAssertTrue((0..<10).contains(start...end)) + XCTAssertFalse((0..<10).contains(start...10)) + } + } + } + func testRanges() { func expectRanges( _ string: String, @@ -48,6 +66,9 @@ class RegexConsumerTests: XCTestCase { // `IndexingIterator` tests the collection conformance let actualCol: [Range] = string[...].ranges(of: regex)[...].map(string.offsets(of:)) XCTAssertEqual(actualCol, expected, file: file, line: line) + + let firstRange = string.firstRange(of: regex).map(string.offsets(of:)) + XCTAssertEqual(firstRange, expected.first, file: file, line: line) } expectRanges("", "", [0..<0]) @@ -68,6 +89,31 @@ class RegexConsumerTests: XCTestCase { expectRanges("abc", "(a|b)*", [0..<2, 2..<2, 3..<3]) expectRanges("abc", "(b|c)+", [1..<3]) expectRanges("abc", "(b|c)*", [0..<0, 1..<3, 3..<3]) + + func expectStringRanges( + _ input: String, + _ pattern: String, + _ expected: [Range], + file: StaticString = #file, line: UInt = #line + ) { + let actualSeq: [Range] = input.ranges(of: pattern).map(input.offsets(of:)) + XCTAssertEqual(actualSeq, expected, file: file, line: line) + + // `IndexingIterator` tests the collection conformance + let actualCol: [Range] = input.ranges(of: pattern)[...].map(input.offsets(of:)) + XCTAssertEqual(actualCol, expected, file: file, line: line) + + let firstRange = input.firstRange(of: pattern).map(input.offsets(of:)) + XCTAssertEqual(firstRange, expected.first, file: file, line: line) + } + + expectStringRanges("", "", [0..<0]) + expectStringRanges("abcde", "", [0..<0, 1..<1, 2..<2, 3..<3, 4..<4, 5..<5]) + expectStringRanges("abcde", "abcd", [0..<4]) + expectStringRanges("abcde", "bcde", [1..<5]) + expectStringRanges("abcde", "bcd", [1..<4]) + expectStringRanges("ababacabababa", "abababa", [6..<13]) + expectStringRanges("ababacabababa", "aba", [0..<3, 6..<9, 10..<13]) } func testSplit() { From 9e09bf8c8ee5aebe43be9ba6a9a73a0970eebbfc Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Sun, 24 Apr 2022 12:48:48 -0500 Subject: [PATCH 15/30] Test to ensure stdlib `split` is still accessible --- Tests/RegexTests/AlgorithmsTests.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tests/RegexTests/AlgorithmsTests.swift b/Tests/RegexTests/AlgorithmsTests.swift index c42ff175f..965e2c42e 100644 --- a/Tests/RegexTests/AlgorithmsTests.swift +++ b/Tests/RegexTests/AlgorithmsTests.swift @@ -135,6 +135,12 @@ class AlgorithmTests: XCTestCase { expectSplit("a", "a", ["", ""]) expectSplit("a____a____a", "_+", ["a", "a", "a"]) expectSplit("____a____a____a____", "_+", ["", "a", "a", "a", ""]) + + // Test that original `split` functions are still accessible + let splitRef = "abcd".split + XCTAssert(type(of: splitRef) == ((Character, Int, Bool) -> [Substring]).self) + let splitParamsRef = "abcd".split(separator:maxSplits:omittingEmptySubsequences:) + XCTAssert(type(of: splitParamsRef) == ((Character, Int, Bool) -> [Substring]).self) } func testSplitPermutations() throws { From 433740b885f5a8012c89ee5d6cc08b92e4ba7ad7 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 25 Apr 2022 10:06:19 -0600 Subject: [PATCH 16/30] Fix stale links --- Documentation/Evolution/RegexSyntaxRunTimeConstruction.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/Evolution/RegexSyntaxRunTimeConstruction.md b/Documentation/Evolution/RegexSyntaxRunTimeConstruction.md index 5c9fa6c59..bee7bbf03 100644 --- a/Documentation/Evolution/RegexSyntaxRunTimeConstruction.md +++ b/Documentation/Evolution/RegexSyntaxRunTimeConstruction.md @@ -12,7 +12,7 @@ A regex declares a string processing algorithm using syntax familiar across a variety of languages and tools throughout programming history. We propose the ability to create a regex at run time from a string containing regex syntax (detailed here), API for accessing the match and captures, and a means to convert between an existential capture representation and concrete types. -The overall story is laid out in [Regex Type and Overview][overview] and each individual component is tracked in [Pitch and Proposal Status](https://github.com/apple/swift-experimental-string-processing/issues/107). +The overall story is laid out in [SE-0350 Regex Type and Overview][overview] and each individual component is tracked in [Pitch and Proposal Status][pitches]. ## Motivation @@ -341,7 +341,7 @@ BuiltinCharClass -> '.' | '\C' | '\d' | '\D' | '\h' | '\H' | '\N' | '\O' | '\R' - `\W`: Non-word character. - `\X`: Any extended grapheme cluster. -Precise definitions of character classes is discussed in [Character Classes for String Processing](https://forums.swift.org/t/pitch-character-classes-for-string-processing/52920). +Precise definitions of character classes is discussed in [Unicode for String Processing][pitches]. #### Unicode scalars @@ -1009,8 +1009,8 @@ This proposal regards _syntactic_ support, and does not necessarily mean that ev [unicode-scripts]: https://www.unicode.org/reports/tr24/#Script [unicode-script-extensions]: https://www.unicode.org/reports/tr24/#Script_Extensions [balancing-groups]: https://docs.microsoft.com/en-us/dotnet/standard/base-types/grouping-constructs-in-regular-expressions#balancing-group-definitions -[overview]: https://github.com/apple/swift-experimental-string-processing/blob/main/Documentation/Evolution/RegexTypeOverview.md -[pitches]: https://github.com/apple/swift-experimental-string-processing/issues/107 +[overview]: https://github.com/apple/swift-evolution/blob/main/proposals/0350-regex-type-overview.md +[pitches]: https://github.com/apple/swift-experimental-string-processing/blob/main/Documentation/Evolution/ProposalOverview.md From 8dce8c2993ba4bc0181cda05ae0c25b46a06d01e Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 25 Apr 2022 10:12:25 -0600 Subject: [PATCH 17/30] Mention API naming consistency (#341) * Mention API naming consistency --- .../Evolution/StringProcessingAlgorithms.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index 0539d46ca..cee6104e2 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -835,6 +835,46 @@ extension RangeReplaceableCollection where Element: Equatable { Most of the proposed algorithms are necessarily on `Collection` due to the use of indices or mutation. `Sequence` does not support multi-pass iteration, so even `trimPrefix` would problematic on `Sequence` because it needs to look 1 `Element` ahead to know when to stop trimming. +### Cross-proposal API naming consistency + +The regex work is broken down into 6 proposals based on technical domain, which is advantageous for deeper technical discussions and makes reviewing the large body of work manageable. The disadvantage of this approach is that relatively-shallow cross-cutting concerns, such as API naming consistency, are harder to evaluate until we've built up intuition from multiple proposals. + +We've seen the [Regex type and overview](https://github.com/apple/swift-evolution/blob/main/proposals/0350-regex-type-overview.md), the [Regex builder DSL](https://github.com/apple/swift-evolution/blob/main/proposals/0351-regex-builder.md), and here we present lots of ways to use regex. Now's a good time to go over API naming consistency. + +(The other proposal with a significant amount of API is [Unicode for String Processing](https://forums.swift.org/t/pitch-unicode-for-string-processing/56907), which is in the pitch phase. It is a technical niche and less impactful on these naming discussions. We'll still want to design those names for consistency, of course.) + + +```swift +protocol RegexComponent { + associatedtype RegexOutput +} +``` + +The associatedtype name is "RegexOutput" to help libraries conform their parsers to this protocol (e.g. via `CustomConsumingRegexComponent`). Regex's capture representation is regexy: it has the overall matched portion as the first capture and the regex builders know how to combine these kinds of capture lists together. This could be different than how e.g. a parser combinator library's output types might be represented. Thus, we chose a more specific name to avoid any potential conflicts. + +The name "RegexComponent" accentuates that any conformer can be used as part of a larger regex, while it de-emphasizes that `Regex` instances themselves can be used directly. We propose methods that are generic over `RegexComponent` and developers will be considering whether they should make their functions that otherwise take a `Regex` also be generic over `RegexComponent`. + +It's possible there might be some initial confusion around the word "component", i.e. a developer may have a regex and not be sure how to make it into a component or how to get the component out. The word "component" carries a lot of value in the context of the regex DSL. An alternative name might be `RegexProtocol`, which implies that a Regex can be used at the site and would be clearly the way to make a function taking a concrete `Regex` generic. But, it's otherwise a naming workaround that doesn't carry the additional regex builder connotations. + +The protocol requirement is `var regex: Regex`, i.e. any type that can produce a regex or hook into the engine's customization hooks (this is what `consuming` does) can be used as a component of the DSL and with these generic API. An alternative name could be "CustomRegexConvertible", but we don't feel that communicates component composability very well, nor is it particularly enlightening when encountering these generic API. + +Another alternative is to have a second protocol just for generic API. But without a compelling semantic distinction or practical utility, we'd prefer to avoid adding protocols just for names. If a clearly superior name exists, we should just choose that. + + +```swift +protocol CustomConsumingRegexComponent { + func consuming(...) +} +``` + +This is not a normal developer-facing protocol or concept; it's an advanced library-extensibility feature. Explicit, descriptive, and careful names are more important than concise names. The "custom" implies that we're not just vending a regex directly ourselves, we're instead customizing behavior by hooking into the run-time engine directly. + +Older versions of the pitch had `func match(...) -> (String.Index, T)?` as the protocol requirement. As [Regex type and overview](https://github.com/apple/swift-evolution/blob/main/proposals/0350-regex-type-overview.md) went through review, naming convention settled on using the word "match" as a noun and in context with operations that produce a `Match` instance. Since this is the engine's customization hook, it produces the value and position to resume execution from directly, and hence different terminology is apt and avoids confusion or future ambiguities. "Consuming" is the nomenclature we're going with for something that chews off the front of its input in order to produces a value. + +This protocol customizes the basic consume-from-the-front functionality. A protocol for customizing search is future work and involves accommodating different kinds of state and ways that a searcher may wish to speed up subsequent searches. Alternative names for the protocol include `CustomRegexComponent`, `CustomConsumingRegex`, etc., but we don't feel brevity is the key consideration here. + + + ## Future directions ### Backward algorithms From 1fd5115d7fac901f892f0cae9fd3891682ce9ea9 Mon Sep 17 00:00:00 2001 From: Richard Wei Date: Sat, 23 Apr 2022 16:43:07 -0700 Subject: [PATCH 18/30] Generic `~=` operator Make `~=` generic over `RegexComponent` so that one can use builder components, e.g. `OneOrMore(...)`, or custom-consuming regex components as patterns. --- Sources/_StringProcessing/Regex/Core.swift | 7 +++ Sources/_StringProcessing/Regex/Match.swift | 20 ++----- Tests/RegexBuilderTests/AlgorithmsTests.swift | 57 +++++++++++++++++++ 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/Sources/_StringProcessing/Regex/Core.swift b/Sources/_StringProcessing/Regex/Core.swift index d77784df4..36d62f674 100644 --- a/Sources/_StringProcessing/Regex/Core.swift +++ b/Sources/_StringProcessing/Regex/Core.swift @@ -61,6 +61,13 @@ public struct Regex: RegexComponent { } } +@available(SwiftStdlib 5.7, *) +extension Regex { + public init(quoting string: String) { + self.init(node: .quotedLiteral(string)) + } +} + @available(SwiftStdlib 5.7, *) extension Regex { /// A program representation that caches any lowered representation for diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 39ff7ece9..45df7aeaa 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -180,20 +180,12 @@ extension BidirectionalCollection where SubSequence == Substring { } @available(SwiftStdlib 5.7, *) -extension Regex { - public init(quoting string: String) { - self.init(node: .quotedLiteral(string)) +extension RegexComponent { + public static func ~=(regex: Self, input: String) -> Bool { + input.wholeMatch(of: regex) != nil } -} -@available(SwiftStdlib 5.7, *) -public func ~=(regex: Regex, input: String) -> Bool { - guard let _ = try? regex.wholeMatch(in: input) else { return false } - return true -} - -@available(SwiftStdlib 5.7, *) -public func ~=(regex: Regex, input: Substring) -> Bool { - guard let _ = try? regex.wholeMatch(in: input) else { return false } - return true + public static func ~=(regex: Self, input: Substring) -> Bool { + input.wholeMatch(of: regex) != nil + } } diff --git a/Tests/RegexBuilderTests/AlgorithmsTests.swift b/Tests/RegexBuilderTests/AlgorithmsTests.swift index 5a7a69fac..97fccde01 100644 --- a/Tests/RegexBuilderTests/AlgorithmsTests.swift +++ b/Tests/RegexBuilderTests/AlgorithmsTests.swift @@ -104,4 +104,61 @@ class RegexConsumerTests: XCTestCase { result: "9+16, 3, 10, 99+1") ) } + + func testSwitches() { + // Failure cases + do { + switch "abcde" { + case Regex { + "a" + ZeroOrMore(.any) + "f" + }: + XCTFail() + + case "abc": + XCTFail() + + case Regex { + "a" + "b" + "c" + }: + XCTFail() + + default: + break + } + } + // Success cases + do { + let input = "abcde" + + switch input { + case Regex { + "a" + ZeroOrMore(.any) + "e" + }: + break + + default: + XCTFail() + } + + guard case Regex({ + "a" + ZeroOrMore(.any) + "e" + }) = input else { + XCTFail() + return + } + + guard case OneOrMore(.word) = input else { + XCTFail() + return + } + } + } } From 5af1427872057dd7928ad133a7238809e8ba5471 Mon Sep 17 00:00:00 2001 From: Tina Liu <49205802+itingliu@users.noreply.github.com> Date: Mon, 25 Apr 2022 15:36:07 -0700 Subject: [PATCH 19/30] Add `@RegexComponentBuilder` overloads for collection algorithms (#342) * Add `@RegexComponentBuilder` overloads for collection algorithms - Add overloads per string processing proposal - Update doc comments - Add tests that uses the builder - Rename `Match.swift` to `Algorithms.swift` as it contains more than match functions now * Update the proposal as well --- .../Evolution/StringProcessingAlgorithms.md | 230 +++++++----- Sources/RegexBuilder/Algorithms.swift | 310 ++++++++++++++++ Sources/RegexBuilder/Match.swift | 45 --- Tests/RegexBuilderTests/AlgorithmsTests.swift | 338 +++++++++++++++++- 4 files changed, 784 insertions(+), 139 deletions(-) create mode 100644 Sources/RegexBuilder/Algorithms.swift delete mode 100644 Sources/RegexBuilder/Match.swift diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index cee6104e2..eee05e3a7 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -246,12 +246,13 @@ extension BidirectionalCollection where SubSequence == Substring { /// `false`. public func contains(_ regex: some RegexComponent) -> Bool - /// Returns a Boolean value indicating whether the collection contains the - /// given regex. - /// - Parameter content: A closure to produce a `RegexComponent` to search for - /// within this collection. - /// - Returns: `true` if the regex was found in the collection, otherwise - /// `false`. + /// Returns a Boolean value indicating whether this collection contains a + /// match for the regex, where the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to search for within + /// this collection. + /// - Returns: `true` if the regex returned by `content` matched anywhere in + /// this collection, otherwise `false`. public func contains( @RegexComponentBuilder _ content: () -> some RegexComponent ) -> Bool @@ -269,11 +270,13 @@ extension BidirectionalCollection where SubSequence == Substring { /// beginning of `regex`; otherwise, `false`. public func starts(with regex: some RegexComponent) -> Bool - /// Returns a Boolean value indicating whether the initial elements of the - /// sequence are the same as the elements in the specified regex. - /// - Parameter content: A closure to produce a `RegexComponent` to compare. - /// - Returns: `true` if the initial elements of the sequence matches the - /// beginning of `regex`; otherwise, `false`. + /// Returns a Boolean value indicating whether the initial elements of this + /// collection are a match for the regex created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to match at + /// the beginning of this collection. + /// - Returns: `true` if the initial elements of this collection match + /// regex returned by `content`; otherwise, `false`. public func starts( @RegexComponentBuilder with content: () -> some RegexComponent ) -> Bool @@ -344,11 +347,16 @@ extension BidirectionalCollection where SubSequence == Substring { /// that does not match `prefix` from the start. public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence - /// Returns a new collection of the same type by removing `prefix` from the - /// start. - /// - Parameter _content A closure to produce a `RegexComponent` to be removed. - /// - Returns: A collection containing the elements that does not match - /// `prefix` from the start. + /// Returns a subsequence of this collection by removing the elements + /// matching the regex from the start, where the regex is created by + /// the given closure. + /// + /// - Parameter content: A closure that returns the regex to search for at + /// the start of this collection. + /// - Returns: A collection containing the elements after those that match + /// the regex returned by `content`. If the regex does not match at + /// the start of the collection, the entire contents of this collection + /// are returned. public func trimmingPrefix( @RegexComponentBuilder _ content: () -> some RegexComponent ) -> SubSequence @@ -361,8 +369,12 @@ extension RangeReplaceableCollection /// - Parameter regex: The regex to remove from this collection. public mutating func trimPrefix(_ regex: some RegexComponent) - /// Removes the initial elements that matches the given regex. - /// - Parameter content: A closure to produce a `RegexComponent` to be removed. + /// Removes the initial elements matching the regex from the start of + /// this collection, if the initial elements match, using the given closure + /// to create the regex. + /// + /// - Parameter content: A closure that returns the regex to search for + /// at the start of this collection. public mutating func trimPrefix( @RegexComponentBuilder _ content: () -> some RegexComponent ) @@ -400,12 +412,13 @@ extension BidirectionalCollection where SubSequence == Substring { /// Returns `nil` if `regex` is not found. public func firstRange(of regex: some RegexComponent) -> Range? - /// Finds and returns the range of the first occurrence of a given regex - /// within the collection. - /// - Parameter content: A closure to produce a `RegexComponent` to search for - /// within this collection. - /// - Returns: A range in the collection of the first occurrence of regex. - /// Returns `nil` if not found. + /// Returns the range of the first match for the regex within this collection, + /// where the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to search for. + /// - Returns: A range in the collection of the first occurrence of the first + /// match of if the regex returned by `content`. Returns `nil` if no match + /// for the regex is found. public func firstRange( @RegexComponentBuilder of content: () -> some RegexComponent ) -> Range? @@ -433,12 +446,13 @@ extension BidirectionalCollection where SubSequence == Substring { /// `regex`. Returns an empty collection if `regex` is not found. public func ranges(of regex: some RegexComponent) -> some Collection> - /// Finds and returns the ranges of the all occurrences of a given sequence - /// within the collection. - /// - Parameter content: A closure to produce a `RegexComponent` to search for - /// within this collection. - /// - Returns: A collection or ranges in the receiver of all occurrences of - /// regex. Returns an empty collection if not found. + /// Returns the ranges of the all non-overlapping matches for the regex + /// within this collection, where the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to search for. + /// - Returns: A collection of ranges of all matches for the regex returned by + /// `content`. Returns an empty collection if no match for the regex + /// is found. public func ranges( @RegexComponentBuilder of content: () -> some RegexComponent ) -> some Collection> @@ -455,10 +469,12 @@ extension BidirectionalCollection where SubSequence == Substring { /// there isn't a match. public func firstMatch(of regex: R) -> Regex.Match? - /// Returns the first match of the specified regex within the collection. - /// - Parameter content: A closure to produce a `RegexComponent` to search for. - /// - Returns: The first match of regex in the collection, or `nil` if - /// there isn't a match. + /// Returns the first match for the regex within this collection, where + /// the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns the regex to search for. + /// - Returns: The first match for the regex created by `content` in this + /// collection, or `nil` if no match is found. public func firstMatch( @RegexComponentBuilder of content: () -> R ) -> Regex.Match? @@ -468,8 +484,10 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: The match if there is one, or `nil` if none. public func wholeMatch(of regex: R) -> Regex.Match? - /// Match a regex in its entirety. - /// - Parameter content: A closure to produce a `RegexComponent` to match against. + /// Matches a regex in its entirety, where the regex is created by + /// the given closure. + /// + /// - Parameter content: A closure that returns a regex to match against. /// - Returns: The match if there is one, or `nil` if none. public func wholeMatch( @RegexComponentBuilder of content: () -> R @@ -480,8 +498,10 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: The match if there is one, or `nil` if none. public func prefixMatch(of regex: R) -> Regex.Match? - /// Match part of the regex, starting at the beginning. - /// - Parameter content: A closure to produce a `RegexComponent` to match against. + /// Matches part of the regex, starting at the beginning, where the regex + /// is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to match against. /// - Returns: The match if there is one, or `nil` if none. public func prefixMatch( @RegexComponentBuilder of content: () -> R @@ -498,9 +518,12 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: A collection of matches of `regex`. public func matches(of regex: R) -> some Collection.Match> - /// Returns a collection containing all matches of the specified regex. - /// - Parameter content: A closure to produce a `RegexComponent` to search for. - /// - Returns: A collection of matches of `regex`. + /// Returns a collection containing all non-overlapping matches of + /// the regex, created by the given closure. + /// + /// - Parameter content: A closure that returns the regex to search for. + /// - Returns: A collection of matches for the regex returned by `content`. + /// If no matches are found, the returned collection is empty. public func matches( @RegexComponentBuilder of content: () -> R ) -> some Collection.Match> @@ -574,16 +597,20 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max ) -> Self where Replacement.Element == Element - /// Returns a new collection in which all occurrences of a sequence matching - /// the given regex are replaced by another collection. + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closure to create the regex. + /// /// - Parameters: - /// - 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`. - /// - content: A closure to produce a `RegexComponent` to replace. - /// - Returns: A new collection in which all occurrences of subsequence - /// matching `regex` in `subrange` are replaced by `replacement`. + /// - replacement: The new elements to add to the collection in place of + /// each match for the regex, using `content` to create the regex. + /// - subrange: The range in the collection in which to search for + /// the regex. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by `replacement`, using `content` to create the regex. public func replacing( with replacement: Replacement, subrange: Range, @@ -606,15 +633,18 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max ) -> Self where Replacement.Element == Element - /// Returns a new collection in which all occurrences of a sequence matching - /// the given regex are replaced by another collection. + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closure to create the regex. + /// /// - Parameters: - /// - 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`. - /// - content: A closure to produce a `RegexComponent` to replace. - /// - Returns: A new collection in which all occurrences of subsequence - /// matching `regex` are replaced by `replacement`. + /// - replacement: The new elements to add to the collection in place of + /// each match for the regex, using `content` to create the regex. + /// - maxReplacements: A number specifying how many occurrences of regex + /// to replace. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by `replacement`, using `content` to create the regex. public func replacing( with replacement: Replacement, maxReplacements: Int = .max, @@ -634,18 +664,21 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max ) where Replacement.Element == Element - /// Replaces all occurrences of the sequence matching the given regex with - /// a given collection. + /// Replaces all matches for the regex in this collection, using the given + /// closure to create the regex. + /// /// - Parameters: - /// - 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`. - /// - content: A closure to produce a `RegexComponent` to replace. + /// - replacement: The new elements to add to the collection in place of + /// each match for the regex, using `content` to create the regex. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace. + /// - content: A closure that returns the collection to search for + /// and replace. public mutating func replace( with replacement: Replacement, maxReplacements: Int = .max, @RegexComponentBuilder content: () -> some RegexComponent - ) -> Self where Replacement.Element == Element + ) where Replacement.Element == Element /// Returns a new collection in which all occurrences of a sequence matching /// the given regex are replaced by another regex match. @@ -664,18 +697,23 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max, with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element - - /// Returns a new collection in which all occurrences of a sequence matching - /// the given regex are replaced by another regex match. + + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closures to create the replacement + /// and the regex. + /// /// - Parameters: - /// - 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`. - /// - content: A closure to produce a `RegexComponent` to replace. + /// - subrange: The range in the collection in which to search for the + /// regex, using `content` to create the regex. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace. + /// - content: A closure that returns the collection to search for + /// and replace. /// - replacement: A closure that receives the full match information, - /// including captures, and returns a replacement collection. - /// - Returns: A new collection in which all occurrences of subsequence - /// matching `regex` are replaced by `replacement`. + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by the result of calling `replacement`, where regex + /// is the result of calling `content`. public func replacing( subrange: Range, maxReplacements: Int = .max, @@ -699,16 +737,20 @@ extension RangeReplaceableCollection where SubSequence == Substring { with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element - /// Returns a new collection in which all occurrences of a sequence matching - /// the given regex are replaced by another collection. + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closures to create the replacement + /// and the regex. + /// /// - Parameters: - /// - maxReplacements: A number specifying how many occurrences of the - /// sequence matching `regex` to replace. Default is `Int.max`. - /// - content: A closure to produce a `RegexComponent` to replace. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace, using `content` to create the regex. + /// - content: A closure that returns the collection to search for + /// and replace. /// - replacement: A closure that receives the full match information, /// including captures, and returns a replacement collection. - /// - Returns: A new collection in which all occurrences of subsequence - /// matching `regex` are replaced by `replacement`. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by the result of calling `replacement`, where regex is + /// the result of calling `content`. public func replacing( maxReplacements: Int = .max, @RegexComponentBuilder content: () -> R, @@ -728,15 +770,17 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max, with replacement: (Regex.Match) throws -> Replacement ) rethrows where Replacement.Element == Element - - /// Replaces all occurrences of the sequence matching the given regex with - /// a given collection. + + /// Replaces all matches for the regex in this collection, using the + /// given closures to create the replacement and the regex. + /// /// - Parameters: - /// - maxReplacements: A number specifying how many occurrences of the - /// sequence matching `regex` to replace. Default is `Int.max`. - /// - content: A closure to produce a `RegexComponent` to replace. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace, using `content` to create the regex. + /// - content: A closure that returns the collection to search for + /// and replace. /// - replacement: A closure that receives the full match information, - /// including captures, and returns a replacement collection. + /// including captures, and returns a replacement collection. public mutating func replace( maxReplacements: Int = .max, @RegexComponentBuilder content: () -> R, @@ -791,16 +835,16 @@ extension BidirectionalCollection where SubSequence == Substring { ) -> some Collection /// Returns the longest possible subsequences of the collection, in order, - /// around subsequence that match the given separator regex. + /// around subsequence that match the regex created by the given closure. /// /// - Parameters: - /// - maxSplits: The maximum number of times to split the collection, + /// - maxSplits: The maximum number of times to split the collection, /// or one less than the number of subsequences to return. - /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// - omittingEmptySubsequences: If `false`, an empty subsequence is /// returned in the result for each consecutive pair of matches /// and for each match at the start or end of the collection. If /// `true`, only nonempty subsequences are returned. - /// - separator: A closure to produce a `RegexComponent` to be split upon. + /// - separator: A closure that returns a regex to be split upon. /// - Returns: A collection of substrings, split from this collection's /// elements. public func split( diff --git a/Sources/RegexBuilder/Algorithms.swift b/Sources/RegexBuilder/Algorithms.swift new file mode 100644 index 000000000..f206ee768 --- /dev/null +++ b/Sources/RegexBuilder/Algorithms.swift @@ -0,0 +1,310 @@ +//===----------------------------------------------------------------------===// +// +// 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 _StringProcessing + +extension BidirectionalCollection where SubSequence == Substring { + /// Matches a regex in its entirety, where the regex is created by + /// the given closure. + /// + /// - Parameter content: A closure that returns a regex to match against. + /// - Returns: The match if there is one, or `nil` if none. + @available(SwiftStdlib 5.7, *) + public func wholeMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + wholeMatch(of: content()) + } + + /// Matches part of the regex, starting at the beginning, where the regex + /// is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to match against. + /// - Returns: The match if there is one, or `nil` if none. + @available(SwiftStdlib 5.7, *) + public func prefixMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + prefixMatch(of: content()) + } + + /// Returns a Boolean value indicating whether this collection contains a + /// match for the regex, where the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to search for within + /// this collection. + /// - Returns: `true` if the regex returned by `content` matched anywhere in + /// this collection, otherwise `false`. + @available(SwiftStdlib 5.7, *) + public func contains( + @RegexComponentBuilder _ content: () -> R + ) -> Bool { + contains(content()) + } + + /// Returns the range of the first match for the regex within this collection, + /// where the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to search for. + /// - Returns: A range in the collection of the first occurrence of the first + /// match of if the regex returned by `content`. Returns `nil` if no match + /// for the regex is found. + @available(SwiftStdlib 5.7, *) + public func firstRange( + @RegexComponentBuilder of content: () -> R + ) -> Range? { + firstRange(of: content()) + } + + // FIXME: Return `some Collection>` for SE-0346 + /// Returns the ranges of the all non-overlapping matches for the regex + /// within this collection, where the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to search for. + /// - Returns: A collection of ranges of all matches for the regex returned by + /// `content`. Returns an empty collection if no match for the regex + /// is found. + @available(SwiftStdlib 5.7, *) + public func ranges( + @RegexComponentBuilder of content: () -> R + ) -> [Range] { + ranges(of: content()) + } + + // FIXME: Return `some Collection` for SE-0346 + /// Returns the longest possible subsequences of the collection, in order, + /// around subsequence that match the regex created by the given closure. + /// + /// - Parameters: + /// - maxSplits: The maximum number of times to split the collection, + /// or one less than the number of subsequences to return. + /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// returned in the result for each consecutive pair of matches + /// and for each match at the start or end of the collection. If + /// `true`, only nonempty subsequences are returned. + /// - separator: A closure that returns a regex to be split upon. + /// - Returns: A collection of substrings, split from this collection's + /// elements. + @available(SwiftStdlib 5.7, *) + public func split( + maxSplits: Int = Int.max, + omittingEmptySubsequences: Bool = true, + @RegexComponentBuilder separator: () -> some RegexComponent + ) -> [SubSequence] { + split(separator: separator(), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) + } + + /// Returns a Boolean value indicating whether the initial elements of this + /// collection are a match for the regex created by the given closure. + /// + /// - Parameter content: A closure that returns a regex to match at + /// the beginning of this collection. + /// - Returns: `true` if the initial elements of this collection match + /// regex returned by `content`; otherwise, `false`. + @available(SwiftStdlib 5.7, *) + public func starts( + @RegexComponentBuilder with content: () -> R + ) -> Bool { + starts(with: content()) + } + + /// Returns a subsequence of this collection by removing the elements + /// matching the regex from the start, where the regex is created by + /// the given closure. + /// + /// - Parameter content: A closure that returns the regex to search for at + /// the start of this collection. + /// - Returns: A collection containing the elements after those that match + /// the regex returned by `content`. If the regex does not match at + /// the start of the collection, the entire contents of this collection + /// are returned. + @available(SwiftStdlib 5.7, *) + public func trimmingPrefix( + @RegexComponentBuilder _ content: () -> R + ) -> SubSequence { + trimmingPrefix(content()) + } + + /// Returns the first match for the regex within this collection, where + /// the regex is created by the given closure. + /// + /// - Parameter content: A closure that returns the regex to search for. + /// - Returns: The first match for the regex created by `content` in this + /// collection, or `nil` if no match is found. + @available(SwiftStdlib 5.7, *) + public func firstMatch( + @RegexComponentBuilder of content: () -> R + ) -> Regex.Match? { + firstMatch(of: content()) + } + + // FIXME: Return `some Collection.Match> for SE-0346 + /// Returns a collection containing all non-overlapping matches of + /// the regex, created by the given closure. + /// + /// - Parameter content: A closure that returns the regex to search for. + /// - Returns: A collection of matches for the regex returned by `content`. + /// If no matches are found, the returned collection is empty. + @available(SwiftStdlib 5.7, *) + public func matches( + @RegexComponentBuilder of content: () -> R + ) -> [Regex.Match] { + matches(of: content()) + } +} + +extension RangeReplaceableCollection +where Self: BidirectionalCollection, SubSequence == Substring { + /// Removes the initial elements matching the regex from the start of + /// this collection, if the initial elements match, using the given closure + /// to create the regex. + /// + /// - Parameter content: A closure that returns the regex to search for + /// at the start of this collection. + @available(SwiftStdlib 5.7, *) + public mutating func trimPrefix( + @RegexComponentBuilder _ content: () -> R + ) { + trimPrefix(content()) + } + + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closure to create the regex. + /// + /// - Parameters: + /// - replacement: The new elements to add to the collection in place of + /// each match for the regex, using `content` to create the regex. + /// - subrange: The range in the collection in which to search for + /// the regex. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by `replacement`, using `content` to create the regex. + @available(SwiftStdlib 5.7, *) + public func replacing( + with replacement: Replacement, + subrange: Range, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> some RegexComponent + ) -> Self where Replacement.Element == Element { + replacing(content(), with: replacement, subrange: subrange, maxReplacements: maxReplacements) + } + + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closure to create the regex. + /// + /// - Parameters: + /// - replacement: The new elements to add to the collection in place of + /// each match for the regex, using `content` to create the regex. + /// - maxReplacements: A number specifying how many occurrences of regex + /// to replace. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by `replacement`, using `content` to create the regex. + @available(SwiftStdlib 5.7, *) + public func replacing( + with replacement: Replacement, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> some RegexComponent + ) -> Self where Replacement.Element == Element { + replacing(content(), with: replacement, maxReplacements: maxReplacements) + } + + /// Replaces all matches for the regex in this collection, using the given + /// closure to create the regex. + /// + /// - Parameters: + /// - replacement: The new elements to add to the collection in place of + /// each match for the regex, using `content` to create the regex. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace. + /// - content: A closure that returns the collection to search for + /// and replace. + @available(SwiftStdlib 5.7, *) + public mutating func replace( + with replacement: Replacement, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> some RegexComponent + ) where Replacement.Element == Element { + replace(content(), with: replacement, maxReplacements: maxReplacements) + } + + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closures to create the replacement + /// and the regex. + /// + /// - Parameters: + /// - subrange: The range in the collection in which to search for the + /// regex, using `content` to create the regex. + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by the result of calling `replacement`, where regex + /// is the result of calling `content`. + @available(SwiftStdlib 5.7, *) + public func replacing( + subrange: Range, + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> R, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows -> Self where Replacement.Element == Element { + try replacing(content(), subrange: subrange, maxReplacements: maxReplacements, with: replacement) + } + + /// Returns a new collection in which all matches for the regex + /// are replaced, using the given closures to create the replacement + /// and the regex. + /// + /// - Parameters: + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace, using `content` to create the regex. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all matches for regex in `subrange` + /// are replaced by the result of calling `replacement`, where regex is + /// the result of calling `content`. + @available(SwiftStdlib 5.7, *) + public func replacing( + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> R, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows -> Self where Replacement.Element == Element { + try replacing(content(), maxReplacements: maxReplacements, with: replacement) + } + + /// Replaces all matches for the regex in this collection, using the + /// given closures to create the replacement and the regex. + /// + /// - Parameters: + /// - maxReplacements: A number specifying how many occurrences of + /// the regex to replace, using `content` to create the regex. + /// - content: A closure that returns the collection to search for + /// and replace. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + @available(SwiftStdlib 5.7, *) + public mutating func replace( + maxReplacements: Int = .max, + @RegexComponentBuilder content: () -> R, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows where Replacement.Element == Element { + try replace(content(), maxReplacements: maxReplacements, with: replacement) + } +} diff --git a/Sources/RegexBuilder/Match.swift b/Sources/RegexBuilder/Match.swift deleted file mode 100644 index 78a466a18..000000000 --- a/Sources/RegexBuilder/Match.swift +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 _StringProcessing - -@available(SwiftStdlib 5.7, *) -extension String { - @available(SwiftStdlib 5.7, *) - public func wholeMatch( - @RegexComponentBuilder of content: () -> R - ) -> Regex.Match? { - wholeMatch(of: content()) - } - - @available(SwiftStdlib 5.7, *) - public func prefixMatch( - @RegexComponentBuilder of content: () -> R - ) -> Regex.Match? { - prefixMatch(of: content()) - } -} - -extension Substring { - @available(SwiftStdlib 5.7, *) - public func wholeMatch( - @RegexComponentBuilder of content: () -> R - ) -> Regex.Match? { - wholeMatch(of: content()) - } - - @available(SwiftStdlib 5.7, *) - public func prefixMatch( - @RegexComponentBuilder of content: () -> R - ) -> Regex.Match? { - prefixMatch(of: content()) - } -} diff --git a/Tests/RegexBuilderTests/AlgorithmsTests.swift b/Tests/RegexBuilderTests/AlgorithmsTests.swift index 5a7a69fac..0a2e6bc21 100644 --- a/Tests/RegexBuilderTests/AlgorithmsTests.swift +++ b/Tests/RegexBuilderTests/AlgorithmsTests.swift @@ -11,7 +11,7 @@ import XCTest import _StringProcessing -@testable import RegexBuilder +import RegexBuilder @available(SwiftStdlib 5.7, *) class RegexConsumerTests: XCTestCase { @@ -105,3 +105,339 @@ class RegexConsumerTests: XCTestCase { ) } } + +class AlgorithmsResultBuilderTests: XCTestCase { + enum MatchAlgo { + case whole + case first + case prefix + } + + enum EquatableAlgo { + case starts + case contains + case trimmingPrefix + } + + func expectMatch( + _ algo: MatchAlgo, + _ tests: (input: String, expectedCaptures: MatchType?)..., + matchType: MatchType.Type, + equivalence: (MatchType, MatchType) -> Bool, + file: StaticString = #file, + line: UInt = #line, + @RegexComponentBuilder _ content: () -> R + ) throws { + for (input, expectedCaptures) in tests { + var actual: Regex.Match? + switch algo { + case .whole: + actual = input.wholeMatch(of: content) + case .first: + actual = input.firstMatch(of: content) + case .prefix: + actual = input.prefixMatch(of: content) + } + if let expectedCaptures = expectedCaptures { + let match = try XCTUnwrap(actual, file: file, line: line) + let captures = try XCTUnwrap(match.output as? MatchType, file: file, line: line) + XCTAssertTrue(equivalence(captures, expectedCaptures), file: file, line: line) + } else { + XCTAssertNil(actual, file: file, line: line) + } + } + } + + func expectEqual( + _ algo: EquatableAlgo, + _ tests: (input: String, expected: Expected)..., + file: StaticString = #file, + line: UInt = #line, + @RegexComponentBuilder _ content: () -> R + ) throws { + for (input, expected) in tests { + var actual: Expected + switch algo { + case .contains: + actual = input.contains(content) as! Expected + case .starts: + actual = input.starts(with: content) as! Expected + case .trimmingPrefix: + actual = input.trimmingPrefix(content) as! Expected + } + XCTAssertEqual(actual, expected) + } + } + + func testMatches() throws { + let int = Capture(OneOrMore(.digit)) { Int($0)! } + + // Test syntax + let add = Regex { + int + "+" + int + } + let content = { add } + + let m = "2020+16".wholeMatch { + int + "+" + int + } + XCTAssertEqual(m?.output.0, "2020+16") + XCTAssertEqual(m?.output.1, 2020) + XCTAssertEqual(m?.output.2, 16) + + let m1 = "2020+16".wholeMatch(of: content) + XCTAssertEqual(m1?.output.0, m?.output.0) + XCTAssertEqual(m1?.output.1, m?.output.1) + XCTAssertEqual(m1?.output.2, m?.output.2) + + let firstMatch = "2020+16 0+0".firstMatch(of: content) + XCTAssertEqual(firstMatch?.output.0, "2020+16") + XCTAssertEqual(firstMatch?.output.1, 2020) + XCTAssertEqual(firstMatch?.output.2, 16) + + let prefix = "2020+16 0+0".prefixMatch(of: content) + XCTAssertEqual(prefix?.output.0, "2020+16") + XCTAssertEqual(prefix?.output.1, 2020) + XCTAssertEqual(prefix?.output.2, 16) + + try expectMatch( + .whole, + ("0+0", ("0+0", 0, 0)), + ("2020+16", ("2020+16", 2020, 16)), + ("-2020+16", nil), + ("2020+16+0+0", nil), + matchType: (Substring, Int, Int).self, + equivalence: == + ) { + int + "+" + int + } + + try expectMatch( + .prefix, + ("0+0", ("0+0", 0, 0)), + ("2020+16", ("2020+16", 2020, 16)), + ("-2020+16", nil), + ("2020+16+0+0", ("2020+16", 2020, 16)), + matchType: (Substring, Int, Int).self, + equivalence: == + ) { + int + "+" + int + } + + try expectMatch( + .first, + ("0+0", ("0+0", 0, 0)), + ("2020+16", ("2020+16", 2020, 16)), + ("-2020+16", ("2020+16", 2020, 16)), + ("2020+16+0+0", ("2020+16", 2020, 16)), + matchType: (Substring, Int, Int).self, + equivalence: == + ) { + int + "+" + int + } + } + + func testStartsAndContains() throws { + let fam = "👨‍👩‍👧‍👦👨‍👨‍👧‍👧 we Ⓡ family" + let startsWithGrapheme = fam.starts { + OneOrMore(.anyGrapheme) + OneOrMore(.whitespace) + } + XCTAssertEqual(startsWithGrapheme, true) + + let containsDads = fam.contains { + "👨‍👨‍👧‍👧" + } + XCTAssertEqual(containsDads, true) + + let content = { + Regex { + OneOrMore(.anyGrapheme) + OneOrMore(.whitespace) + } + } + XCTAssertEqual(fam.starts(with: content), true) + XCTAssertEqual(fam.contains(content), true) + + let int = Capture(OneOrMore(.digit)) { Int($0)! } + + try expectEqual( + .starts, + ("9+16, 0+3, 5+5, 99+1", true), + ("-9+16, 0+3, 5+5, 99+1", false), + (" 9+16", false), + ("a+b, c+d", false), + ("", false) + ) { + int + "+" + int + } + + try expectEqual( + .contains, + ("9+16, 0+3, 5+5, 99+1", true), + ("-9+16, 0+3, 5+5, 99+1", true), + (" 9+16", true), + ("a+b, c+d", false), + ("", false) + ) { + int + "+" + int + } + } + + func testTrim() throws { + let int = Capture(OneOrMore(.digit)) { Int($0)! } + + // Test syntax + let code = "(408)888-8888".trimmingPrefix { + "(" + OneOrMore(.digit) + ")" + } + XCTAssertEqual(code, Substring("888-8888")) + + var mutable = "👨‍👩‍👧‍👦 we Ⓡ family" + mutable.trimPrefix { + .anyGrapheme + ZeroOrMore(.whitespace) + } + XCTAssertEqual(mutable, "we Ⓡ family") + + try expectEqual( + .trimmingPrefix, + ("9+16 0+3 5+5 99+1", Substring(" 0+3 5+5 99+1")), + ("a+b 0+3 5+5 99+1", Substring("a+b 0+3 5+5 99+1")), + ("0+3+5+5+99+1", Substring("+5+5+99+1")), + ("", "") + ) { + int + "+" + int + } + } + + func testReplace() { + // Test no ambiguitiy using the trailing closure + var replaced: String + let str = "9+16, 0+3, 5+5, 99+1" + replaced = str.replacing(with: "🔢") { + OneOrMore(.digit) + "+" + OneOrMore(.digit) + } + XCTAssertEqual(replaced, "🔢, 🔢, 🔢, 🔢") + + replaced = str.replacing( + with: "🔢", + subrange: str.startIndex.. Date: Thu, 21 Apr 2022 10:40:26 -0700 Subject: [PATCH 20/30] Revise doc comments for API reference style. - Fix spelling error in parameter name (invertion --> inversion). - Add docs for parameters and return values. - Use indicative instead of imperative for method/function/initializer abstracts. (Match a regex. --> Matches a regex.) - Don't use code voice in abstracts, or symbol names as English nouns. - Use contractions per Apple style. - Turn /// comments that contain notes for this API's implementers into plain // comments, to omit that content from the docs. Move them before the /// comments, to keep doc comments immediately adjacent to the declaration they documents. --- Sources/RegexBuilder/CharacterClass.swift | 6 +- Sources/RegexBuilder/DSL.swift | 11 ++-- Sources/_RegexParser/Regex/AST/AST.swift | 21 ++++--- Sources/_RegexParser/Regex/AST/Atom.swift | 14 +++-- .../Regex/AST/CustomCharClass.swift | 5 +- Sources/_RegexParser/Regex/AST/Group.swift | 13 +++-- .../Regex/AST/MatchingOptions.swift | 11 ++-- .../Regex/AST/Quantification.swift | 2 +- .../Regex/Parse/CaptureStructure.swift | 3 +- Sources/_RegexParser/Regex/Parse/Parse.swift | 4 +- Sources/_RegexParser/Regex/Parse/Source.swift | 10 ++-- .../Regex/Parse/SourceLocation.swift | 8 +-- .../Regex/Parse/SyntaxOptions.swift | 28 +++++----- .../_RegexParser/Regex/Printing/DumpAST.swift | 7 ++- .../Regex/Printing/PrettyPrinter.swift | 50 ++++++++++------- .../Regex/Printing/PrintAsCanonical.swift | 16 ++++-- Sources/_RegexParser/Utility/Misc.swift | 14 +++-- .../_RegexParser/Utility/MissingUnicode.swift | 30 ++++++---- .../Algorithms/Algorithms/Split.swift | 6 +- .../Algorithms/Algorithms/StartsWith.swift | 3 +- .../_StringProcessing/PrintAsPattern.swift | 2 +- .../Regex/AnyRegexOutput.swift | 23 +++++--- Sources/_StringProcessing/Regex/Core.swift | 2 +- Sources/_StringProcessing/Regex/DSLTree.swift | 14 ++--- Sources/_StringProcessing/Regex/Match.swift | 55 +++++++++++-------- Sources/_StringProcessing/Regex/Options.swift | 51 +++++++++++++---- .../_CharacterClassModel.swift | 21 ++++--- 27 files changed, 269 insertions(+), 161 deletions(-) diff --git a/Sources/RegexBuilder/CharacterClass.swift b/Sources/RegexBuilder/CharacterClass.swift index b7d8454bb..3a96ba363 100644 --- a/Sources/RegexBuilder/CharacterClass.swift +++ b/Sources/RegexBuilder/CharacterClass.swift @@ -100,7 +100,7 @@ extension RegexComponent where Self == CharacterClass { members: s.map { .atom(.char($0)) })) } - /// Returns a character class that matches any unicode scalar in the given + /// Returns a character class that matches any Unicode scalar in the given /// sequence. public static func anyOf(_ s: S) -> CharacterClass where S.Element == UnicodeScalar @@ -118,7 +118,7 @@ extension CharacterClass { } } -/// Range syntax for characters in `CharacterClass`es. +/// Returns a character class that includes the characters in the given range. @available(SwiftStdlib 5.7, *) public func ...(lhs: Character, rhs: Character) -> CharacterClass { let range: DSLTree.CustomCharacterClass.Member = .range(.char(lhs), .char(rhs)) @@ -126,7 +126,7 @@ public func ...(lhs: Character, rhs: Character) -> CharacterClass { return CharacterClass(ccc) } -/// Range syntax for unicode scalars in `CharacterClass`es. +/// Returns a character class that includes the Unicode scalars in the given range. @_disfavoredOverload @available(SwiftStdlib 5.7, *) public func ...(lhs: UnicodeScalar, rhs: UnicodeScalar) -> CharacterClass { diff --git a/Sources/RegexBuilder/DSL.swift b/Sources/RegexBuilder/DSL.swift index 62aacc4af..10590fb74 100644 --- a/Sources/RegexBuilder/DSL.swift +++ b/Sources/RegexBuilder/DSL.swift @@ -95,8 +95,8 @@ extension UnicodeScalar: RegexComponent { // Note: Quantifiers are currently gyb'd. 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. + // Individual public API functions are in the generated Variadics.swift file. + /// Generates a DSL tree node for a repeated range of the given node. @available(SwiftStdlib 5.7, *) static func repeating( _ range: Range, @@ -251,8 +251,10 @@ public struct TryCapture: _BuiltinRegexComponent { // MARK: - Groups -/// An atomic group, i.e. opens a local backtracking scope which, upon successful exit, -/// discards any remaining backtracking points from within the scope +/// An atomic group. +/// +/// This group 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 @@ -265,6 +267,7 @@ public struct Local: _BuiltinRegexComponent { // MARK: - Backreference @available(SwiftStdlib 5.7, *) +/// A backreference. public struct Reference: RegexComponent { let id = ReferenceID() diff --git a/Sources/_RegexParser/Regex/AST/AST.swift b/Sources/_RegexParser/Regex/AST/AST.swift index 409d5a7ee..eae393289 100644 --- a/Sources/_RegexParser/Regex/AST/AST.swift +++ b/Sources/_RegexParser/Regex/AST/AST.swift @@ -9,8 +9,9 @@ // //===----------------------------------------------------------------------===// -/// A regex abstract syntax tree. This is a top-level type that stores the root -/// node. +/// A regex abstract syntax tree. +/// +/// This is a top-level type that stores the root node. public struct AST: Hashable { public var root: AST.Node public var globalOptions: GlobalMatchingOptionSequence? @@ -22,7 +23,7 @@ public struct AST: Hashable { } extension AST { - /// Whether this AST tree has nested somewhere inside it a capture. + /// Whether this AST tree contains at least one capture nested inside of it. public var hasCapture: Bool { root.hasCapture } /// The capture structure of this AST tree. @@ -94,7 +95,9 @@ extension AST.Node { _associatedValue as? T } - /// If this node is a parent node, access its children + /// The child nodes of this node. + /// + /// If the node isn't a parent node, this value is `nil`. public var children: [AST.Node]? { return (_associatedValue as? _ASTParent)?.children } @@ -103,7 +106,7 @@ extension AST.Node { _associatedValue.location } - /// Whether this node is "trivia" or non-semantic, like comments + /// Whether this node is trivia or non-semantic, like comments. public var isTrivia: Bool { switch self { case .trivia: return true @@ -111,7 +114,7 @@ extension AST.Node { } } - /// Whether this node has nested somewhere inside it a capture + /// Whether this node contains at least one capture nested inside of it. public var hasCapture: Bool { switch self { case .group(let g) where g.kind.value.isCapturing: @@ -122,7 +125,7 @@ extension AST.Node { return self.children?.any(\.hasCapture) ?? false } - /// Whether this AST node may be used as the operand of a quantifier such as + /// Whether this node may be used as the operand of a quantifier such as /// `?`, `+` or `*`. public var isQuantifiable: Bool { switch self { @@ -203,7 +206,9 @@ extension AST { } } - /// An Oniguruma absent function. This is used to model a pattern which should + /// An Oniguruma absent function. + /// + /// This is used to model a pattern which should /// not be matched against across varying scopes. public struct AbsentFunction: Hashable, _ASTNode { public enum Start: Hashable { diff --git a/Sources/_RegexParser/Regex/AST/Atom.swift b/Sources/_RegexParser/Regex/AST/Atom.swift index 1f6043d72..e17ce68bb 100644 --- a/Sources/_RegexParser/Regex/AST/Atom.swift +++ b/Sources/_RegexParser/Regex/AST/Atom.swift @@ -415,7 +415,7 @@ extension AST.Atom.CharacterProperty { } extension AST.Atom { - /// Anchors and other built-in zero-width assertions + /// Anchors and other built-in zero-width assertions. @frozen public enum AssertionKind: String { /// \A @@ -574,7 +574,7 @@ extension AST.Atom { } extension AST.Atom.Callout { - /// A tag specifier `[...]` which may appear in an Oniguruma callout. + /// A tag specifier `[...]` that can appear in an Oniguruma callout. public struct OnigurumaTag: Hashable { public var leftBracket: SourceLocation public var name: AST.Located @@ -668,8 +668,10 @@ extension AST.Atom.EscapedBuiltin { } extension AST.Atom { - /// Retrieve the character value of the atom if it represents a literal - /// character or unicode scalar, nil otherwise. + /// Retrieves the character value of the atom. + /// + /// If the atom doesn't represent a literal character or a Unicode scalar, + /// this value is `nil`. public var literalCharacterValue: Character? { switch kind { case .char(let c): @@ -711,9 +713,9 @@ extension AST.Atom { } } - /// Produce a string literal representation of the atom, if possible + /// A string literal representation of the atom, if possible. /// - /// Individual characters will be returned, Unicode scalars will be + /// Individual characters are returned as-is, and Unicode scalars are /// presented using "\u{nnnn}" syntax. public var literalStringValue: String? { switch kind { diff --git a/Sources/_RegexParser/Regex/AST/CustomCharClass.swift b/Sources/_RegexParser/Regex/AST/CustomCharClass.swift index 19e72aef5..c1dd4c620 100644 --- a/Sources/_RegexParser/Regex/AST/CustomCharClass.swift +++ b/Sources/_RegexParser/Regex/AST/CustomCharClass.swift @@ -104,8 +104,9 @@ extension CustomCC.Member { } extension AST.CustomCharacterClass { - /// Strip trivia from the character class members. This does not recurse into - /// nested custom character classes. + /// Strips trivia from the character class members. + /// + /// This method doesn't recurse into nested custom character classes. public var strippingTriviaShallow: Self { var copy = self copy.members = copy.members.filter(\.isSemantic) diff --git a/Sources/_RegexParser/Regex/AST/Group.swift b/Sources/_RegexParser/Regex/AST/Group.swift index a8c4f8b0f..8ecaadeda 100644 --- a/Sources/_RegexParser/Regex/AST/Group.swift +++ b/Sources/_RegexParser/Regex/AST/Group.swift @@ -78,6 +78,7 @@ extension AST { } extension AST.Group.Kind { + /// Whether the group is a capturing group. public var isCapturing: Bool { switch self { case .capture, .namedCapture, .balancedCapture: return true @@ -85,7 +86,9 @@ extension AST.Group.Kind { } } - /// If this is a named group, its name, `nil` otherwise. + /// The name of the group. + /// + /// If the group doesn't have a name, this value is `nil`. public var name: String? { switch self { case .namedCapture(let name): return name.value @@ -96,9 +99,11 @@ extension AST.Group.Kind { } extension AST.Group.Kind { - /// If this group is a lookaround assertion, return its direction - /// and whether it is positive or negative. Otherwise returns - /// `nil`. + /// The direction of a lookaround assertion + /// and an indication of whether the assertion is positive or negative. + /// + /// If the group isn't a lookaheand or lookbehind assertion, + /// this value is `nil`. public var lookaroundKind: (forwards: Bool, positive: Bool)? { switch self { case .lookahead: return (true, true) diff --git a/Sources/_RegexParser/Regex/AST/MatchingOptions.swift b/Sources/_RegexParser/Regex/AST/MatchingOptions.swift index 8e4b31bc5..e779c39fb 100644 --- a/Sources/_RegexParser/Regex/AST/MatchingOptions.swift +++ b/Sources/_RegexParser/Regex/AST/MatchingOptions.swift @@ -10,7 +10,7 @@ //===----------------------------------------------------------------------===// extension AST { - /// An option written in source that changes matching semantics. + /// An option, written in source, that changes matching semantics. public struct MatchingOption: Hashable { public enum Kind { // PCRE options @@ -83,7 +83,7 @@ extension AST { } } - /// A sequence of matching options written in source. + /// A sequence of matching options, written in source. public struct MatchingOptionSequence: Hashable { /// If the sequence starts with a caret '^', its source location, or nil /// otherwise. If this is set, it indicates that all the matching options @@ -138,8 +138,11 @@ extension AST.MatchingOptionSequence: _ASTPrintable { } extension AST { - /// Global matching option specifiers. Unlike `MatchingOptionSequence`, - /// these must appear at the start of the pattern, and apply globally. + /// Global matching option specifiers. + /// + /// Unlike `MatchingOptionSequence`, + /// these options must appear at the start of the pattern, + /// and they apply to the entire pattern. public struct GlobalMatchingOption: _ASTNode, Hashable { /// Determines the definition of a newline for the '.' character class and /// when parsing end-of-line comments. diff --git a/Sources/_RegexParser/Regex/AST/Quantification.swift b/Sources/_RegexParser/Regex/AST/Quantification.swift index f2189cb38..fa7e4de82 100644 --- a/Sources/_RegexParser/Regex/AST/Quantification.swift +++ b/Sources/_RegexParser/Regex/AST/Quantification.swift @@ -59,7 +59,7 @@ extension AST { /// MARK: - Semantic API extension AST.Quantification.Amount { - /// Get the bounds + /// The bounds. public var bounds: (atLeast: Int, atMost: Int?) { switch self { case .zeroOrMore: return (0, nil) diff --git a/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift b/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift index 8298dc207..9cb31c7d9 100644 --- a/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift +++ b/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift @@ -286,10 +286,11 @@ extension CaptureStructure { MemoryLayout.stride + inputUTF8CodeUnitCount + 1 } - /// Encode the capture structure to the given buffer as a serialized + /// Encodes the capture structure to the given buffer as a serialized /// representation. /// /// The encoding rules are as follows: + /// /// ``` /// encode(〚`T`〛) ==> , 〚`T`〛, .end /// 〚`T` (atom)〛 ==> .atom diff --git a/Sources/_RegexParser/Regex/Parse/Parse.swift b/Sources/_RegexParser/Regex/Parse/Parse.swift index a2790924a..ec6e1c26c 100644 --- a/Sources/_RegexParser/Regex/Parse/Parse.swift +++ b/Sources/_RegexParser/Regex/Parse/Parse.swift @@ -577,8 +577,8 @@ fileprivate func defaultSyntaxOptions( } } -/// Parse a given regex string with delimiters, inferring the syntax options -/// from the delimiter used. +/// Parses a given regex string with delimiters, inferring the syntax options +/// from the delimiters used. public func parseWithDelimiters( _ regex: S ) throws -> AST where S.SubSequence == Substring { diff --git a/Sources/_RegexParser/Regex/Parse/Source.swift b/Sources/_RegexParser/Regex/Parse/Source.swift index 6eac16395..23cc0497d 100644 --- a/Sources/_RegexParser/Regex/Parse/Source.swift +++ b/Sources/_RegexParser/Regex/Parse/Source.swift @@ -9,10 +9,12 @@ // //===----------------------------------------------------------------------===// -/// The source given to a parser. This can be bytes in memory, a file on disk, -/// something streamed over a network connection, etc. +// For now, we use String as the source while prototyping... + +/// The source of text being given to a parser. /// -/// For now, we use String... +/// This can be bytes in memory, a file on disk, +/// something streamed over a network connection, and so on. /// public struct Source { var input: Input @@ -37,7 +39,7 @@ extension Source { public typealias Input = String // for wrapper... public typealias Char = Character // for wrapper... - /// A precise point in the input, commonly used for bounded ranges + /// A precise point in the input, commonly used for bounded ranges. public typealias Position = String.Index } diff --git a/Sources/_RegexParser/Regex/Parse/SourceLocation.swift b/Sources/_RegexParser/Regex/Parse/SourceLocation.swift index a58473c96..eb51643bd 100644 --- a/Sources/_RegexParser/Regex/Parse/SourceLocation.swift +++ b/Sources/_RegexParser/Regex/Parse/SourceLocation.swift @@ -62,7 +62,7 @@ public protocol LocatedErrorProtocol: Error { } extension Source { - /// An error with source location info + /// An error that includes information about the location in source code. public struct LocatedError: Error, LocatedErrorProtocol { public let error: E public let location: SourceLocation @@ -77,10 +77,10 @@ extension Source { } } - /// Located value: a value wrapped with a source range + /// A value wrapped with a source range. /// - /// Note: source location is part of value identity, so that the same - /// e.g. `Character` appearing twice can be stored in a data structure + /// Note: Source location is part of value identity so that, for example, the + /// same `Character` value appearing twice can be stored in a data structure /// distinctly. To ignore source locations, use `.value` directly. public struct Located { public var value: T diff --git a/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift b/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift index b7c09ea1c..0a6270f1b 100644 --- a/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift +++ b/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift @@ -31,31 +31,31 @@ public struct SyntaxOptions: OptionSet { [.endOfLineComments, .nonSemanticWhitespace] } + // NOTE: Currently, this means we have raw quotes. + // Better would be to have real Swift string delimiter parsing logic. + /// `'a "." b' == '/a\Q.\Eb/'` - /// - /// NOTE: Currently, this means we have raw quotes. - /// Better would be to have real Swift string delimiter parsing logic. public static var experimentalQuotes: Self { Self(1 << 2) } + // NOTE: traditional comments are not nested. Currently, we are neither. + // Traditional comments can't have `)`, not even escaped in them either, we + // can. Traditional comments can have `*/` in them, we can't without + // escaping. We don't currently do escaping. + /// `'a /* comment */ b' == '/a(?#. comment )b/'` - /// - /// NOTE: traditional comments are not nested. Currently, we are neither. - /// Traditional comments can't have `)`, not even escaped in them either, we - /// can. Traditional comments can have `*/` in them, we can't without - /// escaping. We don't currently do escaping. public static var experimentalComments: Self { Self(1 << 3) } /// ``` - /// 'a{n...m}' == '/a{n,m}/' - /// 'a{n...*)` - /// `(_: .*)` == `(?:.*)` + /// `(_: .*)` == `(?:.*)` public static var experimentalCaptures: Self { Self(1 << 5) } /// The default syntax for a multi-line regex literal. diff --git a/Sources/_RegexParser/Regex/Printing/DumpAST.swift b/Sources/_RegexParser/Regex/Printing/DumpAST.swift index 8565b14e9..a9cf6b424 100644 --- a/Sources/_RegexParser/Regex/Printing/DumpAST.swift +++ b/Sources/_RegexParser/Regex/Printing/DumpAST.swift @@ -9,10 +9,11 @@ // //===----------------------------------------------------------------------===// -/// AST entities can be pretty-printed or dumped +/// AST entities that can be pretty-printed or dumped. /// -/// Alternative: just use `description` for pretty-print -/// and `debugDescription` for dump +/// As an alternative to this protocol, +/// you can also use the `description` to pretty-print an AST, +/// and `debugDescription` for to dump a debugging representation. public protocol _ASTPrintable: CustomStringConvertible, CustomDebugStringConvertible diff --git a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift index f1d8c83b0..c06643aee 100644 --- a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift +++ b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift @@ -9,17 +9,25 @@ // //===----------------------------------------------------------------------===// -/// Track and handle state relevant to pretty-printing ASTs. +/// State used when to pretty-printing regex ASTs. public struct PrettyPrinter { // Configuration - /// Cut off pattern conversion after this many levels + /// The maximum number number of levels, from the root of the tree, + /// at which to perform pattern conversion. + /// + /// A `nil` value indicates that there is no maximum, + /// and pattern conversion always takes place. public var maxTopDownLevels: Int? - /// Cut off pattern conversion after this tree height + /// The maximum number number of levels, from the leaf nodes of the tree, + /// at which to perform pattern conversion. + /// + /// A `nil` value indicates that there is no maximum, + /// and pattern conversion always takes place. public var minBottomUpLevels: Int? - /// How many spaces to indent with ("tab-width") + /// The number of spaces used for indentation. public var indentWidth = 2 // Internal state @@ -46,25 +54,27 @@ extension PrettyPrinter { self.minBottomUpLevels = minBottomUpLevels } - /// Output a string directly, without termination, without - /// indentation, and without updating _any_ internal state. + /// Outputs a string directly, without termination or + /// indentation, and without updating any internal state. /// /// This is the low-level interface to the pret /// - /// NOTE: If `s` includes a newline, even at the end, - /// this function will not update any tracking state. + /// - Note: If `s` includes a newline, even at the end, + /// this method does not update any tracking state. public mutating func output(_ s: String) { result += s } - /// Terminate a line, updating any relevant state + /// Terminates a line, updating any relevant state. public mutating func terminateLine() { output("\n") startOfLine = true } - /// Indent a new line, if at the start of a line, otherwise - /// does nothing. Updates internal state. + /// Indents a new line, if at the start of a line, otherwise + /// does nothing. + /// + /// This function updates internal state. public mutating func indent() { guard startOfLine else { return } let numCols = indentLevel * indentWidth @@ -72,7 +82,9 @@ extension PrettyPrinter { startOfLine = false } - // Finish, flush, and clear. Returns the rendered output + // Finish, flush, and clear. + // + // - Returns: The rendered output. public mutating func finish() -> String { defer { result = "" } return result @@ -85,18 +97,18 @@ extension PrettyPrinter { extension PrettyPrinter { /// Print out a new entry. /// - /// This will property indent `s`, update any internal state, - /// and will also terminate the current line. + /// This method indents `s`, updates any internal state, + /// and terminates the current line. public mutating func print(_ s: String) { indent() output("\(s)") terminateLine() } - /// Print out a new entry by invoking `f` until it returns `nil`. + /// Prints out a new entry by invoking `f` until it returns `nil`. /// - /// This will property indent, update any internal state, - /// and will also terminate the current line. + /// This method indents `s`, updates any internal state, + /// and terminates the current line. public mutating func printLine(_ f: () -> String?) { // TODO: What should we do if `f` never returns non-nil? indent() @@ -106,7 +118,7 @@ extension PrettyPrinter { terminateLine() } - /// Execute `f` at one increased level of indentation + /// Executes `f` at one increased level of indentation. public mutating func printIndented( _ f: (inout Self) -> () ) { @@ -115,7 +127,7 @@ extension PrettyPrinter { self.indentLevel -= 1 } - /// Execute `f` inside an indented "block", which has a header + /// Executes `f` inside an indented block, which has a header /// and delimiters. public mutating func printBlock( _ header: String, diff --git a/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift b/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift index ab961ba51..59c0cc04a 100644 --- a/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift +++ b/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift @@ -12,7 +12,7 @@ // TODO: Round-tripping tests extension AST { - /// Render using Swift's preferred regex literal syntax + /// Renders using Swift's preferred regex literal syntax. public func renderAsCanonical( showDelimiters delimiters: Bool = false, terminateLine: Bool = false @@ -27,7 +27,7 @@ extension AST { } extension AST.Node { - /// Render using Swift's preferred regex literal syntax + /// Renders using Swift's preferred regex literal syntax. public func renderAsCanonical( showDelimiters delimiters: Bool = false, terminateLine: Bool = false @@ -38,8 +38,12 @@ extension AST.Node { } extension PrettyPrinter { - /// Will output `ast` in canonical form, taking care to - /// also indent and terminate the line (updating internal state) + /// Outputs a regular expression abstract syntax tree in canonical form, + /// indenting and terminating the line, and updating its internal state. + /// + /// - Parameter ast: The abstract syntax tree of the regular expression being output. + /// - Parameter delimiters: Whether to include commas between items. + /// - Parameter terminateLine: Whether to include terminate the line. public mutating func printAsCanonical( _ ast: AST, delimiters: Bool = false, @@ -57,8 +61,8 @@ extension PrettyPrinter { } } - /// Output the `ast` in canonical form, does not indent, terminate, - /// or affect internal state + /// Outputs a regular expression abstract syntax tree in canonical form, + /// without indentation, line termation, or affecting its internal state. mutating func outputAsCanonical(_ ast: AST.Node) { switch ast { case let .alternation(a): diff --git a/Sources/_RegexParser/Utility/Misc.swift b/Sources/_RegexParser/Utility/Misc.swift index 55d3d3adc..bd9bc665e 100644 --- a/Sources/_RegexParser/Utility/Misc.swift +++ b/Sources/_RegexParser/Utility/Misc.swift @@ -111,8 +111,11 @@ extension Collection { } extension Collection where Element: Equatable { - /// Attempt to drop a given prefix from the collection, returning the - /// resulting subsequence, or `nil` if the prefix does not match. + /// Attempts to drop a given prefix from the collection. + /// + /// - Parameter other: The collection that contains the prefix. + /// - Returns: The resulting subsequence, + /// or `nil` if the prefix doesn't match. public func tryDropPrefix( _ other: C ) -> SubSequence? where C.Element == Element { @@ -121,8 +124,11 @@ extension Collection where Element: Equatable { return dropFirst(prefixCount) } - /// Attempt to drop a given suffix from the collection, returning the - /// resulting subsequence, or `nil` if the suffix does not match. + /// Attempts to drop a given suffix from the collection. + /// + /// - Parameter other: The collection that contains the suffix. + /// - Returns: The resulting subsequence, + /// or `nil` if the prefix doesn't match. public func tryDropSuffix( _ other: C ) -> SubSequence? where C.Element == Element { diff --git a/Sources/_RegexParser/Utility/MissingUnicode.swift b/Sources/_RegexParser/Utility/MissingUnicode.swift index 4d819806b..b1a4a07ff 100644 --- a/Sources/_RegexParser/Utility/MissingUnicode.swift +++ b/Sources/_RegexParser/Utility/MissingUnicode.swift @@ -12,13 +12,13 @@ // MARK: - Missing stdlib API extension Unicode { + // Note: The `Script` enum includes the "meta" script type "Katakana_Or_Hiragana", which + // isn't defined by https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt, + // but is defined by https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt. + // We may want to split it out, as it's the only case that is a union of + // other script types. + /// Character script types. - /// - /// Note this includes the "meta" script type "Katakana_Or_Hiragana", which - /// isn't defined by https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt, - /// but is defined by https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt. - /// We may want to split it out, as it's the only case that is a union of - /// other script types. @frozen public enum Script: String, Hashable { case adlam = "Adlam" @@ -254,7 +254,8 @@ extension Unicode { case spaceSeparator = "Zs" } - /// A list of unicode properties that can either be true or false. + /// A list of Unicode properties that can either be true or false. + /// /// https://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt @frozen public enum BinaryProperty: String, Hashable { @@ -328,9 +329,10 @@ extension Unicode { } } +// TODO: These should become aliases for the Block (blk) Unicode character +// property. + /// Oniguruma properties that are not covered by Unicode spellings. -/// TODO: These should become aliases for the Block (blk) Unicode character -/// property. @frozen public enum OnigurumaSpecialProperty: String, Hashable { case inBasicLatin = "In_Basic_Latin" @@ -657,18 +659,24 @@ public enum OnigurumaSpecialProperty: String, Hashable { } extension Character { + /// Whether this character represents an octal (base 8) digit, + /// for the purposes of pattern parsing. public var isOctalDigit: Bool { ("0"..."7").contains(self) } + /// Whether this character represents a word character, + /// for the purposes of pattern parsing. public var isWordCharacter: Bool { isLetter || isNumber || self == "_" } - /// Whether this character represents whitespace for the purposes of pattern - /// parsing. + /// Whether this character represents whitespace, + /// for the purposes of pattern parsing. public var isPatternWhitespace: Bool { return unicodeScalars.first!.properties.isPatternWhitespace } } extension UnicodeScalar { + /// Whether this character represents a printable ASCII character, + /// for the purposes of pattern parsing. public var isPrintableASCII: Bool { // Exclude non-printables before the space character U+20, and anything // including and above the DEL character U+7F. diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 97d8c80dd..df121d8c5 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -299,9 +299,10 @@ extension Collection where Element: Equatable { // FIXME: Return `some Collection` for SE-0346 /// 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. + /// elements. @available(SwiftStdlib 5.7, *) public func split( separator: C, @@ -373,9 +374,10 @@ extension BidirectionalCollection where SubSequence == Substring { // FIXME: Return `some Collection` for SE-0346 /// 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. + /// elements. @_disfavoredOverload public func split( separator: R, diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift b/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift index 0dd91f360..2f45a734b 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift @@ -51,9 +51,10 @@ extension BidirectionalCollection where Element: Equatable { 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`. + /// beginning of `regex`; otherwise, `false`. public func starts(with regex: R) -> Bool { starts(with: RegexConsumer(regex)) } diff --git a/Sources/_StringProcessing/PrintAsPattern.swift b/Sources/_StringProcessing/PrintAsPattern.swift index 91626eb5c..ff85e38f1 100644 --- a/Sources/_StringProcessing/PrintAsPattern.swift +++ b/Sources/_StringProcessing/PrintAsPattern.swift @@ -19,7 +19,7 @@ @_spi(PatternConverter) extension AST { - /// Render as a Pattern DSL + /// Renders as a Pattern DSL. @_spi(PatternConverter) public func renderAsBuilderDSL( maxTopDownLevels: Int? = nil, diff --git a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift index 0d018aa81..3dbe9d84e 100644 --- a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift +++ b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift @@ -13,7 +13,9 @@ @available(SwiftStdlib 5.7, *) extension Regex where Output == AnyRegexOutput { - /// Parse and compile `pattern`, resulting in an existentially-typed capture list. + /// Parses and compiles a regular expression, resulting in an existentially-typed capture list. + /// + /// - Parameter pattern: The regular expression. public init(_ pattern: String) throws { self.init(ast: try parse(pattern, .traditional)) } @@ -21,7 +23,10 @@ extension Regex where Output == AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension Regex { - /// Parse and compile `pattern`, resulting in a strongly-typed capture list. + /// Parses and compiles a regular expression. + /// + /// - Parameter pattern: The regular expression. + /// - Parameter as: The desired type for the output. public init( _ pattern: String, as: Output.Type = Output.self @@ -32,7 +37,7 @@ extension Regex { @available(SwiftStdlib 5.7, *) extension Regex.Match where Output == AnyRegexOutput { - // Ensures `.0` always refers to the whole match. + /// Accesses the whole match using the `.0` syntax. public subscript( dynamicMember keyPath: KeyPath<(Substring, _doNotUse: ()), Substring> ) -> Substring { @@ -44,7 +49,7 @@ extension Regex.Match where Output == AnyRegexOutput { } } -/// A type-erased regex output +/// A type-erased regex output. @available(SwiftStdlib 5.7, *) public struct AnyRegexOutput { let input: String @@ -67,7 +72,7 @@ extension 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. + /// use site of a dynamic regex, like one that was created from a string. public init(_ match: Regex.Match) { // Note: We use type equality instead of `match.output as? ...` to prevent // unexpected optional flattening. @@ -84,7 +89,7 @@ extension AnyRegexOutput { /// /// - Parameter type: The expected output type. /// - Returns: The output, if the underlying value can be converted to the - /// output type, or nil otherwise. + /// output type; otherwise `nil`. public func `as`(_ type: Output.Type) -> Output? { let elements = _elements.map { StructuredCapture( @@ -190,7 +195,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. + /// use site of a dynamic regex match, like one that was created from a string. public init(_ match: Regex.Match) { fatalError("FIXME: Not implemented") } @@ -199,8 +204,8 @@ extension Regex.Match where Output == AnyRegexOutput { /// 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. + /// - Returns: A match generic over the output type, if the underlying values + /// can be converted to the output type; otherwise, `nil`. 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 36d62f674..1f9a35dad 100644 --- a/Sources/_StringProcessing/Regex/Core.swift +++ b/Sources/_StringProcessing/Regex/Core.swift @@ -19,7 +19,7 @@ public protocol RegexComponent { var regex: Regex { get } } -/// A regex represents a string processing algorithm. +/// A regular expression. /// /// let regex = try Regex("a(.*)b") /// let match = "cbaxb".firstMatch(of: regex) diff --git a/Sources/_StringProcessing/Regex/DSLTree.swift b/Sources/_StringProcessing/Regex/DSLTree.swift index ce5beeaca..52eaeffb0 100644 --- a/Sources/_StringProcessing/Regex/DSLTree.swift +++ b/Sources/_StringProcessing/Regex/DSLTree.swift @@ -25,29 +25,29 @@ public struct DSLTree { extension DSLTree { @_spi(RegexBuilder) public indirect enum Node { - /// Try to match each node in order + /// Matches each node in order. /// /// ... | ... | ... case orderedChoice([Node]) - /// Match each node in sequence + /// Match each node in sequence. /// /// ... ... case concatenation([Node]) - /// Capture the result of a subpattern + /// Captures the result of a subpattern. /// /// (...), (?...) case capture( name: String? = nil, reference: ReferenceID? = nil, Node) - /// Match a (non-capturing) subpattern / group + /// Matches a noncapturing subpattern. case nonCapturingGroup(_AST.GroupKind, Node) // TODO: Consider splitting off grouped conditions, or have // our own kind - /// Match a choice of two nodes based on a condition + /// Matches a choice of two nodes, based on a condition. /// /// (?(cond) true-branch | false-branch) /// @@ -63,7 +63,7 @@ extension DSLTree { case atom(Atom) - /// Comments, non-semantic whitespace, etc + /// Comments, non-semantic whitespace, and so on. // TODO: Do we want this? Could be interesting case trivia(String) @@ -73,7 +73,7 @@ extension DSLTree { case quotedLiteral(String) - /// An embedded literal + /// An embedded literal. case regexLiteral(_AST.ASTNode) // TODO: What should we do here? diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 45df7aeaa..dd36c8823 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -19,7 +19,7 @@ extension Regex { public struct Match { let input: String - /// The range of the overall match + /// The range of the overall match. public let range: Range let rawCaptures: [StructuredCapture] @@ -34,7 +34,7 @@ extension Regex { @available(SwiftStdlib 5.7, *) extension Regex.Match { - /// The produced output from the match operation + /// The output produced from the match operation. public var output: Output { if Output.self == AnyRegexOutput.self { let wholeMatchAsCapture = StructuredCapture( @@ -62,12 +62,12 @@ extension Regex.Match { } } - /// Lookup a capture by name or number + /// Accesses a capture by its name or number. public subscript(dynamicMember keyPath: KeyPath) -> T { output[keyPath: keyPath] } - // Allows `.0` when `Match` is not a tuple. + /// Accesses a capture using the `.0` syntax, even when the match isn't a tuple. @_disfavoredOverload public subscript( dynamicMember keyPath: KeyPath<(Output, _doNotUse: ()), Output> @@ -88,44 +88,50 @@ extension Regex.Match { @available(SwiftStdlib 5.7, *) extension Regex { - /// Match a string in its entirety. + /// Matches a string in its entirety. /// - /// Returns `nil` if no match and throws on abort + /// - Parameter s: The string to match this regular expression against. + /// - Returns: The match, or `nil` if no match was found. public func wholeMatch(in s: String) throws -> Regex.Match? { try _match(s, in: s.startIndex.. Regex.Match? { try _match(s, in: s.startIndex.. Regex.Match? { try _firstMatch(s, in: s.startIndex.. Regex.Match? { try _match(s.base, in: s.startIndex.. Regex.Match? { try _match(s.base, in: s.startIndex.. Regex.Match? { try _firstMatch(s.base, in: s.startIndex..( of r: R ) -> Regex.Match? { try? r.regex.wholeMatch(in: self[...].base) } - /// Match part of the regex, starting at the beginning. - /// - Parameter r: The regex to match against. - /// - Returns: The match if there is one, or `nil` if none. + /// Checks for a match against the string, starting at its beginning. + /// + /// - Parameter r: The regular expression being matched. + /// - Returns: The match, or `nil` if no match was found. public func prefixMatch( of r: R ) -> Regex.Match? { @@ -183,6 +191,7 @@ extension BidirectionalCollection where SubSequence == Substring { extension RegexComponent { public static func ~=(regex: Self, input: String) -> Bool { input.wholeMatch(of: regex) != nil + try? r.regex.wholeMatch(in: self) } public static func ~=(regex: Self, input: Substring) -> Bool { diff --git a/Sources/_StringProcessing/Regex/Options.swift b/Sources/_StringProcessing/Regex/Options.swift index cb0fe044e..24d5c422e 100644 --- a/Sources/_StringProcessing/Regex/Options.swift +++ b/Sources/_StringProcessing/Regex/Options.swift @@ -13,35 +13,57 @@ @available(SwiftStdlib 5.7, *) extension RegexComponent { - /// Returns a regular expression that ignores casing when matching. + /// Returns a regular expression that ignores case when matching. + /// + /// - Parameter ignoresCase: A Boolean value indicating whether to ignore case. + /// - Returns: The modified regular expression. public func ignoresCase(_ ignoresCase: Bool = true) -> Regex { wrapInOption(.caseInsensitive, addingIf: ignoresCase) } - /// Returns a regular expression that only matches ASCII characters as "word - /// characters". + /// Returns a regular expression that matches only ASCII characters as word + /// characters. + /// + /// - Parameter useASCII: A Boolean value indicating whether to match only + /// ASCII characters as word characters. + /// - Returns: The modified regular expression. public func asciiOnlyWordCharacters(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlyWord, addingIf: useASCII) } - /// Returns a regular expression that only matches ASCII characters as digits. + /// Returns a regular expression that matches only ASCII characters as digits. + /// + /// - Parameter useasciiOnlyDigits: A Boolean value indicating whether to + /// match only ASCII characters as digits. + /// - Returns: The modified regular expression. public func asciiOnlyDigits(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlyDigit, addingIf: useASCII) } - /// Returns a regular expression that only matches ASCII characters as space + /// Returns a regular expression that matches only ASCII characters as space /// characters. + /// + /// - Parameter asciiOnlyWhitespace: A Boolean value indicating whether to + /// match only ASCII characters as space characters. + /// - Returns: The modified regular expression. public func asciiOnlyWhitespace(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlySpace, addingIf: useASCII) } - /// Returns a regular expression that only matches ASCII characters when + /// Returns a regular expression that matches only ASCII characters when /// matching character classes. + /// + /// - Parameter useASCII: A Boolean value indicating whether to match only + /// ASCII characters when matching character classes. + /// - Returns: The modified regular expression. public func asciiOnlyCharacterClasses(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlyPOSIXProps, addingIf: useASCII) } /// Returns a regular expression that uses the specified word boundary algorithm. + /// + /// - Parameter wordBoundaryKind: The algorithm to use for determining word boundaries. + /// - Returns: The modified regular expression. public func wordBoundaryKind(_ wordBoundaryKind: RegexWordBoundaryKind) -> Regex { wrapInOption(.unicodeWordBoundaries, addingIf: wordBoundaryKind == .unicodeLevel2) } @@ -51,6 +73,7 @@ extension RegexComponent { /// /// - Parameter dotMatchesNewlines: A Boolean value indicating whether `.` /// should match a newline character. + /// - Returns: The modified regular expression. public func dotMatchesNewlines(_ dotMatchesNewlines: Bool = true) -> Regex { wrapInOption(.singleLine, addingIf: dotMatchesNewlines) } @@ -65,6 +88,7 @@ extension RegexComponent { /// /// - Parameter matchLineEndings: A Boolean value indicating whether `^` and /// `$` should match the start and end of lines, respectively. + /// - Returns: The modified regular expression. public func anchorsMatchLineEndings(_ matchLineEndings: Bool = true) -> Regex { wrapInOption(.multiline, addingIf: matchLineEndings) } @@ -124,6 +148,9 @@ extension RegexComponent { /// // Prints "true" /// print(decomposed.contains(queRegexScalar)) /// // Prints "false" + /// + /// - Parameter semanticLevel: The semantics to use during matching. + /// - Returns: The modified regular expression. public func matchingSemantics(_ semanticLevel: RegexSemanticLevel) -> Regex { switch semanticLevel.base { case .graphemeCluster: @@ -144,14 +171,18 @@ public struct RegexSemanticLevel: Hashable { internal var base: Representation - /// Match at the default semantic level of a string, where each matched - /// element is a `Character`. + /// Match at the character level. + /// + /// At this semantic level, each matched element is a `Character` value. + /// This is the default semantic level. 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. + /// Match at the Unicode scalar level. + /// + /// At this semantic level, the string's `UnicodeScalarView` is used for matching, + /// and each matched element is a `UnicodeScalar` value. public static var unicodeScalar: RegexSemanticLevel { .init(base: .unicodeScalar) } diff --git a/Sources/_StringProcessing/_CharacterClassModel.swift b/Sources/_StringProcessing/_CharacterClassModel.swift index c02725e33..4d0c12c1f 100644 --- a/Sources/_StringProcessing/_CharacterClassModel.swift +++ b/Sources/_StringProcessing/_CharacterClassModel.swift @@ -139,23 +139,30 @@ public struct _CharacterClassModel: Hashable { return result } - /// Returns an inverted character class if true is passed, otherwise the - /// same character class is returned. - func withInversion(_ invertion: Bool) -> Self { + /// Conditionally inverts a character class. + /// + /// - Parameter inversion: Indicates whether to invert the character class. + /// - Returns: The inverted character class if `inversion` is `true`; + /// otherwise, the same character class. + func withInversion(_ inversion: Bool) -> Self { var copy = self - if invertion { + if inversion { copy.isInverted.toggle() } return copy } - /// Returns the inverse character class. + /// Inverts a character class. public var inverted: Self { return withInversion(true) } - /// Returns the end of the match of this character class in `str`, if - /// it matches. + /// Returns the end of the match of this character class in the string. + /// + /// - Parameter str: The string to match against. + /// - Parameter at: The index to start matching. + /// - Parameter options: Options for the match operation. + /// - Returns: The index of the end of the match, or `nil` if there is no match. func matches(in str: String, at i: String.Index, with options: MatchingOptions) -> String.Index? { switch matchLevel { case .graphemeCluster: From 14674708c9c8aaac30f385aee61d22e9028db408 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 25 Apr 2022 18:52:54 -0600 Subject: [PATCH 21/30] Algorithm cleanup (#351) * Extension collection * Break out long excerpts * cleanup * bidi split * mystery mark * Update Documentation/Evolution/StringProcessingAlgorithms.md Co-authored-by: Nate Cook * split preserving Co-authored-by: Nate Cook --- .../Evolution/StringProcessingAlgorithms.md | 452 ++++++++++++------ 1 file changed, 308 insertions(+), 144 deletions(-) diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index eee05e3a7..001ce1fec 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -31,7 +31,7 @@ while let r = str.range(of: "banana", options: [], range: idx.. @@ -133,13 +133,13 @@ Parsing a currency string such as `$3,020.85` with regex is also tricky, as it c ### Complex string processing We propose a `CustomConsumingRegexComponent` protocol which allows types from outside the standard library participate in regex builders and `RegexComponent` algorithms. This allows types, such as `Date.ParseStrategy` and `FloatingPointFormatStyle.Currency`, to be used directly within a regex: - + ```swift let dateRegex = Regex { Capture(dateParser) } -let date: Date = header.firstMatch(of: dateRegex).map(\.result.1) +let date: Date = header.firstMatch(of: dateRegex).map(\.result.1) let currencyRegex = Regex { Capture(.localizedCurrency(code: "USD").sign(strategy: .accounting)) @@ -174,7 +174,7 @@ We also propose the following regex-powered algorithms as well as their generic `CustomConsumingRegexComponent` inherits from `RegexComponent` and satisfies its sole requirement. Conformers can be used with all of the string algorithms generic over `RegexComponent`. ```swift -/// A protocol allowing custom types to function as regex components by +/// A protocol allowing custom types to function as regex components by /// providing the raw functionality backing `prefixMatch`. public protocol CustomConsumingRegexComponent: RegexComponent { /// Process the input string within the specified bounds, beginning at the given index, and return @@ -199,7 +199,7 @@ public protocol CustomConsumingRegexComponent: RegexComponent { We use Foundation `FloatingPointFormatStyle.Currency` as an example for protocol conformance. It would implement the `match` function with `Match` being a `Decimal`. It could also add a static function `.localizedCurrency(code:)` as a member of `RegexComponent`, so it can be referred as `.localizedCurrency(code:)` in the `Regex` result builder: ```swift -extension FloatingPointFormatStyle.Currency : CustomConsumingRegexComponent { +extension FloatingPointFormatStyle.Currency : CustomConsumingRegexComponent { public func consuming( _ input: String, startingAt index: String.Index, @@ -223,10 +223,12 @@ let regex = Regex { -### String algorithm additions +### String and Collection algorithm additions #### Contains +We propose a `contains` variant over collections that tests for subsequence membership. The second algorithm allows for specialization using e.g. the [two way search algorithm](https://en.wikipedia.org/wiki/Two-way_string-matching_algorithm). + ```swift extension Collection where Element: Equatable { /// Returns a Boolean value indicating whether the collection contains the @@ -237,15 +239,31 @@ extension Collection where Element: Equatable { public func contains(_ other: C) -> Bool where S.Element == Element } +extension BidirectionalCollection where Element: Comparable { + /// 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`. + public func contains(_ other: C) -> Bool + where S.Element == Element +} +``` -extension BidirectionalCollection where SubSequence == Substring { +We propose a regex-taking variant over string types (those that produce a `Substring` upon slicing). + +```swift +extension Collection 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`. public func contains(_ regex: some RegexComponent) -> Bool +} +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns a Boolean value indicating whether this collection contains a /// match for the regex, where the regex is created by the given closure. /// @@ -261,15 +279,20 @@ extension BidirectionalCollection where SubSequence == Substring { #### Starts with +We propose a regex-taking `starts(with:)` variant for string types: + ```swift -extension BidirectionalCollection where SubSequence == Substring { +extension Collection 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: some RegexComponent) -> Bool - +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns a Boolean value indicating whether the initial elements of this /// collection are a match for the regex created by the given closure. /// @@ -285,6 +308,8 @@ extension BidirectionalCollection where SubSequence == Substring { #### Trim prefix +We propose generic `trimmingPrefix` and `trimPrefix` methods for collections that trim elements matching a predicate or a possible prefix sequence. + ```swift extension Collection { /// Returns a new collection of the same type by removing initial elements @@ -338,15 +363,22 @@ extension RangeReplaceableCollection where Element: Equatable { public mutating func trimPrefix(_ prefix: Prefix) where Prefix.Element == Element } +``` + +We propose regex-taking variants for string types: -extension BidirectionalCollection where SubSequence == Substring { +```swift +extension Collection where SubSequence == Substring { /// Returns a new subsequence by removing the initial elements that matches /// the given regex. /// - Parameter regex: The regex to remove from this collection. /// - Returns: A new subsequence containing the elements of the collection /// that does not match `prefix` from the start. public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence - +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns a subsequence of this collection by removing the elements /// matching the regex from the start, where the regex is created by /// the given closure. @@ -362,13 +394,14 @@ extension BidirectionalCollection where SubSequence == Substring { ) -> SubSequence } -extension RangeReplaceableCollection - where Self: BidirectionalCollection, SubSequence == Substring -{ +extension RangeReplaceableCollection where SubSequence == Substring { /// Removes the initial elements that matches the given regex. /// - Parameter regex: The regex to remove from this collection. public mutating func trimPrefix(_ regex: some RegexComponent) - +} + +// In RegexBuilder module +extension RangeReplaceableCollection where SubSequence == Substring { /// Removes the initial elements matching the regex from the start of /// this collection, if the initial elements match, using the given closure /// to create the regex. @@ -383,6 +416,8 @@ extension RangeReplaceableCollection #### First range +We propose a generic collection algorithm for finding the first range of a given subsequence: + ```swift extension Collection where Element: Equatable { /// Finds and returns the range of the first occurrence of a given sequence @@ -390,7 +425,7 @@ extension Collection where Element: Equatable { /// - Parameter sequence: The sequence to search for. /// - Returns: A range in the collection of the first occurrence of `sequence`. /// Returns nil if `sequence` is not found. - public func firstRange(of other: C) -> Range? + public func firstRange(of other: C) -> Range? where C.Element == Element } @@ -403,15 +438,22 @@ extension BidirectionalCollection where Element: Comparable { public func firstRange(of other: C) -> Range? where C.Element == Element } +``` + +We propose a regex-taking variant for string types. -extension BidirectionalCollection where SubSequence == Substring { +```swift +extension Collection 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. public func firstRange(of regex: some RegexComponent) -> Range? - +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns the range of the first match for the regex within this collection, /// where the regex is created by the given closure. /// @@ -421,12 +463,14 @@ extension BidirectionalCollection where SubSequence == Substring { /// for the regex is found. public func firstRange( @RegexComponentBuilder of content: () -> some RegexComponent - ) -> Range? + ) -> Range? } ``` #### Ranges +We propose a generic collection algorithm for iterating over all (non-overlapping) ranges of a given subsequence. + ```swift extension Collection where Element: Equatable { /// Finds and returns the ranges of the all occurrences of a given sequence @@ -438,14 +482,31 @@ extension Collection where Element: Equatable { where C.Element == Element } -extension BidirectionalCollection where SubSequence == Substring { +extension BidirectionalCollection where Element: Comparable { + /// Finds and returns the ranges of the all occurrences of a given sequence + /// within the collection. + /// - Parameter other: The sequence to search for. + /// - Returns: A collection of ranges of all occurrences of `other`. Returns + /// an empty collection if `other` is not found. + public func ranges(of other: C) -> some Collection> + where C.Element == Element +} +``` + +And of course regex-taking versions for string types: + +```swift +extension Collection where SubSequence == Substring { /// Finds and returns the ranges of the all occurrences of a given sequence /// within the collection. /// - Parameter regex: The regex to search for. /// - Returns: A collection or ranges in the receiver of all occurrences of /// `regex`. Returns an empty collection if `regex` is not found. public func ranges(of regex: some RegexComponent) -> some Collection> - +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns the ranges of the all non-overlapping matches for the regex /// within this collection, where the regex is created by the given closure. /// @@ -461,14 +522,29 @@ extension BidirectionalCollection where SubSequence == Substring { #### Match +We propose algorithms for extracting a `Match` instance from a given regex from the start, anywhere in the middle, or over the entire `self`. + ```swift -extension BidirectionalCollection where SubSequence == Substring { +extension Collection where SubSequence == Substring { /// 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. public func firstMatch(of regex: R) -> Regex.Match? - + + /// Match a regex in its entirety. + /// - Parameter regex: The regex to match against. + /// - Returns: The match if there is one, or `nil` if none. + public func wholeMatch(of regex: R) -> Regex.Match? + + /// Match part of the regex, starting at the beginning. + /// - Parameter regex: The regex to match against. + /// - Returns: The match if there is one, or `nil` if none. + public func prefixMatch(of regex: R) -> Regex.Match? +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns the first match for the regex within this collection, where /// the regex is created by the given closure. /// @@ -477,13 +553,8 @@ extension BidirectionalCollection where SubSequence == Substring { /// collection, or `nil` if no match is found. public func firstMatch( @RegexComponentBuilder of content: () -> R - ) -> Regex.Match? - - /// Match a regex in its entirety. - /// - Parameter regex: The regex to match against. - /// - Returns: The match if there is one, or `nil` if none. - public func wholeMatch(of regex: R) -> Regex.Match? - + ) -> Regex.Match? + /// Matches a regex in its entirety, where the regex is created by /// the given closure. /// @@ -491,13 +562,8 @@ extension BidirectionalCollection where SubSequence == Substring { /// - Returns: The match if there is one, or `nil` if none. public func wholeMatch( @RegexComponentBuilder of content: () -> R - ) -> Regex.Match? - - /// Match part of the regex, starting at the beginning. - /// - Parameter regex: The regex to match against. - /// - Returns: The match if there is one, or `nil` if none. - public func prefixMatch(of regex: R) -> Regex.Match? - + ) -> Regex.Match? + /// Matches part of the regex, starting at the beginning, where the regex /// is created by the given closure. /// @@ -511,13 +577,18 @@ extension BidirectionalCollection where SubSequence == Substring { #### Matches +We propose an algorithm for iterating over all (non-overlapping) matches of a given regex: + ```swift -extension BidirectionalCollection where SubSequence == Substring { +extension Collection where SubSequence == Substring { /// Returns a collection containing all matches of the specified regex. /// - Parameter regex: The regex to search for. /// - Returns: A collection of matches of `regex`. public func matches(of regex: R) -> some Collection.Match> - +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns a collection containing all non-overlapping matches of /// the regex, created by the given closure. /// @@ -532,6 +603,8 @@ extension BidirectionalCollection where SubSequence == Substring { #### Replace +We propose generic collection algorithms that will replace all occurences of a given subsequence: + ```swift extension RangeReplaceableCollection where Element: Equatable { /// Returns a new collection in which all occurrences of a target sequence @@ -543,14 +616,59 @@ extension RangeReplaceableCollection where Element: Equatable { /// - 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`. + /// `subrange` of the collection are replaced by `replacement`. + public func replacing( + _ other: C, + with replacement: Replacement, + subrange: Range, + maxReplacements: Int = .max + ) -> Self where C.Element == Element, Replacement.Element == Element + + /// 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`. + public func replacing( + _ other: C, + with replacement: Replacement, + maxReplacements: Int = .max + ) -> Self where C.Element == Element, Replacement.Element == Element + + /// Replaces all occurrences of a target sequence with a given 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`. + public mutating func replace( + _ other: C, + with replacement: Replacement, + maxReplacements: Int = .max + ) where C.Element == Element, Replacement.Element == Element +} +extension RangeReplaceableCollection where Self: BidirectionalCollection, Element: Comparable { + /// 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`. public func replacing( _ other: C, with replacement: Replacement, subrange: Range, maxReplacements: Int = .max ) -> Self where C.Element == Element, Replacement.Element == Element - + /// Returns a new collection in which all occurrences of a target sequence /// are replaced by another collection. /// - Parameters: @@ -565,7 +683,7 @@ extension RangeReplaceableCollection where Element: Equatable { with replacement: Replacement, maxReplacements: Int = .max ) -> Self where C.Element == Element, Replacement.Element == Element - + /// Replaces all occurrences of a target sequence with a given collection /// - Parameters: /// - other: The sequence to replace. @@ -578,7 +696,11 @@ extension RangeReplaceableCollection where Element: Equatable { maxReplacements: Int = .max ) where C.Element == Element, Replacement.Element == Element } +``` + +We propose regex-taking variants for string types as well as variants that take a closure which will generate the replacement portion from a regex match (e.g. by reading captures). +```swift 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. @@ -597,6 +719,85 @@ extension RangeReplaceableCollection where SubSequence == Substring { maxReplacements: Int = .max ) -> Self where Replacement.Element == Element + /// 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`. + public func replacing( + _ r: some RegexComponent, + with replacement: Replacement, + maxReplacements: Int = .max + ) -> Self where Replacement.Element == Element + + /// Replaces all occurrences of the sequence matching the given regex with + /// a given 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`. + public mutating func replace( + _ r: some RegexComponent, + with replacement: Replacement, + maxReplacements: Int = .max + ) where Replacement.Element == Element + + /// 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. + /// - 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`. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + public func replacing( + _ regex: R, + subrange: Range, + maxReplacements: Int = .max, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows -> Self where Replacement.Element == Element + + /// 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. + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + /// - Returns: A new collection in which all occurrences of subsequence + /// matching `regex` are replaced by `replacement`. + public func replacing( + _ regex: R, + maxReplacements: Int = .max, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows -> Self where Replacement.Element == Element + + /// Replaces all occurrences of the sequence matching the given regex with + /// a given collection. + /// - Parameters: + /// - regex: A regex describing the sequence to replace. + /// - maxReplacements: A number specifying how many occurrences of the + /// sequence matching `regex` to replace. Default is `Int.max`. + /// - replacement: A closure that receives the full match information, + /// including captures, and returns a replacement collection. + public mutating func replace( + _ regex: R, + maxReplacements: Int = .max, + with replacement: (Regex.Match) throws -> Replacement + ) rethrows where Replacement.Element == Element +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns a new collection in which all matches for the regex /// are replaced, using the given closure to create the regex. /// @@ -610,29 +811,14 @@ extension RangeReplaceableCollection where SubSequence == Substring { /// - content: A closure that returns the collection to search for /// and replace. /// - Returns: A new collection in which all matches for regex in `subrange` - /// are replaced by `replacement`, using `content` to create the regex. + /// are replaced by `replacement`, using `content` to create the regex. public func replacing( with replacement: Replacement, subrange: Range, maxReplacements: Int = .max, @RegexComponentBuilder content: () -> some RegexComponent ) -> Self where Replacement.Element == Element - - /// 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`. - public func replacing( - _ r: some RegexComponent, - with replacement: Replacement, - maxReplacements: Int = .max - ) -> Self where Replacement.Element == Element - + /// Returns a new collection in which all matches for the regex /// are replaced, using the given closure to create the regex. /// @@ -649,21 +835,8 @@ extension RangeReplaceableCollection where SubSequence == Substring { with replacement: Replacement, maxReplacements: Int = .max, @RegexComponentBuilder content: () -> some RegexComponent - ) -> Self where Replacement.Element == Element - - /// Replaces all occurrences of the sequence matching the given regex with - /// a given 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`. - public mutating func replace( - _ r: some RegexComponent, - with replacement: Replacement, - maxReplacements: Int = .max - ) where Replacement.Element == Element - + ) -> Self where Replacement.Element == Element + /// Replaces all matches for the regex in this collection, using the given /// closure to create the regex. /// @@ -678,25 +851,7 @@ extension RangeReplaceableCollection where SubSequence == Substring { with replacement: Replacement, maxReplacements: Int = .max, @RegexComponentBuilder content: () -> some RegexComponent - ) where Replacement.Element == Element - - /// 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. - /// - 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`. - /// - replacement: A closure that receives the full match information, - /// including captures, and returns a replacement collection. - /// - Returns: A new collection in which all occurrences of subsequence - /// matching `regex` are replaced by `replacement`. - public func replacing( - _ regex: R, - subrange: Range, - maxReplacements: Int = .max, - with replacement: (Regex.Match) throws -> Replacement - ) rethrows -> Self where Replacement.Element == Element + ) where Replacement.Element == Element /// Returns a new collection in which all matches for the regex /// are replaced, using the given closures to create the replacement @@ -720,23 +875,7 @@ extension RangeReplaceableCollection where SubSequence == Substring { @RegexComponentBuilder content: () -> R, with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element - - /// 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. - /// - maxReplacements: A number specifying how many occurrences of the - /// sequence matching `regex` to replace. Default is `Int.max`. - /// - replacement: A closure that receives the full match information, - /// including captures, and returns a replacement collection. - /// - Returns: A new collection in which all occurrences of subsequence - /// matching `regex` are replaced by `replacement`. - public func replacing( - _ regex: R, - maxReplacements: Int = .max, - with replacement: (Regex.Match) throws -> Replacement - ) rethrows -> Self where Replacement.Element == Element - + /// Returns a new collection in which all matches for the regex /// are replaced, using the given closures to create the replacement /// and the regex. @@ -756,20 +895,6 @@ extension RangeReplaceableCollection where SubSequence == Substring { @RegexComponentBuilder content: () -> R, with replacement: (Regex.Match) throws -> Replacement ) rethrows -> Self where Replacement.Element == Element - - /// Replaces all occurrences of the sequence matching the given regex with - /// a given collection. - /// - Parameters: - /// - regex: A regex describing the sequence to replace. - /// - maxReplacements: A number specifying how many occurrences of the - /// sequence matching `regex` to replace. Default is `Int.max`. - /// - replacement: A closure that receives the full match information, - /// including captures, and returns a replacement collection. - public mutating func replace( - _ regex: R, - maxReplacements: Int = .max, - with replacement: (Regex.Match) throws -> Replacement - ) rethrows where Replacement.Element == Element /// Replaces all matches for the regex in this collection, using the /// given closures to create the replacement and the regex. @@ -791,6 +916,8 @@ extension RangeReplaceableCollection where SubSequence == Substring { #### Split +We propose a generic collection `split` that can take a subsequence separator: + ```swift extension Collection where Element: Equatable { /// Returns the longest possible subsequences of the collection, in order, @@ -798,11 +925,11 @@ extension Collection where Element: Equatable { /// /// - Parameters: /// - separator: A collection of elements to be split upon. - /// - maxSplits: The maximum number of times to split the collection, + /// - maxSplits: The maximum number of times to split the collection, /// or one less than the number of subsequences to return. - /// - omittingEmptySubsequences: If `false`, an empty subsequence is - /// returned in the result for each consecutive pair of separator - /// sequences in the collection and for each instance of separator + /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// returned in the result for each consecutive pair of separator + /// sequences in the collection and for each instance of separator /// sequences at the start or end of the collection. If `true`, only /// nonempty subsequences are returned. /// - Returns: A collection of subsequences, split from this collection's @@ -813,16 +940,41 @@ extension Collection where Element: Equatable { omittingEmptySubsequences: Bool = true ) -> some Collection where C.Element == Element } +extension BidirectionalCollection where Element: Comparable { + /// Returns the longest possible subsequences of the collection, in order, + /// around elements equal to the given separator collection. + /// + /// - Parameters: + /// - separator: A collection of elements to be split upon. + /// - maxSplits: The maximum number of times to split the collection, + /// or one less than the number of subsequences to return. + /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// returned in the result for each consecutive pair of separator + /// sequences in the collection and for each instance of separator + /// sequences at the start or end of the collection. If `true`, only + /// nonempty subsequences are returned. + /// - Returns: A collection of subsequences, split from this collection's + /// elements. + public func split( + separator: C, + maxSplits: Int = Int.max, + omittingEmptySubsequences: Bool = true + ) -> some Collection where C.Element == Element +} +``` -extension BidirectionalCollection where SubSequence == Substring { +And a regex-taking variant for string types: + +```swift +extension Collection where SubSequence == Substring { /// Returns the longest possible subsequences of the collection, in order, /// around subsequence that match the given separator regex. /// /// - Parameters: /// - separator: A regex to be split upon. - /// - maxSplits: The maximum number of times to split the collection, + /// - maxSplits: The maximum number of times to split the collection, /// or one less than the number of subsequences to return. - /// - omittingEmptySubsequences: If `false`, an empty subsequence is + /// - omittingEmptySubsequences: If `false`, an empty subsequence is /// returned in the result for each consecutive pair of matches /// and for each match at the start or end of the collection. If /// `true`, only nonempty subsequences are returned. @@ -833,7 +985,10 @@ extension BidirectionalCollection where SubSequence == Substring { maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true ) -> some Collection - +} + +// In RegexBuilder module +extension Collection where SubSequence == Substring { /// Returns the longest possible subsequences of the collection, in order, /// around subsequence that match the regex created by the given closure. /// @@ -918,24 +1073,33 @@ Older versions of the pitch had `func match(...) -> (String.Index, T)?` as the p This protocol customizes the basic consume-from-the-front functionality. A protocol for customizing search is future work and involves accommodating different kinds of state and ways that a searcher may wish to speed up subsequent searches. Alternative names for the protocol include `CustomRegexComponent`, `CustomConsumingRegex`, etc., but we don't feel brevity is the key consideration here. +### Why `where SubSequence == Substring`? + +A `Substring` slice requirement allows the regex engine to produce indicies in the original collection by operating over a portion of the input. Unfortunately, this is not one of the requirements of `StringProtocol`. + +A new protocol for types that can produce a `Substring` on request (e.g. from UTF-8 contents) would have to eagerly produce a `String` copy first and would need requirements to translate indices. When higher-level algorithms are implemented via multiple calls to the lower-level algorithms, these copies could happen many times. Shared strings are future work but a much better solution to this. + ## Future directions ### Backward algorithms -It would be useful to have algorithms that operate from the back of a collection, including ability to find the last non-overlapping range of a pattern in a string, and/or that to find the first range of a pattern when searching from the back, and trimming a string from both sides. They are deferred from this proposal as the API that could clarify the nuances of backward algorithms are still being explored. +It would be useful to have algorithms that operate from the back of a collection, including ability to find the last non-overlapping range of a pattern in a string, and/or that to find the first range of a pattern when searching from the back, and trimming a string from both sides. They are deferred from this proposal as the API that could clarify the nuances of backward algorithms are still being explored.
Nuances of backward algorithms -There is a subtle difference between finding the last non-overlapping range of a pattern in a string, and finding the first range of this pattern when searching from the back. +There is a subtle difference between finding the last non-overlapping range of a pattern in a string, and finding the first range of this pattern when searching from the back. -The currently proposed algorithm that finds a pattern from the front, e.g. `"aaaaa".ranges(of: "aa")`, produces two non-overlapping ranges, splitting the string in the chunks `aa|aa|a`. It would not be completely unreasonable to expect to introduce a counterpart, such as `"aaaaa".lastRange(of: "aa")`, to return the range that contains the third and fourth characters of the string. This would be a shorthand for `"aaaaa".ranges(of: "aa").last`. Yet, it would also be reasonable to expect the function to return the first range of `"aa"` when searching from the back of the string, i.e. the range that contains the fourth and fifth characters. +The currently proposed algorithm that finds a pattern from the front, e.g. `"aaaaa".ranges(of: "aa")`, produces two non-overlapping ranges, splitting the string in the chunks `aa|aa|a`. It would not be completely unreasonable to expect to introduce a counterpart, such as `"aaaaa".lastRange(of: "aa")`, to return the range that contains the third and fourth characters of the string. This would be a shorthand for `"aaaaa".ranges(of: "aa").last`. Yet, it would also be reasonable to expect the function to return the first range of `"aa"` when searching from the back of the string, i.e. the range that contains the fourth and fifth characters. -Trimming a string from both sides shares a similar story. For example, `"ababa".trimming("aba")` can return either `"ba"` or `"ab"`, depending on whether the prefix or the suffix was trimmed first. +Trimming a string from both sides shares a similar story. For example, `"ababa".trimming("aba")` can return either `"ba"` or `"ab"`, depending on whether the prefix or the suffix was trimmed first.
- +### Split preserving the separator + +Future work is a split variant that interweaves the separator with the separated portions. For example, when splitting over `\p{punctuation}` it might be useful to be able to preserve the punctionation as a separate entry in the returned collection. + ### Future API -Some common string processing functions are not currently included in this proposal, such as trimming the suffix from a string/collection, and finding overlapping ranges of matched substrings. This pitch aims to establish a pattern for using `RegexComponent` with string processing algorithms, so that further enhancement can to be introduced to the standard library easily in the future, and eventually close the gap between Swift and other popular scripting languages. +Some common string processing functions are not currently included in this proposal, such as trimming the suffix from a string/collection, and finding overlapping ranges of matched substrings. This pitch aims to establish a pattern for using `RegexComponent` with string processing algorithms, so that further enhancement can to be introduced to the standard library easily in the future, and eventually close the gap between Swift and other popular scripting languages. From e0922ec2c947c6955eb621455ced1718f5d59eff Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Mon, 25 Apr 2022 19:46:24 -0600 Subject: [PATCH 22/30] API stubs for casting and named captures (#349) * API stubs for casting and named captures * Update Sources/_StringProcessing/Regex/AnyRegexOutput.swift Co-authored-by: Richard Wei Co-authored-by: Richard Wei --- .../Regex/AnyRegexOutput.swift | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift index 0d018aa81..295ef97fc 100644 --- a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift +++ b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift @@ -205,3 +205,28 @@ extension Regex.Match where Output == AnyRegexOutput { fatalError("FIXME: Not implemented") } } + +@available(SwiftStdlib 5.7, *) +extension Regex where Output == AnyRegexOutput { + /// Returns whether a named-capture with `name` exists + public func contains(captureNamed name: String) -> Bool { + fatalError("FIXME: not implemented") + } + + /// Creates a type-erased regex from an existing regex. + /// + /// 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) { + fatalError("FIXME: Not implemented") + } + + /// Returns a typed regex by converting the underlying types. + /// + /// - Parameter type: The expected output type. + /// - Returns: A regex generic over the output type if the underlying types can be converted. + /// Returns `nil` otherwise. + public func `as`(_ type: Output.Type) -> Regex? { + fatalError("FIXME: Not implemented") + } +} From bef2092af735465fb6878427e09b04d80247b6cf Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 26 Apr 2022 07:38:50 -0600 Subject: [PATCH 23/30] Mention language level pattern matching (#354) --- .../Evolution/StringProcessingAlgorithms.md | 38 +++++++++++++++++++ Tests/RegexBuilderTests/AlgorithmsTests.swift | 3 ++ 2 files changed, 41 insertions(+) diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index 001ce1fec..8106281ca 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -166,6 +166,31 @@ We also propose the following regex-powered algorithms as well as their generic |`prefixMatch(of:)`| Matches the specified `RegexComponent` against the collection at the beginning | |`matches(of:)`| Returns a collection containing all matches of the specified `RegexComponent` | +We also propose an overload of `~=` allowing regexes to be used in `case` expressions: + +```swift + switch "abcde" { + case /a.*f/: // never taken + case /abc/: // never taken + case /ab.*e/: return "success" + default: // never taken + } + + switch "2022-04-22" { + case decimalParser: // never taken + + case OneOrMore { + CharacterClass.whitespace + }: // never taken + + case #/\d{2}/\d{2}/\d{4}/# // never taken + + case dateParser: return "success" + + default: // never taken + } +``` + ## Detailed design @@ -1025,6 +1050,19 @@ extension RangeReplaceableCollection where Element: Equatable { } ``` +### Language-level pattern matching via `~=` + +We propose allowing any regex component be used in case statements by overloading the `~=` operator for matching against the entire input: + +```swift +extension RegexComponent { + public static func ~=(regex: Self, input: String) -> Bool + + public static func ~=(regex: Self, input: Substring) -> Bool +} +``` + + [SE-0346]: https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md [stdlib-pitch]: https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426 diff --git a/Tests/RegexBuilderTests/AlgorithmsTests.swift b/Tests/RegexBuilderTests/AlgorithmsTests.swift index 220535e31..173d41598 100644 --- a/Tests/RegexBuilderTests/AlgorithmsTests.swift +++ b/Tests/RegexBuilderTests/AlgorithmsTests.swift @@ -116,6 +116,9 @@ class RegexConsumerTests: XCTestCase { }: XCTFail() + case OneOrMore { CharacterClass.whitespace }: + XCTFail() + case "abc": XCTFail() From 9ff87db3250a6a4d7cf40e96bb58b41d46ed2495 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Tue, 26 Apr 2022 09:23:03 -0500 Subject: [PATCH 24/30] Fix empty.split w/ empty separator (#353) --- .../_StringProcessing/Algorithms/Algorithms/Split.swift | 4 ++++ Tests/RegexTests/AlgorithmsTests.swift | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 97d8c80dd..f7bbfbd0c 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -75,6 +75,10 @@ extension SplitCollection: Sequence { : base[index...] } + if index == base.endIndex { + return finish() + } + if splitCounter >= maxSplits { return finish() } diff --git a/Tests/RegexTests/AlgorithmsTests.swift b/Tests/RegexTests/AlgorithmsTests.swift index 965e2c42e..d63333c01 100644 --- a/Tests/RegexTests/AlgorithmsTests.swift +++ b/Tests/RegexTests/AlgorithmsTests.swift @@ -128,14 +128,17 @@ class AlgorithmTests: XCTestCase { XCTAssertEqual(actual, expected, file: file, line: line) } - expectSplit("", "", ["", ""]) + expectSplit("", "", [""]) expectSplit("", "x", [""]) expectSplit("a", "", ["", "a", ""]) expectSplit("a", "x", ["a"]) expectSplit("a", "a", ["", ""]) expectSplit("a____a____a", "_+", ["a", "a", "a"]) expectSplit("____a____a____a____", "_+", ["", "a", "a", "a", ""]) - + + XCTAssertEqual("".split(separator: ""), []) + XCTAssertEqual("".split(separator: "", omittingEmptySubsequences: false), [""]) + // Test that original `split` functions are still accessible let splitRef = "abcd".split XCTAssert(type(of: splitRef) == ((Character, Int, Bool) -> [Substring]).self) From 2401a58325385f54b4c881655d56c743723846e5 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Tue, 26 Apr 2022 09:23:20 -0500 Subject: [PATCH 25/30] Add a section describing 'find empty' behavior (#352) --- .../Evolution/StringProcessingAlgorithms.md | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Documentation/Evolution/StringProcessingAlgorithms.md b/Documentation/Evolution/StringProcessingAlgorithms.md index 8106281ca..58426c145 100644 --- a/Documentation/Evolution/StringProcessingAlgorithms.md +++ b/Documentation/Evolution/StringProcessingAlgorithms.md @@ -1066,11 +1066,50 @@ extension RegexComponent { [SE-0346]: https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md [stdlib-pitch]: https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426 +#### Searching for empty strings and matches + +Empty matches and inputs are an important edge case for several of the algorithms proposed above. For example, what is the result of `"123.firstRange(of: /[a-z]*/)`? How do you split a collection separated by an empty collection, as in `"1234".split(separator: "")`? For the Swift standard library, this is a new consideration, as current algorithms are `Element`-based and cannot be passed an empty input. + +Languages and libraries are nearly unanimous about finding the location of an empty string, with Ruby, Python, C#, Java, Javascript, etc, finding an empty string at each index in the target. Notably, Foundation's `NSString.range(of:)` does _not_ find an empty string at all. + +The methods proposed here follow the consensus behavior, which makes sense if you think of `a.firstRange(of: b)` as returning the first subrange `r` where `a[r] == b`. If a regex can match an empty substring, like `/[a-z]*/`, the behavior is the same. + +```swift +let hello = "Hello" +let emptyRange = hello.firstRange(of: "") +// emptyRange is equivalent to '0..<0' (integer ranges shown for readability) +``` + +Because searching again at the same index would yield that same empty string, we advance one position after finding an empty string or matching an empty pattern when finding all ranges. This yields the position of every valid index in the string. + +```swift +let allRanges = hello.ranges(of: "") +// allRanges is equivalent to '[0..<0, 1..<1, 2..<2, 3..<3, 4..<4, 5..<5]' +``` + +Splitting with an empty separator (or a pattern that matches empty string), uses this same behavior, resulting in a collection of single-element substrings. Interestingly, a couple languages make different choices here. C# returns the original string instead of its parts, and Python rejects an empty separator (though it permits regexes that match empty strings). + +```swift +let parts = hello.split(separator: "") +// parts == ["h", "e", "l", "l", "o"] + +let moreParts = hello.split(separator: "", omittingEmptySubsequences: false) +// parts == ["", "h", "e", "l", "l", "o", ""] +``` + +Finally, searching for an empty string within an empty string yields, as you might imagine, the empty string: + +```swift +let empty = "" +let range = empty.firstRange(of: empty) +// empty == empty[range] +``` + ## Alternatives considered ### Extend `Sequence` instead of `Collection` -Most of the proposed algorithms are necessarily on `Collection` due to the use of indices or mutation. `Sequence` does not support multi-pass iteration, so even `trimPrefix` would problematic on `Sequence` because it needs to look 1 `Element` ahead to know when to stop trimming. +Most of the proposed algorithms are necessarily on `Collection` due to the use of indices or mutation. `Sequence` does not support multi-pass iteration, so even `trimmingPrefix` would problematic on `Sequence` because it needs to look one `Element` ahead to know when to stop trimming and would need to return a wrapper for the in-progress iterator instead of a subsequence. ### Cross-proposal API naming consistency From d0598b7f50fe7fcfb58ce47ac09582e1bf632d8f Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Tue, 26 Apr 2022 09:24:13 -0500 Subject: [PATCH 26/30] Add example from RegexBuilder proposal as a test (#344) The "motivation tests" still aren't working on macOS CI --- Tests/RegexBuilderTests/MotivationTests.swift | 135 +++++++++++++++--- Tests/RegexBuilderTests/RegexDSLTests.swift | 32 +++++ 2 files changed, 145 insertions(+), 22 deletions(-) diff --git a/Tests/RegexBuilderTests/MotivationTests.swift b/Tests/RegexBuilderTests/MotivationTests.swift index 22e790e2d..7dd4c77e4 100644 --- a/Tests/RegexBuilderTests/MotivationTests.swift +++ b/Tests/RegexBuilderTests/MotivationTests.swift @@ -9,18 +9,14 @@ // //===----------------------------------------------------------------------===// -// FIXME: macOS CI seems to be busted and Linux doesn't have FormatStyle -// So, we disable this file for now - -#if false - -import _MatchingEngine - import XCTest import _StringProcessing - import RegexBuilder +// FIXME: macOS CI seems to be busted and Linux doesn't have FormatStyle +// So, we disable this larger test for now. +#if false + private struct Transaction: Hashable { enum Kind: Hashable { case credit @@ -140,17 +136,19 @@ private func processWithRuntimeDynamicRegex( ) -> Transaction? { // FIXME: Shouldn't this init throw? let regex = try! Regex(pattern) + let dateStrat = Date.FormatStyle(date: .numeric).parseStrategy + + guard let result = line.wholeMatch(of: regex)?.output, + let kind = Transaction.Kind(result[1].substring!), + let date = try? Date(String(result[2].substring!), strategy: dateStrat), + let account = result[3].substring.map(String.init), + let amount = try? Decimal( + String(result[4].substring!), format: .currency(code: "USD")) else { + return nil + } -// guard let result = line.match(regex) else { return nil } -// -// // TODO: We should have Regex or somesuch and `.1` -// // should be the same as `\1`. -// let dynCaps = result.1 -// -// -// let kind = Transaction.Kind(result.1.first!.capture as Substring) - - return nil + return Transaction( + kind: kind, date: date, account: account, amount: amount) } @available(macOS 12.0, *) @@ -239,7 +237,8 @@ extension RegexDSLTests { XCTAssertEqual( referenceOutput, processWithNSRegularExpression(line)) - _ = processWithRuntimeDynamicRegex(line) + XCTAssertEqual( + referenceOutput, processWithRuntimeDynamicRegex(line)) // Static run-time regex XCTAssertEqual( @@ -256,12 +255,104 @@ extension RegexDSLTests { XCTFail() continue } - } - } - } #endif +extension RegexDSLTests { + func testProposalExample() { + let statement = """ + CREDIT 04062020 PayPal transfer $4.99 + CREDIT 04032020 Payroll $69.73 + DEBIT 04022020 ACH transfer $38.25 + DEBIT 03242020 IRS tax payment $52249.98 + """ + let expectation: [(TransactionKind, Date, Substring, Double)] = [ + (.credit, Date(mmddyyyy: "04062020")!, "PayPal transfer", 4.99), + (.credit, Date(mmddyyyy: "04032020")!, "Payroll", 69.73), + (.debit, Date(mmddyyyy: "04022020")!, "ACH transfer", 38.25), + (.debit, Date(mmddyyyy: "03242020")!, "IRS tax payment", 52249.98), + ] + + enum TransactionKind: String { + case credit = "CREDIT" + case debit = "DEBIT" + } + + struct Date: Hashable { + var month: Int + var day: Int + var year: Int + + init?(mmddyyyy: String) { + guard let (_, m, d, y) = mmddyyyy.wholeMatch(of: Regex { + Capture(Repeat(.digit, count: 2), transform: { Int($0)! }) + Capture(Repeat(.digit, count: 2), transform: { Int($0)! }) + Capture(Repeat(.digit, count: 4), transform: { Int($0)! }) + })?.output else { + return nil + } + + self.month = m + self.day = d + self.year = y + } + } + + let statementRegex = Regex { + // First, lets capture the transaction kind by wrapping our ChoiceOf in a + // TryCapture because we want + TryCapture { + ChoiceOf { + "CREDIT" + "DEBIT" + } + } transform: { + TransactionKind(rawValue: String($0)) + } + + OneOrMore(.whitespace) + + // Next, lets represent our date as 3 separate repeat quantifiers. The first + // two will require 2 digit characters, and the last will require 4. Then + // we'll take the entire substring and try to parse a date out. + TryCapture { + Repeat(.digit, count: 2) + Repeat(.digit, count: 2) + Repeat(.digit, count: 4) + } transform: { + Date(mmddyyyy: String($0)) + } + + OneOrMore(.whitespace) + + // Next, grab the description which can be any combination of word characters, + // digits, etc. + Capture { + OneOrMore(.any, .reluctant) + } + + OneOrMore(.whitespace) + + "$" + + // Finally, we'll grab one or more digits which will represent the whole + // dollars, match the decimal point, and finally get 2 digits which will be + // our cents. + TryCapture { + OneOrMore(.digit) + "." + Repeat(.digit, count: 2) + } transform: { + Double($0) + } + } + + for (i, match) in statement.matches(of: statementRegex).enumerated() { + let (_, kind, date, description, amount) = match.output + XCTAssert((kind, date, description, amount) == expectation[i]) + } + } +} diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift index 42cb9c52e..b646f16f7 100644 --- a/Tests/RegexBuilderTests/RegexDSLTests.swift +++ b/Tests/RegexBuilderTests/RegexDSLTests.swift @@ -830,6 +830,38 @@ class RegexDSLTests: XCTestCase { XCTAssertEqual(result[b], 42) } + do { + let key = Reference(Substring.self) + let value = Reference(Int.self) + let input = " " + let regex = Regex { + Capture(as: key) { + Optionally { + OneOrMore(.word) + } + } + ":" + Optionally { + Capture(as: value) { + OneOrMore(.digit) + } transform: { Int($0)! } + } + } + + let result1 = try XCTUnwrap("age:123".wholeMatch(of: regex)) + XCTAssertEqual(result1[key], "age") + XCTAssertEqual(result1[value], 123) + + let result2 = try XCTUnwrap(":567".wholeMatch(of: regex)) + XCTAssertEqual(result2[key], "") + XCTAssertEqual(result2[value], 567) + + let result3 = try XCTUnwrap("status:".wholeMatch(of: regex)) + XCTAssertEqual(result3[key], "status") + // Traps: + // XCTAssertEqual(result3[value], nil) + } + // Post-hoc captured references // #"(?:\w\1|:(\w):)+"# try _testDSLCaptures( From 435090d1d13f08db1b88f5d2c909ed2b9a5b7061 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 26 Apr 2022 13:37:21 -0600 Subject: [PATCH 27/30] Refactor generator script (#356) * Number captures consistently * Proper indentation --- Sources/RegexBuilder/Variadics.swift | 1623 +++++++---------- .../VariadicsGenerator.swift | 123 +- Tests/RegexTests/MatchTests.swift | 1 + 3 files changed, 675 insertions(+), 1072 deletions(-) diff --git a/Sources/RegexBuilder/Variadics.swift b/Sources/RegexBuilder/Variadics.swift index 356853ec5..f06978c8b 100644 --- a/Sources/RegexBuilder/Variadics.swift +++ b/Sources/RegexBuilder/Variadics.swift @@ -15,496 +15,441 @@ @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0) { + ) -> Regex<(Substring, C1)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1) { + ) -> Regex<(Substring, C1, C2)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2) { + ) -> Regex<(Substring, C1, C2, C3)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3) { + ) -> Regex<(Substring, C1, C2, C3, C4)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == W0, R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1) { + ) -> Regex<(Substring, C1, C2)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2) { + ) -> Regex<(Substring, C1, C2, C3)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3) { + ) -> Regex<(Substring, C1, C2, C3, C4)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2) { + ) -> Regex<(Substring, C1, C2, C3)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3) { + ) -> Regex<(Substring, C1, C2, C3, C4)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3) { + ) -> Regex<(Substring, C1, C2, C3, C4)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> Regex<(Substring, C0, C1, C2, C3, C4, C5, C6)> where R0.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where R0.RegexOutput == (W0, 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( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3, C4, C5, C6, C7, C8), R1.RegexOutput == (W1, C9, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock( + public static func buildPartialBlock( accumulated: R0, next: R1 - ) -> 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) { + ) -> Regex<(Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where R0.RegexOutput == (W0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R1.RegexOutput == (W1, C10) { .init(node: accumulated.regex.root.appending(next.regex.root)) } } @@ -611,7 +556,6 @@ extension RegexComponentBuilder { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, @@ -624,7 +568,6 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -637,7 +580,6 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) public static func buildLimitedAvailability( _ component: Component ) -> Regex { @@ -646,7 +588,6 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, @@ -659,7 +600,6 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -673,7 +613,6 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, @@ -686,7 +625,6 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -700,7 +638,6 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, @@ -711,7 +648,6 @@ extension Repeat { self.init(node: .quantification(.exactly(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( count: Int, @@ -722,7 +658,6 @@ extension Repeat { self.init(node: .quantification(.exactly(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: Component, @@ -732,7 +667,6 @@ extension Repeat { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, @@ -744,11 +678,10 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, C1) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -756,11 +689,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, C1) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -768,20 +700,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?)> where Component.RegexOutput == (W, C0) { + ) -> Regex<(Substring, C1?)> where Component.RegexOutput == (W, C1) { .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, C1) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -789,11 +719,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, C1) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -802,11 +731,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1), Component.RegexOutput == (W, C1) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -814,11 +742,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1), Component.RegexOutput == (W, C1) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -827,51 +754,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0), R.Bound == Int { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, C1), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0), R.Bound == Int { + ) where RegexOutput == (Substring, C1?), Component.RegexOutput == (W, C1), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, C1, C2) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -879,11 +801,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, C1, C2) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -891,20 +812,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?)> where Component.RegexOutput == (W, C0, C1) { + ) -> Regex<(Substring, C1?, C2?)> where Component.RegexOutput == (W, C1, C2) { .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, C1, C2) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -912,11 +831,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, C1, C2) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -925,11 +843,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1, C2), Component.RegexOutput == (W, C1, C2) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -937,11 +854,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1, C2), Component.RegexOutput == (W, C1, C2) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -950,51 +866,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, C1, C2), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?), Component.RegexOutput == (W, C1, C2), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, C1, C2, C3) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1002,11 +913,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, C1, C2, C3) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1014,20 +924,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?)> where Component.RegexOutput == (W, C0, C1, C2) { + ) -> Regex<(Substring, C1?, C2?, C3?)> where Component.RegexOutput == (W, C1, C2, C3) { .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, C1, C2, C3) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1035,11 +943,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, C1, C2, C3) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1048,11 +955,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1, C2, C3), Component.RegexOutput == (W, C1, C2, C3) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1060,11 +966,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1, C2, C3), Component.RegexOutput == (W, C1, C2, C3) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1073,51 +978,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, C1, C2, C3), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?), Component.RegexOutput == (W, C1, C2, C3), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C1, C2, C3, C4) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1125,11 +1025,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C1, C2, C3, C4) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1137,20 +1036,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?)> where Component.RegexOutput == (W, C0, C1, C2, C3) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?)> where Component.RegexOutput == (W, C1, C2, C3, C4) { .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C1, C2, C3, C4) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1158,11 +1055,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C1, C2, C3, C4) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1171,11 +1067,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1, C2, C3, C4), Component.RegexOutput == (W, C1, C2, C3, C4) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1183,11 +1078,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1, C2, C3, C4), Component.RegexOutput == (W, C1, C2, C3, C4) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1196,51 +1090,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C1, C2, C3, C4), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C1, C2, C3, C4), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1248,11 +1137,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1260,20 +1148,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?, C5?)> where Component.RegexOutput == (W, 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( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1281,11 +1167,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1294,11 +1179,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1306,11 +1190,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1319,51 +1202,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C1, C2, C3, C4, C5), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C1, C2, C3, C4, C5), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1371,11 +1249,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1383,20 +1260,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?, C5?, C6?)> where Component.RegexOutput == (W, 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( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1404,11 +1279,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1417,11 +1291,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1429,11 +1302,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1442,51 +1314,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1494,11 +1361,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1506,20 +1372,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where Component.RegexOutput == (W, 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( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1527,11 +1391,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1540,11 +1403,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1552,11 +1414,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1565,51 +1426,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1617,11 +1473,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1629,20 +1484,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where Component.RegexOutput == (W, 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( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1650,11 +1503,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1663,11 +1515,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1675,11 +1526,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1688,51 +1538,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: Int - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = 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 { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) 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 { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1740,11 +1585,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1752,20 +1596,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> Regex<(Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where Component.RegexOutput == (W, 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( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1773,11 +1615,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1786,11 +1627,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = 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) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1798,11 +1638,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1811,51 +1650,46 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = 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 { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) 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 { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } @@ -1863,11 +1697,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } @@ -1875,20 +1708,18 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension RegexComponentBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildLimitedAvailability( + public static func buildLimitedAvailability( _ component: Component - ) -> 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) { + ) -> Regex<(Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?)> where Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { .init(node: .quantification(.zeroOrOne, .default, component.regex.root)) } } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } @@ -1896,11 +1727,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } @@ -1909,11 +1739,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ behavior: RegexRepetitionBehavior? = 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) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } @@ -1921,11 +1750,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) 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) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } @@ -1934,41 +1762,37 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, count: 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { 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(count), .default, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( count: Int, @RegexComponentBuilder _ component: () -> Component - ) 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) { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { 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(count), .default, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component, _ expression: R, _ behavior: RegexRepetitionBehavior? = 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 { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component - ) 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 { + ) where RegexOutput == (Substring, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( + public init( _ component: Component - ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1), Component.RegexOutput == (W, C1) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2006,18 +1830,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, C1), Component.RegexOutput == (W, C1) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1, C2), Component.RegexOutput == (W, C1, C2) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2025,18 +1849,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, C1, C2), Component.RegexOutput == (W, C1, C2) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1, C2, C3), Component.RegexOutput == (W, C1, C2, C3) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2044,18 +1868,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, C1, C2, C3), Component.RegexOutput == (W, C1, C2, C3) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1, C2, C3, C4), Component.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2063,18 +1887,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, C1, C2, C3, C4), Component.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component().regex.root)) } } @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2082,18 +1906,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5), Component.RegexOutput == (W, 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( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2101,18 +1925,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, 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( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2120,18 +1944,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, 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( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2139,18 +1963,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, 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( + public init( _ component: Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2158,18 +1982,18 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, 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( + public init( _ component: Component - ) 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) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .nonCapturingGroup(.atomicNonCapturing, component.regex.root)) } } @@ -2177,15 +2001,14 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> Component - ) 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) { + ) where RegexOutput == (Substring, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), Component.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { 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 { @@ -2194,7 +2017,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0) { @@ -2203,7 +2025,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1) { @@ -2212,7 +2033,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2) { @@ -2221,7 +2041,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3) { @@ -2230,7 +2049,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3, C4) { @@ -2239,7 +2057,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3, C4, C5) { @@ -2248,7 +2065,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6) { @@ -2257,7 +2073,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7) { @@ -2266,7 +2081,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8) { @@ -2275,7 +2089,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W1, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { @@ -2284,7 +2097,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0) { @@ -2293,7 +2105,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1) { @@ -2302,7 +2113,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2) { @@ -2311,7 +2121,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3) { @@ -2320,7 +2129,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4) { @@ -2329,7 +2137,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5) { @@ -2338,7 +2145,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6) { @@ -2347,7 +2153,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7) { @@ -2356,7 +2161,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8) { @@ -2365,7 +2169,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0), R1.RegexOutput == (W1, C1, C2, C3, C4, C5, C6, C7, C8, C9) { @@ -2374,7 +2177,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1) { @@ -2383,7 +2185,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2) { @@ -2392,7 +2193,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3) { @@ -2401,7 +2201,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4) { @@ -2410,7 +2209,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5) { @@ -2419,7 +2217,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6) { @@ -2428,7 +2225,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7) { @@ -2437,7 +2233,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8) { @@ -2446,7 +2241,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1), R1.RegexOutput == (W1, C2, C3, C4, C5, C6, C7, C8, C9) { @@ -2455,7 +2249,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2) { @@ -2464,7 +2257,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3) { @@ -2473,7 +2265,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4) { @@ -2482,7 +2273,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5) { @@ -2491,7 +2281,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6) { @@ -2500,7 +2289,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7) { @@ -2509,7 +2297,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8) { @@ -2518,7 +2305,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2), R1.RegexOutput == (W1, C3, C4, C5, C6, C7, C8, C9) { @@ -2527,7 +2313,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3) { @@ -2536,7 +2321,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4) { @@ -2545,7 +2329,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5) { @@ -2554,7 +2337,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6) { @@ -2563,7 +2345,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7) { @@ -2572,7 +2353,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8) { @@ -2581,7 +2361,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3), R1.RegexOutput == (W1, C4, C5, C6, C7, C8, C9) { @@ -2590,7 +2369,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4) { @@ -2599,7 +2377,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5) { @@ -2608,7 +2385,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6) { @@ -2617,7 +2393,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7) { @@ -2626,7 +2401,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8) { @@ -2635,7 +2409,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4), R1.RegexOutput == (W1, C5, C6, C7, C8, C9) { @@ -2644,7 +2417,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5) { @@ -2653,7 +2425,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6) { @@ -2662,7 +2433,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7) { @@ -2671,7 +2441,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8) { @@ -2680,7 +2449,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5), R1.RegexOutput == (W1, C6, C7, C8, C9) { @@ -2689,7 +2457,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6) { @@ -2698,7 +2465,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7) { @@ -2707,7 +2473,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8) { @@ -2716,7 +2481,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6), R1.RegexOutput == (W1, C7, C8, C9) { @@ -2725,7 +2489,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7) { @@ -2734,7 +2497,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8) { @@ -2743,7 +2505,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7), R1.RegexOutput == (W1, C8, C9) { @@ -2752,7 +2513,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8) { @@ -2761,7 +2521,6 @@ extension AlternationBuilder { } @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.RegexOutput == (W0, C0, C1, C2, C3, C4, C5, C6, C7, C8), R1.RegexOutput == (W1, C9) { @@ -2770,71 +2529,61 @@ extension AlternationBuilder { } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?)> where R: RegexComponent, R.RegexOutput == (W, C0) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?)> where R: RegexComponent, R.RegexOutput == (W, C1) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @available(SwiftStdlib 5.7, *) - public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C0?, C1?)> where R: RegexComponent, R.RegexOutput == (W, C0, C1) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?, C5?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4, C5) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?, C5?, C6?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?, C5?, C6?, C7?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { .init(node: .orderedChoice([regex.regex.root])) } } @available(SwiftStdlib 5.7, *) extension AlternationBuilder { - @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) { + public static func buildPartialBlock(first regex: R) -> ChoiceOf<(W, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?, C10?)> where R: RegexComponent, R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { .init(node: .orderedChoice([regex.regex.root])) } } @@ -2842,7 +2591,6 @@ extension AlternationBuilder { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R @@ -2850,7 +2598,6 @@ extension Capture { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, as reference: Reference @@ -2858,7 +2605,6 @@ extension Capture { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, @@ -2871,7 +2617,6 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, @@ -2890,7 +2635,6 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, @@ -2903,7 +2647,6 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( _ component: R, @@ -2924,7 +2667,6 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> R @@ -2932,7 +2674,6 @@ extension Capture { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( as reference: Reference, @@ -2943,7 +2684,6 @@ extension Capture { component().regex.root)) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> R, @@ -2956,7 +2696,6 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( as reference: Reference, @@ -2975,7 +2714,6 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( @RegexComponentBuilder _ component: () -> R, @@ -2988,7 +2726,6 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( as reference: Reference, @@ -3009,25 +2746,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, W, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, W, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3035,12 +2769,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture( reference: reference.id, .transform( @@ -3053,11 +2786,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3065,12 +2797,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture( reference: reference.id, .transform( @@ -3085,28 +2816,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, W, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, W, C1), R.RegexOutput == (W, C1) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3114,12 +2842,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture( reference: reference.id, .transform( @@ -3132,11 +2859,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3144,12 +2870,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0), R.RegexOutput == (W, C0) { + ) where RegexOutput == (Substring, NewCapture, C1), R.RegexOutput == (W, C1) { self.init(node: .capture( reference: reference.id, .transform( @@ -3164,25 +2889,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3190,12 +2912,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( @@ -3208,11 +2929,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3220,12 +2940,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( @@ -3240,28 +2959,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, W, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3269,12 +2985,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( @@ -3287,11 +3002,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3299,12 +3013,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1), R.RegexOutput == (W, C0, C1) { + ) where RegexOutput == (Substring, NewCapture, C1, C2), R.RegexOutput == (W, C1, C2) { self.init(node: .capture( reference: reference.id, .transform( @@ -3319,25 +3032,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3345,12 +3055,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( @@ -3363,11 +3072,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3375,12 +3083,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( @@ -3395,28 +3102,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, W, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3424,12 +3128,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( @@ -3442,11 +3145,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3454,12 +3156,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2), R.RegexOutput == (W, C0, C1, C2) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3), R.RegexOutput == (W, C1, C2, C3) { self.init(node: .capture( reference: reference.id, .transform( @@ -3474,25 +3175,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3500,12 +3198,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( @@ -3518,11 +3215,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3530,12 +3226,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( @@ -3550,28 +3245,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3579,12 +3271,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( @@ -3597,11 +3288,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3609,12 +3299,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3), R.RegexOutput == (W, C0, C1, C2, C3) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4), R.RegexOutput == (W, C1, C2, C3, C4) { self.init(node: .capture( reference: reference.id, .transform( @@ -3629,25 +3318,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3655,12 +3341,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( @@ -3673,11 +3358,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3685,12 +3369,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( @@ -3705,28 +3388,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3734,12 +3414,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( @@ -3752,11 +3431,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3764,12 +3442,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4), R.RegexOutput == (W, C0, C1, C2, C3, C4) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5), R.RegexOutput == (W, C1, C2, C3, C4, C5) { self.init(node: .capture( reference: reference.id, .transform( @@ -3784,25 +3461,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3810,12 +3484,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( @@ -3828,11 +3501,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3840,12 +3512,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( @@ -3860,28 +3531,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3889,12 +3557,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( @@ -3907,11 +3574,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3919,12 +3585,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? - ) where RegexOutput == (Substring, NewCapture, C0, C1, C2, C3, C4, C5), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6) { self.init(node: .capture( reference: reference.id, .transform( @@ -3939,25 +3604,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -3965,12 +3627,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( @@ -3983,11 +3644,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -3995,12 +3655,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( @@ -4015,28 +3674,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4044,12 +3700,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( @@ -4062,11 +3717,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4074,12 +3728,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7) { self.init(node: .capture( reference: reference.id, .transform( @@ -4094,25 +3747,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4120,12 +3770,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( @@ -4138,11 +3787,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4150,12 +3798,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( @@ -4170,28 +3817,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) where RegexOutput == (Substring, W, C0, C1, C2, C3, C4, C5, C6, C7), R.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4199,12 +3843,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( @@ -4217,11 +3860,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4229,12 +3871,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8) { self.init(node: .capture( reference: reference.id, .transform( @@ -4249,25 +3890,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4275,12 +3913,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( @@ -4293,11 +3930,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4305,12 +3941,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( @@ -4325,28 +3960,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4354,12 +3986,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( @@ -4372,11 +4003,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4384,12 +4014,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9) { self.init(node: .capture( reference: reference.id, .transform( @@ -4404,25 +4033,22 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4430,12 +4056,11 @@ extension Capture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture( reference: reference.id, .transform( @@ -4448,11 +4073,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4460,12 +4084,11 @@ extension TryCapture { component.regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( _ component: R, as reference: Reference, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture( reference: reference.id, .transform( @@ -4480,28 +4103,25 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R - ) 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) { + ) where RegexOutput == (Substring, W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture( reference: reference.id, component().regex.root)) } - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any @@ -4509,12 +4129,11 @@ extension Capture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture( reference: reference.id, .transform( @@ -4527,11 +4146,10 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { - @available(SwiftStdlib 5.7, *) - public init( + public init( @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture(.transform( CaptureTransform(resultType: NewCapture.self) { try transform($0) as Any? @@ -4539,12 +4157,11 @@ extension TryCapture { component().regex.root))) } - @available(SwiftStdlib 5.7, *) - public init( + public init( as reference: Reference, @RegexComponentBuilder _ component: () -> R, 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) { + ) where RegexOutput == (Substring, NewCapture, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10), R.RegexOutput == (W, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) { self.init(node: .capture( reference: reference.id, .transform( diff --git a/Sources/VariadicsGenerator/VariadicsGenerator.swift b/Sources/VariadicsGenerator/VariadicsGenerator.swift index f57cd8caa..56e2f3790 100644 --- a/Sources/VariadicsGenerator/VariadicsGenerator.swift +++ b/Sources/VariadicsGenerator/VariadicsGenerator.swift @@ -58,6 +58,17 @@ struct Permutations: Sequence { } } +func captureTypeList( + _ arity: Int, + lowerBound: Int = 0, + optional: Bool = false +) -> String { + let opt = optional ? "?" : "" + return (lowerBound..( accumulated: R0, next: R1 ) -> \(regexTypeName)<\(matchType)> \(whereClause) { @@ -340,24 +348,23 @@ struct VariadicsGenerator: ParsableCommand { } init(kind: QuantifierKind, arity: Int) { - self.disfavored = arity == 0 ? "@_disfavoredOverload\n" : "" + self.disfavored = arity == 0 ? " @_disfavoredOverload\n" : "" self.genericParams = { var result = "" if arity > 0 { - result += "W" - result += (0..( _ component: Component, _ behavior: RegexRepetitionBehavior? = nil @@ -391,8 +397,7 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension \(kind.rawValue) { - \(defaultAvailableAttr) - \(params.disfavored)\ + \(params.disfavored)\ public init<\(params.genericParams)>( _ behavior: RegexRepetitionBehavior? = nil, @\(concatBuilderName) _ component: () -> Component @@ -406,7 +411,6 @@ struct VariadicsGenerator: ParsableCommand { """ \(defaultAvailableAttr) extension \(concatBuilderName) { - \(defaultAvailableAttr) public static func buildLimitedAvailability<\(params.genericParams)>( _ component: Component ) -> \(regexTypeName)<\(params.matchType)> \(params.whereClause) { @@ -430,19 +434,18 @@ struct VariadicsGenerator: ParsableCommand { """ } - let disfavored = arity == 0 ? "@_disfavoredOverload\n" : "" + let disfavored = arity == 0 ? " @_disfavoredOverload\n" : "" let genericParams: String = { var result = "" if arity > 0 { - result += "W" - result += (0..( _ component: Component ) \(whereClauseForInit) { @@ -464,7 +467,7 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension \(groupName) { \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams)>( @\(concatBuilderName) _ component: () -> Component ) \(whereClauseForInit) { @@ -486,8 +489,7 @@ struct VariadicsGenerator: ParsableCommand { output(""" \(defaultAvailableAttr) extension Repeat { - \(defaultAvailableAttr) - \(params.disfavored)\ + \(params.disfavored)\ public init<\(params.genericParams)>( _ component: Component, count: Int @@ -497,8 +499,7 @@ struct VariadicsGenerator: ParsableCommand { self.init(node: .quantification(.exactly(count), .default, component.regex.root)) } - \(defaultAvailableAttr) - \(params.disfavored)\ + \(params.disfavored)\ public init<\(params.genericParams)>( count: Int, @\(concatBuilderName) _ component: () -> Component @@ -508,8 +509,7 @@ struct VariadicsGenerator: ParsableCommand { self.init(node: .quantification(.exactly(count), .default, component().regex.root)) } - \(defaultAvailableAttr) - \(params.disfavored)\ + \(params.disfavored)\ public init<\(params.genericParams), R: RangeExpression>( _ component: Component, _ expression: R, @@ -518,8 +518,7 @@ struct VariadicsGenerator: ParsableCommand { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, _ behavior: RegexRepetitionBehavior? = nil, @@ -573,7 +572,6 @@ struct VariadicsGenerator: ParsableCommand { output(""" \(defaultAvailableAttr) extension \(altBuilderName) { - \(defaultAvailableAttr) public static func buildPartialBlock<\(genericParams)>( accumulated: R0, next: R1 ) -> ChoiceOf<\(matchType)> \(whereClause) { @@ -586,7 +584,7 @@ struct VariadicsGenerator: ParsableCommand { func emitUnaryAlternationBuildBlock(arity: Int) { assert(arity > 0) - let captures = (0..(first regex: R) -> ChoiceOf<(W, \(resultCaptures))> \(whereClause) { .init(node: .orderedChoice([regex.regex.root])) } @@ -611,17 +608,17 @@ struct VariadicsGenerator: ParsableCommand { } func emitCapture(arity: Int) { - let disfavored = arity == 0 ? "@_disfavoredOverload\n" : "" + let disfavored = arity == 0 ? " @_disfavoredOverload\n" : "" let genericParams = arity == 0 ? "R: \(regexComponentProtocolName), W" - : "R: \(regexComponentProtocolName), W, " + (0.. String { return arity == 0 ? "(\(baseMatchTypeName), \(newCaptureType))" - : "(\(baseMatchTypeName), \(newCaptureType), " + (0..( _ component: R ) \(whereClauseRaw) { self.init(node: .capture(component.regex.root)) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams)>( _ component: R, as reference: Reference ) \(whereClauseRaw) { self.init(node: .capture(reference: reference.id, component.regex.root)) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, transform: @escaping (Substring) throws -> NewCapture @@ -661,8 +655,7 @@ struct VariadicsGenerator: ParsableCommand { component.regex.root))) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, as reference: Reference, @@ -680,8 +673,7 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension TryCapture { - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, transform: @escaping (Substring) throws -> NewCapture? @@ -693,8 +685,7 @@ struct VariadicsGenerator: ParsableCommand { component.regex.root))) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( _ component: R, as reference: Reference, @@ -714,16 +705,14 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension Capture { - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams)>( @\(concatBuilderName) _ component: () -> R ) \(whereClauseRaw) { self.init(node: .capture(component().regex.root)) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams)>( as reference: Reference, @\(concatBuilderName) _ component: () -> R @@ -733,8 +722,7 @@ struct VariadicsGenerator: ParsableCommand { component().regex.root)) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( @\(concatBuilderName) _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture @@ -746,8 +734,7 @@ struct VariadicsGenerator: ParsableCommand { component().regex.root))) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( as reference: Reference, @\(concatBuilderName) _ component: () -> R, @@ -765,8 +752,7 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension TryCapture { - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( @\(concatBuilderName) _ component: () -> R, transform: @escaping (Substring) throws -> NewCapture? @@ -778,8 +764,7 @@ struct VariadicsGenerator: ParsableCommand { component().regex.root))) } - \(defaultAvailableAttr) - \(disfavored)\ + \(disfavored)\ public init<\(genericParams), NewCapture>( as reference: Reference, @\(concatBuilderName) _ component: () -> R, diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index dab53cc1c..345e80e22 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -1549,5 +1549,6 @@ extension RegexTests { // TODO: Add test for implied grapheme cluster requirement at group boundaries // TODO: Add test for grapheme boundaries at start/end of match + } From 96df14d0379acbe0fce937f39d7da690a3186faa Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 26 Apr 2022 13:28:17 -0700 Subject: [PATCH 28/30] Fix cut-off sentence. Co-authored-by: Nate Cook --- Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift index c06643aee..bf379fc14 100644 --- a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift +++ b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift @@ -57,7 +57,7 @@ extension PrettyPrinter { /// Outputs a string directly, without termination or /// indentation, and without updating any internal state. /// - /// This is the low-level interface to the pret + /// This is the low-level interface to the pretty printer. /// /// - Note: If `s` includes a newline, even at the end, /// this method does not update any tracking state. From 0e59bdf59b4b4d96381aeb6add164fdae31584ca Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 26 Apr 2022 20:45:30 -0600 Subject: [PATCH 29/30] Update Sources/_StringProcessing/Regex/Match.swift --- Sources/_StringProcessing/Regex/Match.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index dd36c8823..9937f1e03 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -191,7 +191,6 @@ extension String { extension RegexComponent { public static func ~=(regex: Self, input: String) -> Bool { input.wholeMatch(of: regex) != nil - try? r.regex.wholeMatch(in: self) } public static func ~=(regex: Self, input: Substring) -> Bool { From ac618f63eb2071703406c806f44ec63f57247f78 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 27 Apr 2022 11:08:27 -0700 Subject: [PATCH 30/30] Back out an accidental source change. Confirmed (using the command below) that this branch now contains only changes to doc comments, changes to // comments where content was moved into or out of a doc comment, and one spelling correction to code. % git diff origin/main... | grep -v '^+ *///\|- *///' | grep -v '^@@' | grep -v '^ ' | grep -v '^+++\|^---' | grep -v '^diff --git' | grep -v '^index ' + // Individual public API functions are in the generated Variadics.swift file. +// For now, we use String as the source while prototyping... + + // NOTE: Currently, this means we have raw quotes. + // Better would be to have real Swift string delimiter parsing logic. + + // NOTE: traditional comments are not nested. Currently, we are neither. + // Traditional comments can't have `)`, not even escaped in them either, we + // can. Traditional comments can have `*/` in them, we can't without + // escaping. We don't currently do escaping. + - // Finish, flush, and clear. Returns the rendered output + // Finish, flush, and clear. + // + // - Returns: The rendered output. + // Note: The `Script` enum includes the "meta" script type "Katakana_Or_Hiragana", which + // isn't defined by https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt, + // but is defined by https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt. + // We may want to split it out, as it's the only case that is a union of + // other script types. + +// TODO: These should become aliases for the Block (blk) Unicode character +// property. + - // Ensures `.0` always refers to the whole match. - // Allows `.0` when `Match` is not a tuple. - func withInversion(_ invertion: Bool) -> Self { + func withInversion(_ inversion: Bool) -> Self { - if invertion { + if inversion { --- Sources/_StringProcessing/Regex/Match.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 9937f1e03..8172e993b 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -165,7 +165,7 @@ extension Regex { } @available(SwiftStdlib 5.7, *) -extension String { +extension BidirectionalCollection where SubSequence == Substring { /// Checks for a match against the string in its entirety. /// /// - Parameter r: The regular expression being matched.