From 36e0690d0e70261b42a67090124d016299e79988 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 6 Oct 2022 17:25:13 -0500 Subject: [PATCH 1/7] Atomically load the lowered program (#610) Since we're atomically initializing the compiled program in `Regex.Program`, we need to pair that with an atomic load. Resolves #609. --- Sources/_StringProcessing/Regex/Core.swift | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Sources/_StringProcessing/Regex/Core.swift b/Sources/_StringProcessing/Regex/Core.swift index f58f63de7..ba40f4f90 100644 --- a/Sources/_StringProcessing/Regex/Core.swift +++ b/Sources/_StringProcessing/Regex/Core.swift @@ -95,12 +95,29 @@ extension Regex { /// The program for execution with the matching engine. var loweredProgram: MEProgram { - if let loweredObject = _loweredProgramStorage as? ProgramBox { - return loweredObject.value + /// Atomically loads the compiled program if it has already been stored. + func loadProgram() -> MEProgram? { + guard let loweredObject = _stdlib_atomicLoadARCRef(object: &_loweredProgramStorage) + else { return nil } + return unsafeDowncast(loweredObject, to: ProgramBox.self).value } - let lowered = try! Compiler(tree: tree, compileOptions: compileOptions).emit() - _stdlib_atomicInitializeARCRef(object: &_loweredProgramStorage, desired: ProgramBox(lowered)) - return lowered + + // Use the previously compiled program, if available. + if let program = loadProgram() { + return program + } + + // Compile the DSLTree into a lowered program and store it atomically. + let compiledProgram = try! Compiler(tree: tree, compileOptions: compileOptions).emit() + let storedNewProgram = _stdlib_atomicInitializeARCRef( + object: &_loweredProgramStorage, + desired: ProgramBox(compiledProgram)) + + // Return the winner of the storage race. We're guaranteed at this point + // to have compiled program stored in `_loweredProgramStorage`. + return storedNewProgram + ? compiledProgram + : loadProgram()! } init(ast: AST) { From 134c837c965c9260f73c32845af39af2d65738d9 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Fri, 2 Dec 2022 09:22:07 -0600 Subject: [PATCH 2/7] Add tests for line start/end word boundary diffs (#616) The `default` and `simple` word boundaries have different behaviors at the start and end of strings/lines. These tests validate that we have the correct behavior implemented. Related to issue #613. --- Tests/RegexTests/MatchTests.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index 2fa9b9381..a1bf0e76f 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -1517,6 +1517,19 @@ extension RegexTests { (" 123", "23"), ("123 456", "23")) + let defaultBoundaryRegex = try Regex(#"\b.{3}X.{3}\b"#) + // Default word boundaries match at the start/end of a string/line. + XCTAssertNotNil(try defaultBoundaryRegex.firstMatch(in: "---X---")) + XCTAssertNotNil(try defaultBoundaryRegex.firstMatch(in: "abc\n---X---\ndef")) + + let simpleBoundaryRegex = defaultBoundaryRegex.wordBoundaryKind(.simple) + // Simple word boundaries match only when the adjacent position matches \w. + XCTAssertNil(try simpleBoundaryRegex.firstMatch(in: "---X---")) + XCTAssertNil(try simpleBoundaryRegex.firstMatch(in: "abc\n---X---\ndef")) + + XCTAssertNotNil(try simpleBoundaryRegex.firstMatch(in: "x--X--x")) + XCTAssertNotNil(try simpleBoundaryRegex.firstMatch(in: "abc\nx--X--x\ndef")) + // \G and \K let regex = try Regex(#"\Gab"#, as: Substring.self) XCTAssertEqual("abab".matches(of: regex).map(\.output), ["ab", "ab"]) From e5357786e5ce9a9da6c602cf19ec540793ad2423 Mon Sep 17 00:00:00 2001 From: Ole Begemann Date: Tue, 6 Dec 2022 20:30:38 +0100 Subject: [PATCH 3/7] Fix documentation typo (#615) --- Sources/RegexBuilder/Anchor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/RegexBuilder/Anchor.swift b/Sources/RegexBuilder/Anchor.swift index cf1931577..8283b9cbd 100644 --- a/Sources/RegexBuilder/Anchor.swift +++ b/Sources/RegexBuilder/Anchor.swift @@ -81,7 +81,7 @@ extension Anchor { } /// An anchor that matches at the end of the input string or at the end of - /// the line immediately before the the end of the string. + /// the line immediately before the end of the string. /// /// This anchor is equivalent to `\Z` in regex syntax. public static var endOfSubjectBeforeNewline: Anchor { From cbc6738c87eaf92bf9f78208122a1e8ef2660cef Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 6 Dec 2022 11:32:47 -0800 Subject: [PATCH 4/7] Fix abstract for Regex.dotMatchesNewlines(_:). (#614) The old version looks like it was accidentally duplicated from anchorsMatchLineEndings(_:) just below it. --- Sources/_StringProcessing/Regex/Options.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/_StringProcessing/Regex/Options.swift b/Sources/_StringProcessing/Regex/Options.swift index 88d2dbf5d..368a5b634 100644 --- a/Sources/_StringProcessing/Regex/Options.swift +++ b/Sources/_StringProcessing/Regex/Options.swift @@ -68,8 +68,8 @@ extension Regex { wrapInOption(.unicodeWordBoundaries, addingIf: wordBoundaryKind == .default) } - /// Returns a regular expression where the start and end of input - /// anchors (`^` and `$`) also match against the start and end of a line. + /// Returns a regular expression where the "any" metacharacter (`.`) + /// also matches against the start and end of a line. /// /// - Parameter dotMatchesNewlines: A Boolean value indicating whether `.` /// should match a newline character. From 87fb60223062b9a77ef85a9e3dd3f36015bee4ef Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Wed, 14 Dec 2022 13:15:24 -0600 Subject: [PATCH 5/7] Remove `RegexConsumer` and fix its dependencies (#617) * Remove `RegexConsumer` and fix its dependencies This eliminates the RegexConsumer type and rewrites its users to call through to other, existing functionality on Regex or in the Algorithms implementations. RegexConsumer doesn't take account of the dual subranges required for matching, so it can produce results that are inconsistent with matches(of:) and ranges(of:), which were rewritten earlier. rdar://102841216 * Remove remaining from-end algorithm methods This removes methods that are left over from when we were considering from-end algorithms. These aren't tested and may not have the correct semantics, so it's safer to remove them entirely. --- .../Algorithms/Algorithms/FirstRange.swift | 17 +- .../Algorithms/Algorithms/Ranges.swift | 83 ------- .../Algorithms/Algorithms/Split.swift | 189 +++------------- .../Algorithms/Algorithms/StartsWith.swift | 43 +--- .../Algorithms/Algorithms/Trim.swift | 209 +----------------- .../Algorithms/Consumers/RegexConsumer.swift | 98 -------- .../Algorithms/Matching/FirstMatch.swift | 15 -- .../Algorithms/Matching/MatchReplace.swift | 39 ---- .../Algorithms/Matching/Matches.swift | 7 - .../Algorithms/Searchers/TwoWaySearcher.swift | 8 + .../RegexTests/AlgorithmsInternalsTests.swift | 8 - Tests/RegexTests/RenderDSLTests.swift | 13 +- 12 files changed, 63 insertions(+), 666 deletions(-) delete mode 100644 Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift b/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift index 696f36eca..484ff4648 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift @@ -20,15 +20,6 @@ extension Collection { } } -extension BidirectionalCollection { - func _lastRange( - of searcher: S - ) -> Range? where S.BackwardSearched == Self { - var state = searcher.backwardState(for: self, in: startIndex.. Range? { - _firstRange(of: RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - func _lastRange(of regex: R) -> Range? { - _lastRange(of: RegexConsumer(regex)) + let s = self[...] + return try? regex.regex.firstMatch(in: s)?.range } } diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift index fc6b23af2..030ce1f64 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift @@ -115,43 +115,6 @@ extension RangesCollection.Index: Comparable { } } -// MARK: `ReversedRangesCollection` - -struct ReversedRangesCollection { - typealias Base = Searcher.BackwardSearched - - let base: Base - let searcher: Searcher - - init(base: Base, searcher: Searcher) { - self.base = base - self.searcher = searcher - } -} - -extension ReversedRangesCollection: Sequence { - public struct Iterator: IteratorProtocol { - let base: Base - let searcher: Searcher - var state: Searcher.BackwardState - - init(base: Base, searcher: Searcher) { - self.base = base - self.searcher = searcher - self.state = searcher.backwardState( - for: base, in: base.startIndex.. Range? { - searcher.searchBack(base, &state) - } - } - - public func makeIterator() -> Iterator { - Iterator(base: base, searcher: searcher) - } -} - // TODO: `Collection` conformance // MARK: `CollectionSearcher` algorithms @@ -164,14 +127,6 @@ extension Collection { } } -extension BidirectionalCollection { - func _rangesFromBack( - of searcher: S - ) -> ReversedRangesCollection where S.BackwardSearched == Self { - ReversedRangesCollection(base: self, searcher: searcher) - } -} - // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { @@ -195,37 +150,6 @@ extension Collection where Element: Equatable { } } -extension BidirectionalCollection where Element: Equatable { - // FIXME -// public func rangesFromBack( -// of other: S -// ) -> ReversedRangesCollection> -// where S.Element == Element -// { -// fatalError() -// } -} - -extension BidirectionalCollection where Element: Comparable { - func _ranges( - of other: C - ) -> RangesCollection>> - where C.Element == Element - { - _ranges(of: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other)))) - } - - // FIXME -// public func rangesFromBack( -// of other: S -// ) -> ReversedRangesCollection>> -// where S.Element == Element -// { -// rangesFromBack( -// of: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other)))) -// } -} - @available(SwiftStdlib 5.7, *) struct RegexRangesCollection { let base: RegexMatchesCollection @@ -299,13 +223,6 @@ extension Collection where SubSequence == Substring { } extension BidirectionalCollection where SubSequence == Substring { - @available(SwiftStdlib 5.7, *) - func _rangesFromBack( - of regex: R - ) -> ReversedRangesCollection> { - _rangesFromBack(of: RegexConsumer(regex)) - } - // FIXME: Return `some Collection>` for SE-0346 /// Finds and returns the ranges of the all occurrences of a given sequence /// within the collection. diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 44364df71..6634d2945 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -106,121 +106,6 @@ extension SplitCollection: Sequence { } } -//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` - -struct ReversedSplitCollection { - public typealias Base = Searcher.BackwardSearched - - let ranges: ReversedRangesCollection - - init(ranges: ReversedRangesCollection) { - self.ranges = ranges - } - - init(base: Base, searcher: Searcher) { - self.ranges = base._rangesFromBack(of: searcher) - } -} - -extension ReversedSplitCollection: Sequence { - public struct Iterator: IteratorProtocol { - let base: Base - var index: Base.Index - var ranges: ReversedRangesCollection.Iterator - var isDone: Bool - - init(ranges: ReversedRangesCollection) { - self.base = ranges.base - self.index = base.endIndex - self.ranges = ranges.makeIterator() - self.isDone = false - } - - public mutating func next() -> Base.SubSequence? { - guard !isDone else { return nil } - - guard let range = ranges.next() else { - isDone = true - return base[.. Iterator { - Iterator(ranges: ranges) - } -} - -// TODO: `Collection` conformance - // MARK: `CollectionSearcher` algorithms extension Collection { @@ -237,16 +122,6 @@ extension Collection { } } -extension BidirectionalCollection { - func splitFromBack( - by separator: Searcher - ) -> ReversedSplitCollection - where Searcher.BackwardSearched == Self - { - ReversedSplitCollection(base: self, searcher: separator) - } -} - // MARK: Predicate algorithms extension Collection { @@ -260,14 +135,6 @@ extension Collection { } } -extension BidirectionalCollection where Element: Equatable { - func splitFromBack( - whereSeparator predicate: @escaping (Element) -> Bool - ) -> ReversedSplitCollection> { - splitFromBack(by: PredicateConsumer(predicate: predicate)) - } -} - // MARK: Single element algorithms extension Collection where Element: Equatable { @@ -280,14 +147,6 @@ extension Collection where Element: Equatable { } } -extension BidirectionalCollection where Element: Equatable { - func splitFromBack( - by separator: Element - ) -> ReversedSplitCollection> { - splitFromBack(whereSeparator: { $0 == separator }) - } -} - // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { @@ -399,21 +258,6 @@ extension StringProtocol where SubSequence == Substring { @available(SwiftStdlib 5.7, *) extension BidirectionalCollection where SubSequence == Substring { - @_disfavoredOverload - func split( - by separator: R, - maxSplits: Int, - omittingEmptySubsequences: Bool - ) -> SplitCollection> { - split(by: RegexConsumer(separator), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences) - } - - func splitFromBack( - by separator: R - ) -> ReversedSplitCollection> { - splitFromBack(by: RegexConsumer(separator)) - } - // 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 @@ -431,9 +275,34 @@ extension BidirectionalCollection where SubSequence == Substring { maxSplits: Int = .max, omittingEmptySubsequences: Bool = true ) -> [SubSequence] { - Array(split( - by: RegexConsumer(separator), - maxSplits: maxSplits, - omittingEmptySubsequences: omittingEmptySubsequences)) + var result: [SubSequence] = [] + var subSequenceStart = startIndex + + func appendSubsequence(end: Index) -> Bool { + if subSequenceStart == end && omittingEmptySubsequences { + return false + } + result.append(self[subSequenceStart.. 0 && !isEmpty else { + _ = appendSubsequence(end: endIndex) + return result + } + + for match in _matches(of: separator) { + defer { subSequenceStart = match.range.upperBound } + let didAppend = appendSubsequence(end: match.range.lowerBound) + if didAppend && result.count == maxSplits { + break + } + } + + if subSequenceStart != endIndex || !omittingEmptySubsequences { + result.append(self[subSequenceStart..(with consumer: C) -> Bool - where C.Consumed == SubSequence - { - consumer.consuming(self[...]) != nil - } -} - -extension BidirectionalCollection { - func _ends(with consumer: C) -> Bool - where C.Consumed == SubSequence - { - consumer.consumingBack(self[...]) != nil - } -} - -// MARK: Fixed pattern algorithms - -extension Collection where Element: Equatable { - func _starts(with prefix: C) -> Bool - where C.Element == Element - { - _starts(with: FixedPatternConsumer(pattern: prefix)) - } -} - -extension BidirectionalCollection where Element: Equatable { - func _ends(with suffix: C) -> Bool - where C.Element == Element - { - _ends(with: FixedPatternConsumer(pattern: suffix)) - } -} - // MARK: Regex algorithms @available(SwiftStdlib 5.7, *) @@ -56,10 +20,7 @@ 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 { - _starts(with: RegexConsumer(regex)) - } - - func _ends(with regex: R) -> Bool { - _ends(with: RegexConsumer(regex)) + let s = self[...] + return (try? regex.regex.prefixMatch(in: s)) != nil } } diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift index 37f7513db..2908c4dc5 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Trim.swift @@ -41,64 +41,6 @@ extension RangeReplaceableCollection { } } -extension BidirectionalCollection { - func _trimmingSuffix( - _ consumer: Consumer - ) -> SubSequence - where Consumer.Consumed == Self - { - let end = consumer.consumingBack(self) ?? endIndex - return self[..( - _ consumer: Consumer - ) -> SubSequence where Consumer.Consumed == Self { - // NOTE: Might give different results than trimming the suffix before - // trimming the prefix - let start = consumer.consuming(self) ?? startIndex - let end = consumer.consumingBack(self) ?? endIndex - let actualEnd = end < start ? start : end - return self[start..( - _ consumer: Consumer - ) where Consumer.Consumed == SubSequence - { - _ = consumer.consumeBack(&self) - } - - mutating func _trim( - _ consumer: Consumer - ) where Consumer.Consumed == Self { - _trimPrefix(consumer) - _trimSuffix(consumer) - } -} - -extension RangeReplaceableCollection where Self: BidirectionalCollection { - @_disfavoredOverload - mutating func _trimSuffix( - _ consumer: Consumer - ) where Consumer.Consumed == Self - { - if let end = consumer.consumingBack(self) { - removeSubrange(end...) - } - } - - @_disfavoredOverload - mutating func _trim( - _ consumer: Consumer - ) where Consumer.Consumed == Self { - _trimSuffix(consumer) - _trimPrefix(consumer) - } -} - // MARK: Predicate algorithms extension Collection { @@ -136,53 +78,6 @@ extension RangeReplaceableCollection { } } -extension BidirectionalCollection { - func _trimmingSuffix( - while predicate: @escaping (Element) -> Bool - ) -> SubSequence { - _trimmingSuffix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) - } - - func _trimming( - while predicate: @escaping (Element) -> Bool - ) -> SubSequence { - _trimming(ManyConsumer(base: PredicateConsumer(predicate: predicate))) - } -} - -extension BidirectionalCollection where SubSequence == Self { - mutating func _trimSuffix( - while predicate: @escaping (Element) -> Bool - ) { - _trimSuffix(ManyConsumer( - base: PredicateConsumer(predicate: predicate))) - } - - mutating func _trim(while predicate: @escaping (Element) -> Bool) { - let consumer = ManyConsumer( - base: PredicateConsumer(predicate: predicate)) - _trimPrefix(consumer) - _trimSuffix(consumer) - } -} - -extension RangeReplaceableCollection where Self: BidirectionalCollection { - @_disfavoredOverload - mutating func _trimSuffix( - while predicate: @escaping (Element) -> Bool - ) { - _trimSuffix(ManyConsumer(base: PredicateConsumer(predicate: predicate))) - } - - @_disfavoredOverload - mutating func _trim(while predicate: @escaping (Element) -> Bool) { - let consumer = ManyConsumer( - base: PredicateConsumer(predicate: predicate)) - _trimPrefix(consumer) - _trimSuffix(consumer) - } -} - // MARK: Fixed pattern algorithms extension Collection where Element: Equatable { @@ -229,58 +124,6 @@ extension RangeReplaceableCollection where Element: Equatable { } } -extension BidirectionalCollection where Element: Equatable { - func _trimmingSuffix( - _ suffix: Suffix - ) -> SubSequence where Suffix.Element == Element { - _trimmingSuffix(FixedPatternConsumer(pattern: suffix)) - } - - func _trimming( - _ pattern: Pattern - ) -> SubSequence where Pattern.Element == Element { - _trimming(FixedPatternConsumer(pattern: pattern)) - } -} - -extension BidirectionalCollection - where SubSequence == Self, Element: Equatable -{ - mutating func _trimSuffix( - _ suffix: Suffix - ) where Suffix.Element == Element { - _trimSuffix(FixedPatternConsumer(pattern: suffix)) - } - - mutating func _trim( - _ pattern: Pattern - ) where Pattern.Element == Element { - let consumer = FixedPatternConsumer(pattern: pattern) - _trimPrefix(consumer) - _trimSuffix(consumer) - } -} - -extension RangeReplaceableCollection - where Self: BidirectionalCollection, Element: Equatable -{ - @_disfavoredOverload - mutating func _trimSuffix( - _ prefix: Suffix - ) where Suffix.Element == Element { - _trimSuffix(FixedPatternConsumer(pattern: prefix)) - } - - @_disfavoredOverload - mutating func _trim( - _ pattern: Pattern - ) where Pattern.Element == Element { - let consumer = FixedPatternConsumer(pattern: pattern) - _trimPrefix(consumer) - _trimSuffix(consumer) - } -} - // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { @@ -292,17 +135,11 @@ extension BidirectionalCollection where SubSequence == Substring { @_disfavoredOverload @available(SwiftStdlib 5.7, *) public func trimmingPrefix(_ regex: some RegexComponent) -> SubSequence { - _trimmingPrefix(RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - func _trimmingSuffix(_ regex: R) -> SubSequence { - _trimmingSuffix(RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - func _trimming(_ regex: R) -> SubSequence { - _trimming(RegexConsumer(regex)) + let s = self[...] + guard let prefix = try? regex.regex.prefixMatch(in: s) else { + return s + } + return s[prefix.range.upperBound...] } } @@ -314,37 +151,11 @@ extension RangeReplaceableCollection @_disfavoredOverload @available(SwiftStdlib 5.7, *) public mutating func trimPrefix(_ regex: some RegexComponent) { - _trimPrefix(RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - mutating func _trimSuffix(_ regex: R) { - _trimSuffix(RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - mutating func _trim(_ regex: R) { - let consumer = RegexConsumer(regex) - _trimPrefix(consumer) - _trimSuffix(consumer) + let s = self[...] + guard let prefix = try? regex.regex.prefixMatch(in: s) else { + return + } + self.removeSubrange(prefix.range) } } -extension Substring { - @available(SwiftStdlib 5.7, *) - mutating func _trimPrefix(_ regex: R) { - _trimPrefix(RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - mutating func _trimSuffix(_ regex: R) { - _trimSuffix(RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - mutating func _trim(_ regex: R) { - let consumer = RegexConsumer(regex) - _trimPrefix(consumer) - _trimSuffix(consumer) - } -} diff --git a/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift b/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift deleted file mode 100644 index 4956406da..000000000 --- a/Sources/_StringProcessing/Algorithms/Consumers/RegexConsumer.swift +++ /dev/null @@ -1,98 +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 -// -//===----------------------------------------------------------------------===// - -// FIXME: What even is this? Can we delete this whole thing? -@available(SwiftStdlib 5.7, *) -struct RegexConsumer< - R: RegexComponent, Consumed: BidirectionalCollection -> where Consumed.SubSequence == Substring { - // TODO: Should `Regex` itself implement these protocols? - let regex: R - - init(_ regex: R) { - self.regex = regex - } -} - -@available(SwiftStdlib 5.7, *) -extension RegexConsumer { - func _matchingConsuming( - _ consumed: Substring, in range: Range - ) -> (upperBound: String.Index, match: Match)? { - guard let result = try! regex.regex._match( - consumed.base, - in: range, mode: .partialFromFront - ) else { return nil } - return (result.range.upperBound, result.output) - } -} - -// TODO: Explicitly implement the non-matching consumer/searcher protocols as -// well, taking advantage of the fact that the captures can be ignored - -@available(SwiftStdlib 5.7, *) -extension RegexConsumer: MatchingCollectionConsumer { - typealias Match = R.RegexOutput - - func matchingConsuming( - _ consumed: Consumed, in range: Range - ) -> (upperBound: String.Index, match: Match)? { - _matchingConsuming(consumed[...], in: range) - } -} - -// TODO: We'll want to bake backwards into the engine -@available(SwiftStdlib 5.7, *) -extension RegexConsumer: BidirectionalMatchingCollectionConsumer { - func matchingConsumingBack( - _ consumed: Consumed, in range: Range - ) -> (lowerBound: String.Index, match: Match)? { - var i = range.lowerBound - while true { - if let (end, capture) = _matchingConsuming( - consumed[...], - in: i.. - ) -> (range: Range, match: Match)? { - ConsumerSearcher(consumer: self).matchingSearch(searched, in: range) - } -} - -// TODO: Bake in search-back to engine too -@available(SwiftStdlib 5.7, *) -extension RegexConsumer: BackwardMatchingStatelessCollectionSearcher { - typealias BackwardSearched = Consumed - - func matchingSearchBack( - _ searched: BackwardSearched, in range: Range - ) -> (range: Range, match: Match)? { - ConsumerSearcher(consumer: self).matchingSearchBack(searched, in: range) - } -} diff --git a/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift b/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift index c8c6867f4..3ee74f258 100644 --- a/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift +++ b/Sources/_StringProcessing/Algorithms/Matching/FirstMatch.swift @@ -38,21 +38,6 @@ extension BidirectionalCollection { // MARK: Regex algorithms extension BidirectionalCollection where SubSequence == Substring { - @available(SwiftStdlib 5.7, *) - @_disfavoredOverload - func firstMatch( - of regex: R - ) -> _MatchResult>? { - _firstMatch(of: RegexConsumer(regex)) - } - - @available(SwiftStdlib 5.7, *) - func lastMatch( - of regex: R - ) -> _BackwardMatchResult>? { - lastMatch(of: RegexConsumer(regex)) - } - /// Returns the first match of the specified regex within the collection. /// - Parameter regex: The regex to search for. /// - Returns: The first match of `regex` in the collection, or `nil` if diff --git a/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift b/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift index 6bc9b4d77..0f23280ce 100644 --- a/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift +++ b/Sources/_StringProcessing/Algorithms/Matching/MatchReplace.swift @@ -75,45 +75,6 @@ extension RangeReplaceableCollection { // MARK: Regex algorithms extension RangeReplaceableCollection where SubSequence == Substring { - @available(SwiftStdlib 5.7, *) - func _replacing( - _ regex: R, - with replacement: (_MatchResult>) throws -> Replacement, - subrange: Range, - maxReplacements: Int = .max - ) rethrows -> Self where Replacement.Element == Element { - try _replacing( - RegexConsumer(regex), - with: replacement, - subrange: subrange, - maxReplacements: maxReplacements) - } - - @available(SwiftStdlib 5.7, *) - func _replacing( - _ regex: R, - with replacement: (_MatchResult>) throws -> Replacement, - maxReplacements: Int = .max - ) rethrows -> Self where Replacement.Element == Element { - try _replacing( - regex, - with: replacement, - subrange: startIndex..( - _ regex: R, - with replacement: (_MatchResult>) throws -> Replacement, - maxReplacements: Int = .max - ) rethrows where Replacement.Element == Element { - self = try _replacing( - regex, - with: replacement, - maxReplacements: maxReplacements) - } - /// Returns a new collection in which all occurrences of a sequence matching /// the given regex are replaced by another regex match. /// - Parameters: diff --git a/Sources/_StringProcessing/Algorithms/Matching/Matches.swift b/Sources/_StringProcessing/Algorithms/Matching/Matches.swift index f5c645105..12846bf0f 100644 --- a/Sources/_StringProcessing/Algorithms/Matching/Matches.swift +++ b/Sources/_StringProcessing/Algorithms/Matching/Matches.swift @@ -357,13 +357,6 @@ extension BidirectionalCollection where SubSequence == Substring { regex: regex.regex) } - @available(SwiftStdlib 5.7, *) - func _matchesFromBack( - of regex: R - ) -> ReversedMatchesCollection> { - _matchesFromBack(of: RegexConsumer(regex)) - } - // FIXME: Return `some Collection.Match> for SE-0346 /// Returns a collection containing all matches of the specified regex. /// - Parameter regex: The regex to search for. diff --git a/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift b/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift index 837493a30..c3537d415 100644 --- a/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift +++ b/Sources/_StringProcessing/Algorithms/Searchers/TwoWaySearcher.swift @@ -9,6 +9,14 @@ // //===----------------------------------------------------------------------===// +extension BidirectionalCollection where Element: Equatable { + fileprivate func _ends(with suffix: C) -> Bool + where C.Element == Element + { + FixedPatternConsumer(pattern: suffix).consumingBack(self[...]) != nil + } + } + struct TwoWaySearcher where Searched.Element: Comparable { diff --git a/Tests/RegexTests/AlgorithmsInternalsTests.swift b/Tests/RegexTests/AlgorithmsInternalsTests.swift index 96cd12076..af0007bbe 100644 --- a/Tests/RegexTests/AlgorithmsInternalsTests.swift +++ b/Tests/RegexTests/AlgorithmsInternalsTests.swift @@ -24,25 +24,17 @@ extension AlgorithmTests { 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).. Bool) -> SubSequence { + var i = endIndex + while i > startIndex { + formIndex(before: &i) + if !predicate(self[i]) { return self[...i] } + } + return self[.. Date: Wed, 14 Dec 2022 13:37:48 -0600 Subject: [PATCH 6/7] Improve StringProcessing and RegexBuilder documentation (#611) This includes documentation improvements for core types/methods, RegexBuilder types along with their generated variadic initializers, and adds some curation. It also includes tests of the documentation code samples. --- .gitignore | 3 + Package.swift | 8 + Sources/RegexBuilder/Anchor.swift | 4 +- Sources/RegexBuilder/Builder.swift | 9 + Sources/RegexBuilder/CharacterClass.swift | 102 +- Sources/RegexBuilder/DSL.swift | 249 +- Sources/RegexBuilder/Variadics.swift | 2431 +++++++++++++++++ .../VariadicsGenerator.swift | 194 ++ .../Documentation.docc/Extensions/Regex.md | 41 + .../Regex/AnyRegexOutput.swift | 186 +- Sources/_StringProcessing/Regex/Core.swift | 63 +- Sources/_StringProcessing/Regex/Match.swift | 222 +- Sources/_StringProcessing/Regex/Options.swift | 23 +- .../RegexBuilderTests.swift | 202 ++ Tests/DocumentationTests/RegexTests.swift | 149 + 15 files changed, 3777 insertions(+), 109 deletions(-) create mode 100644 Sources/_StringProcessing/Documentation.docc/Extensions/Regex.md create mode 100644 Tests/DocumentationTests/RegexBuilderTests.swift create mode 100644 Tests/DocumentationTests/RegexTests.swift diff --git a/.gitignore b/.gitignore index ff85b9fa3..fabf56f96 100644 --- a/.gitignore +++ b/.gitignore @@ -93,3 +93,6 @@ fastlane/test_output # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ + +# DocC build folder +*.docc-build diff --git a/Package.swift b/Package.swift index 18764fcaf..baeea543f 100644 --- a/Package.swift +++ b/Package.swift @@ -89,6 +89,14 @@ let package = Package( swiftSettings: [ .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) ]), + .testTarget( + name: "DocumentationTests", + dependencies: ["_StringProcessing", "RegexBuilder"], + swiftSettings: [ + .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]), + .unsafeFlags(["-enable-bare-slash-regex"]), + ]), + // FIXME: Disabled due to rdar://94763190. // .testTarget( // name: "Prototypes", diff --git a/Sources/RegexBuilder/Anchor.swift b/Sources/RegexBuilder/Anchor.swift index 8283b9cbd..86be6ce0b 100644 --- a/Sources/RegexBuilder/Anchor.swift +++ b/Sources/RegexBuilder/Anchor.swift @@ -147,7 +147,7 @@ extension Anchor { /// /// Word boundaries are identified using the Unicode default word boundary /// algorithm by default. To specify a different word boundary algorithm, - /// see the `RegexComponent.wordBoundaryKind(_:)` method. + /// use the `wordBoundaryKind(_:)` method. /// /// This anchor is equivalent to `\b` in regex syntax. public static var wordBoundary: Anchor { @@ -157,7 +157,7 @@ extension Anchor { /// The inverse of this anchor, which matches at every position that this /// anchor does not. /// - /// For the `wordBoundary` and `textSegmentBoundary` anchors, the inverted + /// For the ``wordBoundary`` and ``textSegmentBoundary`` anchors, the inverted /// version corresponds to `\B` and `\Y`, respectively. public var inverted: Anchor { var result = self diff --git a/Sources/RegexBuilder/Builder.swift b/Sources/RegexBuilder/Builder.swift index 7afe254c2..4b754c231 100644 --- a/Sources/RegexBuilder/Builder.swift +++ b/Sources/RegexBuilder/Builder.swift @@ -11,6 +11,15 @@ @_spi(RegexBuilder) import _StringProcessing +/// A custom parameter attribute that constructs regular expressions from +/// closures. +/// +/// You typically see `RegexComponentBuilder` as a parameter attribute for +/// `Regex`- or `RegexComponent`-producing closure parameters, allowing those +/// closures to combine multiple regular expression components. Type +/// initializers and string algorithm methods in the RegexBuilder framework +/// include a builder closure parameter, so that you can use regular expression +/// components together. @available(SwiftStdlib 5.7, *) @resultBuilder public enum RegexComponentBuilder { diff --git a/Sources/RegexBuilder/CharacterClass.swift b/Sources/RegexBuilder/CharacterClass.swift index 08c7d347e..cab0ab29b 100644 --- a/Sources/RegexBuilder/CharacterClass.swift +++ b/Sources/RegexBuilder/CharacterClass.swift @@ -12,6 +12,11 @@ @_implementationOnly import _RegexParser @_spi(RegexBuilder) import _StringProcessing +/// A class of characters that match in a regex. +/// +/// A character class can represent individual characters, a group of +/// characters, the set of character that match some set of criteria, or +/// a set algebraic combination of all of the above. @available(SwiftStdlib 5.7, *) public struct CharacterClass { internal var ccc: DSLTree.CustomCharacterClass @@ -42,6 +47,20 @@ extension CharacterClass: RegexComponent { @available(SwiftStdlib 5.7, *) extension CharacterClass { + /// A character class that matches any character that does not match this + /// character class. + /// + /// For example, you can use the `inverted` property to create a character + /// class that excludes a specific group of characters: + /// + /// let validCharacters = CharacterClass("a"..."z", .anyOf("-_")) + /// let invalidCharacters = validCharacters.inverted + /// + /// let username = "user123" + /// if username.contains(invalidCharacters) { + /// print("Invalid username: '\(username)'") + /// } + /// // Prints "Invalid username: 'user123'" public var inverted: CharacterClass { if let inv = builtin?.inverted { return CharacterClass(builtin: inv) @@ -53,26 +72,50 @@ extension CharacterClass { @available(SwiftStdlib 5.7, *) extension RegexComponent where Self == CharacterClass { + /// A character class that matches any element. + /// + /// This character class is unaffected by the `dotMatchesNewlines()` method. + /// To match any character that isn't a newline, see + /// ``anyNonNewline``. + /// + /// This character class is equivalent to the regex syntax "dot" + /// metacharacter in single-line mode: `(?s:.)`. public static var any: CharacterClass { .init(DSLTree.CustomCharacterClass(members: [.atom(.any)])) } + /// A character class that matches any element that isn't a newline. + /// + /// This character class is unaffected by the `dotMatchesNewlines()` method. + /// To match any character, including newlines, see ``any``. + /// + /// This character class is equivalent to the regex syntax "dot" + /// metacharacter with single-line mode disabled: `(?-s:.)`. public static var anyNonNewline: CharacterClass { .init(DSLTree.CustomCharacterClass(members: [.atom(.anyNonNewline)])) } + /// A character class that matches any single `Character`, or extended + /// grapheme cluster, regardless of the current semantic level. + /// + /// This character class is equivalent to `\X` in regex syntax. public static var anyGraphemeCluster: CharacterClass { .init(builtin: .anyGrapheme) } - public static var whitespace: CharacterClass { - .init(builtin: .whitespace) - } - + /// A character class that matches any digit. + /// + /// This character class is equivalent to `\d` in regex syntax. public static var digit: CharacterClass { .init(builtin: .digit) } + /// A character class that matches any hexadecimal digit. + /// + /// `hexDigit` matches the ASCII characters `0` through `9`, and upper- or + /// lowercase `a` through `f`. The corresponding characters in the "Halfwidth + /// and Fullwidth Forms" Unicode block are not matched by this character + /// class. public static var hexDigit: CharacterClass { .init(DSLTree.CustomCharacterClass(members: [ .range(.char("A"), .char("F")), @@ -81,27 +124,56 @@ extension RegexComponent where Self == CharacterClass { ])) } + /// A character class that matches any element that is a "word character". + /// + /// This character class is equivalent to `\w` in regex syntax. + public static var word: CharacterClass { + .init(builtin: .word) + } + + /// A character class that matches any element that is classified as + /// whitespace. + /// + /// This character class is equivalent to `\s` in regex syntax. + public static var whitespace: CharacterClass { + .init(builtin: .whitespace) + } + + /// A character class that matches any element that is classified as + /// horizontal whitespace. + /// + /// This character class is equivalent to `\h` in regex syntax. public static var horizontalWhitespace: CharacterClass { .init(builtin: .horizontalWhitespace) } + /// A character class that matches any newline sequence. + /// + /// This character class is equivalent to `\R` or `\n` in regex syntax. public static var newlineSequence: CharacterClass { .init(builtin: .newlineSequence) } + /// A character class that matches any element that is classified as + /// vertical whitespace. + /// + /// This character class is equivalent to `\v` in regex syntax. public static var verticalWhitespace: CharacterClass { .init(builtin: .verticalWhitespace) } - - public static var word: CharacterClass { - .init(builtin: .word) - } } @available(SwiftStdlib 5.7, *) extension RegexComponent where Self == CharacterClass { /// Returns a character class that matches any character in the given string /// or sequence. + /// + /// Calling this method with a group of characters is equivalent to listing + /// those characters in a custom character class in regex syntax. For example, + /// the two regexes in this example are equivalent: + /// + /// let regex1 = /[abcd]+/ + /// let regex2 = OneOrMore(.anyOf("abcd")) public static func anyOf(_ s: S) -> CharacterClass where S.Element == Character { @@ -111,6 +183,9 @@ extension RegexComponent where Self == CharacterClass { /// Returns a character class that matches any Unicode scalar in the given /// sequence. + /// + /// Calling this method with a group of Unicode scalars is equivalent to + /// listing them in a custom character class in regex syntax. public static func anyOf(_ s: S) -> CharacterClass where S.Element == UnicodeScalar { @@ -122,6 +197,11 @@ extension RegexComponent where Self == CharacterClass { // Unicode properties @available(SwiftStdlib 5.7, *) extension CharacterClass { + /// Returns a character class that matches any element with the given Unicode + /// general category. + /// + /// For example, when passed `.uppercaseLetter`, this method is equivalent to + /// `/\p{Uppercase_Letter}/` or `/\p{Lu}/`. public static func generalCategory(_ category: Unicode.GeneralCategory) -> CharacterClass { return CharacterClass(.generalCategory(category)) } @@ -148,6 +228,7 @@ public func ...(lhs: UnicodeScalar, rhs: UnicodeScalar) -> CharacterClass { @available(SwiftStdlib 5.7, *) extension RegexComponent where Self == CharacterClass { + /// Creates a character class that combines the given classes in a union. public init(_ first: CharacterClass, _ rest: CharacterClass...) { if rest.isEmpty { self.init(first.ccc) @@ -161,24 +242,29 @@ extension RegexComponent where Self == CharacterClass { @available(SwiftStdlib 5.7, *) extension CharacterClass { + /// Returns a character class from the union of this class and the given class. public func union(_ other: CharacterClass) -> CharacterClass { CharacterClass(.init(members: [ .custom(self.ccc), .custom(other.ccc)])) } + /// Returns a character class from the intersection of this class and the given class. public func intersection(_ other: CharacterClass) -> CharacterClass { CharacterClass(.init(members: [ .intersection(self.ccc, other.ccc) ])) } + /// Returns a character class by subtracting the given class from this class. public func subtracting(_ other: CharacterClass) -> CharacterClass { CharacterClass(.init(members: [ .subtraction(self.ccc, other.ccc) ])) } + /// Returns a character class matching elements in one or the other, but not both, + /// of this class and the given class. public func symmetricDifference(_ other: CharacterClass) -> CharacterClass { CharacterClass(.init(members: [ .symmetricDifference(self.ccc, other.ccc) diff --git a/Sources/RegexBuilder/DSL.swift b/Sources/RegexBuilder/DSL.swift index e758999ef..152aadd0c 100644 --- a/Sources/RegexBuilder/DSL.swift +++ b/Sources/RegexBuilder/DSL.swift @@ -14,6 +14,7 @@ @available(SwiftStdlib 5.7, *) extension Regex { + /// Creates a regular expression using a RegexBuilder closure. public init( @RegexComponentBuilder _ content: () -> Content ) where Content.RegexOutput == Output { @@ -89,6 +90,7 @@ extension UnicodeScalar: RegexComponent { public struct One: RegexComponent { public var regex: Regex + /// Creates a regex component that matches the given component exactly once. public init( _ component: Component ) where Component.RegexOutput == Output { @@ -96,6 +98,8 @@ public struct One: RegexComponent { } } +/// A regex component that matches one or more occurrences of its underlying +/// component. @available(SwiftStdlib 5.7, *) public struct OneOrMore: _BuiltinRegexComponent { public var regex: Regex @@ -109,6 +113,8 @@ public struct OneOrMore: _BuiltinRegexComponent { // Variadics.swift. } +/// A regex component that matches zero or more occurrences of its underlying +/// component. @available(SwiftStdlib 5.7, *) public struct ZeroOrMore: _BuiltinRegexComponent { public var regex: Regex @@ -122,6 +128,8 @@ public struct ZeroOrMore: _BuiltinRegexComponent { // Variadics.swift. } +/// A regex component that matches zero or one occurrences of its underlying +/// component. @available(SwiftStdlib 5.7, *) public struct Optionally: _BuiltinRegexComponent { public var regex: Regex @@ -135,6 +143,8 @@ public struct Optionally: _BuiltinRegexComponent { // Variadics.swift. } +/// A regex component that matches a selectable number of occurrences of its +/// underlying component. @available(SwiftStdlib 5.7, *) public struct Repeat: _BuiltinRegexComponent { public var regex: Regex @@ -162,6 +172,12 @@ public struct Repeat: _BuiltinRegexComponent { // ) -> R where R.Match == (W, C...) // } +/// A custom parameter attribute that constructs regular expression alternations +/// from closures. +/// +/// When you use a `ChoiceOf` initializer, the initializer's +/// closure parameter has an `AlternationBuilder` attribute, allowing you +/// to provide multiple regular expression statements as alternatives. @available(SwiftStdlib 5.7, *) @resultBuilder public struct AlternationBuilder { @@ -177,6 +193,22 @@ public struct AlternationBuilder { } } +/// A regex component that chooses exactly one of its constituent regex +/// components when matching. +/// +/// You can use `ChoiceOf` to provide a group of regex components, each of +/// which can be exclusively matched. In this example, `regex` successfully +/// matches either a `"CREDIT"` or `"DEBIT"` substring: +/// +/// let regex = Regex { +/// ChoiceOf { +/// "CREDIT" +/// "DEBIT" +/// } +/// } +/// let match = try regex.prefixMatch(in: "DEBIT 04032020 Payroll $69.73") +/// print(match?.0 as Any) +/// // Prints "DEBIT" @available(SwiftStdlib 5.7, *) public struct ChoiceOf: _BuiltinRegexComponent { public var regex: Regex @@ -186,6 +218,24 @@ public struct ChoiceOf: _BuiltinRegexComponent { self.regex = regex } + /// Creates a regex component that chooses exactly one of the regex components + /// provided by the builder closure. + /// + /// In this example, `regex` successfully matches either a `"CREDIT"` or + /// `"DEBIT"` substring: + /// + /// let regex = Regex { + /// ChoiceOf { + /// "CREDIT" + /// "DEBIT" + /// } + /// } + /// let match = try regex.prefixMatch(in: "DEBIT 04032020 Payroll $69.73") + /// print(match?.0 as Any) + /// // Prints "DEBIT" + /// + /// - Parameter builder: A builder closure that declares a list of regex + /// components, each of which can be exclusively matched. public init(@AlternationBuilder _ builder: () -> Self) { self = builder() } @@ -193,6 +243,71 @@ public struct ChoiceOf: _BuiltinRegexComponent { // MARK: - Capture +/// A regex component that saves the matched substring, or a transformed result, +/// for access in a regex match. +/// +/// Use a `Capture` component to capture one part of a regex to access +/// separately after matching. In the example below, `regex` matches a dollar +/// sign (`"$"`) followed by one or more digits, a period (`"."`), and then two +/// additional digits, as long as that pattern appears at the end of the line. +/// Because the `Capture` block wraps the digits and period, that part of the +/// match is captured separately. +/// +/// let transactions = """ +/// CREDIT 109912311421 Payroll $69.73 +/// CREDIT 105912031123 Travel $121.54 +/// DEBIT 107733291022 Refund $8.42 +/// """ +/// +/// let regex = Regex { +/// "$" +/// Capture { +/// OneOrMore(.digit) +/// "." +/// Repeat(.digit, count: 2) +/// } +/// Anchor.endOfLine +/// } +/// +/// // The type of each match's output is `(Substring, Substring)`. +/// for match in transactions.matches(of: regex) { +/// print("Transaction amount: \(match.1)") +/// } +/// // Prints "Transaction amount: 69.73" +/// // Prints "Transaction amount: 121.54" +/// // Prints "Transaction amount: 8.42" +/// +/// Each `Capture` block increases the number of components in the regex's +/// output type. In the example above, the capture type of each match is +/// `(Substring, Substring)`. +/// +/// By providing a transform function to the `Capture` block, you can change the +/// type of the captured value from `Substring` to the result of the transform. +/// This example declares `doubleValueRegex`, which converts the captured amount +/// to a `Double`: +/// +/// let doubleValueRegex = Regex { +/// "$" +/// Capture { +/// OneOrMore(.digit) +/// "." +/// Repeat(.digit, count: 2) +/// } transform: { Double($0)! } +/// Anchor.endOfLine +/// } +/// +/// // The type of each match's output is `(Substring, Double)`. +/// for match in transactions.matches(of: doubleValueRegex) { +/// if match.1 >= 100.0 { +/// print("Large amount: \(match.1)") +/// } +/// } +/// // Prints "Large amount: 121.54" +/// +/// Throwing an error from a `transform` closure aborts matching and propagates +/// the error out to the caller. If you instead want to use a failable +/// transformation, where a `nil` result participates in matching, use +/// ``TryCapture`` instead of `Capture`. @available(SwiftStdlib 5.7, *) public struct Capture: _BuiltinRegexComponent { public var regex: Regex @@ -205,6 +320,61 @@ public struct Capture: _BuiltinRegexComponent { // Note: Public initializers are currently gyb'd. See Variadics.swift. } +/// A regex component that attempts to transform a matched substring, saving +/// the result if successful and backtracking if the transformation fails. +/// +/// You use a `TryCapture` component to capture part of a match as a +/// transformed value, when a failure to transform should mean the regex +/// continues matching, backtracking from that point if necessary. +/// +/// The code below demonstrates using `TryCapture` to include a test that the +/// `Double` value of a capture is over a limit. In the example, `regex` +/// matches a dollar sign (`"$"`) followed by one or more digits, a period +/// (`"."`), and then two additional digits, as long as that pattern appears at +/// the end of the line. The `TryCapture` block wraps the digits and period, +/// capturing that part of the match separately and passing it to its +/// `transform` closure. That closure converts the captured portion of the +/// match, converts it to a `Double`, and only returns a non-`nil` value if it +/// is over the transaction limit. +/// +/// let transactions = """ +/// CREDIT 109912311421 Payroll $69.73 +/// CREDIT 105912031123 Travel $121.54 +/// DEBIT 107733291022 Refund $8.42 +/// """ +/// let transactionLimit = 100.0 +/// +/// let regex = Regex { +/// "$" +/// TryCapture { +/// OneOrMore(.digit) +/// "." +/// Repeat(.digit, count: 2) +/// } transform: { str -> Double? in +/// let value = Double(str)! +/// if value > transactionLimit { +/// return value +/// } +/// return nil +/// } +/// Anchor.endOfLine +/// } +/// +/// When the `TryCapture` block's `transform` closure processes the three +/// different amounts in the list of transactions, it only returns a non-`nil` +/// value for the $121.54 transaction. Even though the capture returns an +/// optional `Double` value, the captured value is non-optional. +/// +/// // The type of each match's output is `(Substring, Double)`. +/// for match in transactions.matches(of: regex) { +/// print("Transaction amount: \(match.1)") +/// } +/// // Prints "Transaction amount: 121.54" +/// +/// Throwing an error from a `transform` closure aborts matching and propagates +/// the error out to the caller. If you want to capture the `nil` results of a +/// failable transformation, instead of continuing a search, use ``Capture`` +/// instead of `TryCapture`. @available(SwiftStdlib 5.7, *) public struct TryCapture: _BuiltinRegexComponent { public var regex: Regex @@ -219,10 +389,10 @@ public struct TryCapture: _BuiltinRegexComponent { // MARK: - Groups -/// An atomic group. +/// A regex component that represents an atomic group. /// -/// This group opens a local backtracking scope which, upon successful exit, -/// discards any remaining backtracking points from within the scope. +/// An atomic 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 @@ -235,11 +405,81 @@ public struct Local: _BuiltinRegexComponent { // MARK: - Backreference +/// A reference to a captured portion of a regular expression. +/// +/// You can use a `Reference` to access a regular expression, both during +/// the matching process and after a capture has been successful. +/// +/// In this example, the `kind` reference captures either `"CREDIT"` or +/// `"DEBIT"` at the beginning of a line. Later in the regular expression, the +/// presence of `kind` matches the same substring that was captured previously +/// at the end of the line. +/// +/// let kindRef = Reference(Substring.self) +/// let kindRegex = ChoiceOf { +/// "CREDIT" +/// "DEBIT" +/// } +/// +/// let transactionRegex = Regex { +/// Anchor.startOfLine +/// Capture(kindRegex, as: kindRef) +/// OneOrMore(.anyNonNewline) +/// kindRef +/// Anchor.endOfLine +/// } +/// +/// let validTransaction = "CREDIT 109912311421 Payroll $69.73 CREDIT" +/// let invalidTransaction = "DEBIT 00522142123 Expense $5.17 CREDIT" +/// +/// print(validTransaction.contains(transactionRegex)) +/// // Prints "true" +/// print(invalidTransaction.contains(transactionRegex)) +/// // Prints "false" +/// +/// Any reference that is used for matching must be captured elsewhere in the +/// `Regex` block. You can use a reference for matching before it is captured; +/// in that case, the reference will not match until it has previously been +/// captured. +/// +/// To access the captured "transaction kind", you can use the `kind` reference +/// to subscript a `Regex.Match` instance: +/// +/// if let match = validTransaction.firstMatch(of: transactionRegex) { +/// print(match[kindRef]) +/// } +/// // Prints "CREDIT" +/// +/// To use a `Reference` to capture a transformed value, include a `transform` +/// closure when capturing. +/// +/// struct Transaction { +/// var id: UInt64 +/// } +/// let transactionRef = Reference(Transaction.self) +/// +/// let transactionIDRegex = Regex { +/// Capture(kindRegex, as: kindRef) +/// OneOrMore(.whitespace) +/// TryCapture(as: transactionRef) { +/// OneOrMore(.digit) +/// } transform: { str in +/// UInt64(str).map(Transaction.init(id:)) +/// } +/// OneOrMore(.anyNonNewline) +/// kindRef +/// Anchor.endOfLine +/// } +/// +/// if let match = validTransaction.firstMatch(of: transactionIDRegex) { +/// print(match[transactionRef]) +/// } +/// // Prints "Transaction(id: 109912311421)" @available(SwiftStdlib 5.7, *) -/// A backreference. public struct Reference: RegexComponent { let id = ReferenceID() + /// Creates a reference with the specified capture type. public init(_ captureType: Capture.Type = Capture.self) {} @usableFromInline @@ -254,6 +494,7 @@ public struct Reference: RegexComponent { @available(SwiftStdlib 5.7, *) extension Regex.Match { + /// Accesses this match's capture by the given reference. public subscript(_ reference: Reference) -> Capture { self[reference.id] } diff --git a/Sources/RegexBuilder/Variadics.swift b/Sources/RegexBuilder/Variadics.swift index 7336f0a30..0f19cd6b0 100644 --- a/Sources/RegexBuilder/Variadics.swift +++ b/Sources/RegexBuilder/Variadics.swift @@ -688,6 +688,16 @@ extension RegexComponentBuilder { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -701,6 +711,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -724,6 +745,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -737,6 +768,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -751,6 +793,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -764,6 +816,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -778,6 +841,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -789,6 +859,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -800,6 +878,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -811,6 +901,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( @@ -824,6 +927,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -836,6 +949,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -858,6 +982,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -870,6 +1004,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -883,6 +1028,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -895,6 +1050,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -908,6 +1074,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -918,6 +1091,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -928,6 +1109,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -938,6 +1131,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -950,6 +1156,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -962,6 +1178,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -984,6 +1211,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -996,6 +1233,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1009,6 +1257,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1021,6 +1279,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1034,6 +1303,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1044,6 +1320,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1054,6 +1338,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1064,6 +1360,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1076,6 +1385,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1088,6 +1407,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1110,6 +1440,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1122,6 +1462,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1135,6 +1486,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1147,6 +1508,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1160,6 +1532,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1170,6 +1549,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1180,6 +1567,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1190,6 +1589,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1202,6 +1614,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1214,6 +1636,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1236,6 +1669,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1248,6 +1691,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1261,6 +1715,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1273,6 +1737,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1286,6 +1761,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1296,6 +1778,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1306,6 +1796,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1316,6 +1818,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1328,6 +1843,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1340,6 +1865,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1362,6 +1898,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1374,6 +1920,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1387,6 +1944,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1399,6 +1966,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1412,6 +1990,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1422,6 +2007,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1432,6 +2025,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1442,6 +2047,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1454,6 +2072,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1466,6 +2094,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1488,6 +2127,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1500,6 +2149,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1513,6 +2173,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1525,6 +2195,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1538,6 +2219,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1548,6 +2236,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1558,6 +2254,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1568,6 +2276,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1580,6 +2301,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1592,6 +2323,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1614,6 +2356,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1626,6 +2378,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1639,6 +2402,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1651,6 +2424,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1664,6 +2448,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1674,6 +2465,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1684,6 +2483,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1694,6 +2505,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1706,6 +2530,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1718,6 +2552,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1740,6 +2585,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1752,6 +2607,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1765,6 +2631,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1777,6 +2653,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1790,6 +2677,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1800,6 +2694,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1810,6 +2712,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1820,6 +2734,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1832,6 +2759,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1844,6 +2781,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1866,6 +2814,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1878,6 +2836,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1891,6 +2860,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1903,6 +2882,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1916,6 +2906,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1926,6 +2923,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -1936,6 +2941,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1946,6 +2963,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -1958,6 +2988,16 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -1970,6 +3010,17 @@ extension Optionally { @available(SwiftStdlib 5.7, *) extension Optionally { + /// Creates a regex component that matches the given component + /// zero or one times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -1992,6 +3043,16 @@ extension RegexComponentBuilder { } @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -2004,6 +3065,17 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension ZeroOrMore { + /// Creates a regex component that matches the given component + /// zero or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -2017,6 +3089,16 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -2029,6 +3111,17 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension OneOrMore { + /// Creates a regex component that matches the given component + /// one or more times. + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. @_alwaysEmitIntoClient public init( _ behavior: RegexRepetitionBehavior? = nil, @@ -2042,6 +3135,13 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. @_alwaysEmitIntoClient public init( _ component: Component, @@ -2052,6 +3152,14 @@ extension Repeat { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. @_alwaysEmitIntoClient public init( count: Int, @@ -2062,6 +3170,18 @@ extension Repeat { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. @_alwaysEmitIntoClient public init( _ component: Component, @@ -2072,6 +3192,19 @@ extension Repeat { self.init(factory.repeating(expression.relative(to: 0..( _ expression: R, @@ -2084,6 +3217,10 @@ extension Repeat { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_disfavoredOverload @_alwaysEmitIntoClient @@ -2097,6 +3234,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_disfavoredOverload @_alwaysEmitIntoClient @@ -2109,6 +3250,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2121,6 +3266,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2132,6 +3281,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2144,6 +3297,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2155,6 +3312,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2167,6 +3328,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2178,6 +3343,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2190,6 +3359,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2201,6 +3374,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2213,6 +3390,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2224,6 +3405,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2236,6 +3421,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2247,6 +3436,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2259,6 +3452,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2270,6 +3467,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2282,6 +3483,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2293,6 +3498,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2305,6 +3514,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2316,6 +3529,10 @@ extension Local { } @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -2328,6 +3545,10 @@ extension Local { @available(SwiftStdlib 5.7, *) extension Local { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. @available(SwiftStdlib 5.7, *) @_alwaysEmitIntoClient public init( @@ -3071,6 +4292,9 @@ extension AlternationBuilder { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3080,6 +4304,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3089,6 +4320,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3099,6 +4339,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3113,6 +4364,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3123,6 +4384,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3139,6 +4412,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3148,6 +4425,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3158,6 +4443,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3168,6 +4463,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3182,6 +4489,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3192,6 +4510,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_disfavoredOverload @_alwaysEmitIntoClient public init( @@ -3208,6 +4539,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3216,6 +4550,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3224,6 +4565,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3233,6 +4583,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3246,6 +4607,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3255,6 +4626,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3270,6 +4653,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -3278,6 +4665,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3287,6 +4682,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3296,6 +4701,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3309,6 +4726,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3318,6 +4746,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3333,6 +4774,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3341,6 +4785,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3349,6 +4800,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3358,6 +4818,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3371,6 +4842,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3380,6 +4861,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3395,6 +4888,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -3403,6 +4900,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3412,6 +4917,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3421,6 +4936,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3434,6 +4961,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3443,6 +4981,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3458,6 +5009,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3466,6 +5020,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3474,6 +5035,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3483,6 +5053,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3496,6 +5077,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3505,6 +5096,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3520,6 +5123,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -3528,6 +5135,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3537,6 +5152,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3546,6 +5171,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3559,6 +5196,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3568,6 +5216,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3583,6 +5244,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3591,6 +5255,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3599,6 +5270,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3608,6 +5288,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3621,6 +5312,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3630,6 +5331,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3645,6 +5358,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -3653,6 +5370,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3662,6 +5387,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3671,6 +5406,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3684,6 +5431,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3693,6 +5451,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3708,6 +5479,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3716,6 +5490,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3724,6 +5505,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3733,6 +5523,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3746,6 +5547,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3755,6 +5566,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3770,6 +5593,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -3778,6 +5605,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3787,6 +5622,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3796,6 +5641,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3809,6 +5666,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3818,6 +5686,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3833,6 +5714,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3841,6 +5725,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3849,6 +5740,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3858,6 +5758,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3871,6 +5782,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3880,6 +5801,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3895,6 +5828,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -3903,6 +5840,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3912,6 +5857,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3921,6 +5876,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3934,6 +5901,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -3943,6 +5921,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -3958,6 +5949,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -3966,6 +5960,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -3974,6 +5975,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3983,6 +5993,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -3996,6 +6017,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4005,6 +6036,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4020,6 +6063,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -4028,6 +6075,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4037,6 +6092,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4046,6 +6111,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4059,6 +6136,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4068,6 +6156,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4083,6 +6184,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -4091,6 +6195,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -4099,6 +6210,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4108,6 +6228,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4121,6 +6252,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4130,6 +6271,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4145,6 +6298,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -4153,6 +6310,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4162,6 +6327,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4171,6 +6346,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4184,6 +6371,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4193,6 +6391,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4208,6 +6419,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -4216,6 +6430,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -4224,6 +6445,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4233,6 +6463,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4246,6 +6487,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4255,6 +6506,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4270,6 +6533,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -4278,6 +6545,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4287,6 +6562,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4296,6 +6581,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4309,6 +6606,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4318,6 +6626,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4333,6 +6654,9 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. @_alwaysEmitIntoClient public init( _ component: R @@ -4341,6 +6665,13 @@ extension Capture { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. @_alwaysEmitIntoClient public init( _ component: R, as reference: Reference @@ -4349,6 +6680,15 @@ extension Capture { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4358,6 +6698,17 @@ extension Capture { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4371,6 +6722,16 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4380,6 +6741,18 @@ extension TryCapture { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( _ component: R, @@ -4395,6 +6768,10 @@ extension TryCapture { @available(SwiftStdlib 5.7, *) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R @@ -4403,6 +6780,14 @@ extension Capture { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4412,6 +6797,16 @@ extension Capture { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4421,6 +6816,18 @@ extension Capture { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, @@ -4434,6 +6841,17 @@ extension Capture { @available(SwiftStdlib 5.7, *) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( @RegexComponentBuilder _ componentBuilder: () -> R, @@ -4443,6 +6861,19 @@ extension TryCapture { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. @_alwaysEmitIntoClient public init( as reference: Reference, diff --git a/Sources/VariadicsGenerator/VariadicsGenerator.swift b/Sources/VariadicsGenerator/VariadicsGenerator.swift index 8ddaee145..180bfb168 100644 --- a/Sources/VariadicsGenerator/VariadicsGenerator.swift +++ b/Sources/VariadicsGenerator/VariadicsGenerator.swift @@ -335,6 +335,23 @@ struct VariadicsGenerator: ParsableCommand { case .oneOrMore: return "oneOrMore" } } + + var commentAbstract: String { + switch self { + case .zeroOrOne: return """ + /// Creates a regex component that matches the given component + /// zero or one times. + """ + case .zeroOrMore: return """ + /// Creates a regex component that matches the given component + /// zero or more times. + """ + case .oneOrMore: return """ + /// Creates a regex component that matches the given component + /// one or more times. + """ + } + } } struct QuantifierParameters { @@ -389,6 +406,15 @@ struct VariadicsGenerator: ParsableCommand { output(""" \(defaultAvailableAttr) extension \(kind.rawValue) { + \(kind.commentAbstract) + /// + /// - Parameters: + /// - component: The regex component. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. \(params.disfavored)\ @_alwaysEmitIntoClient public init<\(params.genericParams)>( @@ -402,6 +428,16 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension \(kind.rawValue) { + \(kind.commentAbstract) + /// + /// - Parameters: + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. + /// - componentBuilder: A builder closure that generates a regex + /// component. \(params.disfavored)\ @_alwaysEmitIntoClient public init<\(params.genericParams)>( @@ -461,6 +497,10 @@ struct VariadicsGenerator: ParsableCommand { output(""" \(defaultAvailableAttr) extension \(groupName) { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter component: The regex component to wrap in an atomic + /// group. \(defaultAvailableAttr) \(disfavored)\ @_alwaysEmitIntoClient @@ -474,6 +514,10 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension \(groupName) { + /// Creates an atomic group with the given regex component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to wrap in an atomic group. \(defaultAvailableAttr) \(disfavored)\ @_alwaysEmitIntoClient @@ -499,6 +543,13 @@ struct VariadicsGenerator: ParsableCommand { output(""" \(defaultAvailableAttr) extension Repeat { + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. \(params.disfavored)\ @_alwaysEmitIntoClient public init<\(params.genericParams)>( @@ -510,6 +561,14 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.exactly(count, component)) } + /// Creates a regex component that matches the given component repeated + /// the specified number of times. + /// + /// - Parameters: + /// - count: The number of times to repeat `component`. `count` must + /// be greater than or equal to zero. + /// - componentBuilder: A builder closure that creates the regex + /// component to repeat. \(params.disfavored)\ @_alwaysEmitIntoClient public init<\(params.genericParams)>( @@ -521,6 +580,18 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.exactly(count, componentBuilder())) } + /// Creates a regex component that matches the given component repeated + /// a number of times specified by the given range expression. + /// + /// - Parameters: + /// - component: The regex component to repeat. + /// - expression: A range expression specifying the number of times + /// that `component` can repeat. + /// - behavior: The repetition behavior to use when repeating + /// `component` in the match. If `behavior` is `nil`, the default + /// repetition behavior is used, which can be changed from + /// `eager` by calling `repetitionBehavior(_:)` on the resulting + /// `Regex`. \(params.disfavored)\ @_alwaysEmitIntoClient public init<\(params.genericParams), R: RangeExpression>( @@ -532,6 +603,19 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.repeating(expression.relative(to: 0..( @@ -649,6 +733,9 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter component: The regex component to capture. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams)>( @@ -658,6 +745,13 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.capture(component)) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams)>( @@ -667,6 +761,15 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.capture(component, reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -677,6 +780,17 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.capture(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -691,6 +805,16 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -701,6 +825,18 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.captureOptional(component, nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - component: The regex component to capture. + /// - reference: The reference to use for anything captured by + /// `component`. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -717,6 +853,10 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension Capture { + /// Creates a capture for the given component. + /// + /// - Parameter componentBuilder: A builder closure that generates a + /// regex component to capture. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams)>( @@ -726,6 +866,14 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.capture(componentBuilder())) } + /// Creates a capture for the given component using the specified + /// reference. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams)>( @@ -736,6 +884,16 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.capture(componentBuilder(), reference._raw)) } + /// Creates a capture for the given component, transforming with the + /// given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -746,6 +904,18 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.capture(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, transforming with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -760,6 +930,17 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) extension TryCapture { + /// Creates a capture for the given component, attempting to transform + /// with the given closure. + /// + /// - Parameters: + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( @@ -770,6 +951,19 @@ struct VariadicsGenerator: ParsableCommand { self.init(factory.captureOptional(componentBuilder(), nil, transform)) } + /// Creates a capture for the given component using the specified + /// reference, attempting to transform with the given closure. + /// + /// - Parameters: + /// - reference: The reference to use for anything captured by + /// `component`. + /// - componentBuilder: A builder closure that generates a regex + /// component to capture. + /// - transform: A closure that takes the substring matched by + /// `component` and returns a new value to capture, or `nil` if + /// matching should proceed, backtracking if allowed. If `transform` + /// throws an error, matching is abandoned and the error is returned + /// to the caller. \(disfavored)\ @_alwaysEmitIntoClient public init<\(genericParams), NewCapture>( diff --git a/Sources/_StringProcessing/Documentation.docc/Extensions/Regex.md b/Sources/_StringProcessing/Documentation.docc/Extensions/Regex.md new file mode 100644 index 000000000..69852efb9 --- /dev/null +++ b/Sources/_StringProcessing/Documentation.docc/Extensions/Regex.md @@ -0,0 +1,41 @@ +# ``_StringProcessing/Regex`` + +## Topics + +### Creating a Regex + +- ``init(_:)-52kg`` +- ``init(_:as:)-5z5nu`` +- ``init(verbatim:)`` + +### Converting Different Outputs + +- ``init(_:)-92siq`` +- ``init(_:as:)-2ucu7`` + +### Searching in Strings + +- ``firstMatch(in:)-6s8x0`` +- ``firstMatch(in:)-45hz7`` +- ``prefixMatch(in:)-5oh8i`` +- ``prefixMatch(in:)-1an24`` +- ``wholeMatch(in:)-9do8t`` +- ``wholeMatch(in:)-8hr88`` + +### Inspecting a Regex + +- ``regex`` +- ``contains(captureNamed:)`` + +### Setting Options + +- ``ignoresCase(_:)`` +- ``dotMatchesNewlines(_:)`` +- ``anchorsMatchLineEndings(_:)`` +- ``repetitionBehavior(_:)`` +- ``matchingSemantics(_:)`` +- ``wordBoundaryKind(_:)`` +- ``asciiOnlyDigits(_:)`` +- ``asciiOnlyWhitespace(_:)`` +- ``asciiOnlyWordCharacters(_:)`` +- ``asciiOnlyCharacterClasses(_:)`` diff --git a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift index 0cf27af6b..fd292ed1b 100644 --- a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift +++ b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift @@ -11,7 +11,10 @@ @_implementationOnly import _RegexParser -/// A type-erased regex output. +/// The type-erased, dynamic output of a regular expression match. +/// +/// When you find a match using regular expression that has `AnyRegexOutput` +/// as its output type, you can find information about matches by iterating @available(SwiftStdlib 5.7, *) public struct AnyRegexOutput { internal let input: String @@ -20,21 +23,22 @@ public struct AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension AnyRegexOutput { - /// Creates a type-erased regex output from an existing match. + /// Creates a dynamic regular expression match output from an existing match. /// - /// Use this initializer to fit a strongly-typed regex match into the - /// use site of a type-erased regex output. + /// You can use this initializer when you need an `AnyRegexOutput` instance + /// instead of the output type of a strongly-typed `Regex.Match`. public init(_ match: Regex.Match) { self = match.anyRegexOutput } - /// Returns a strongly-typed output by converting type-erased values to the specified type. + /// Returns strongly-typed match output by converting this type-erased + /// output to the specified type, if possible. /// - /// - Parameter type: The expected output type. - /// - Returns: The output, if the underlying value can be converted to the - /// output type; otherwise `nil`. + /// - Parameter outputType: The expected output type. + /// - Returns: The output, if the underlying value can be converted to + /// `outputType`; otherwise, `nil`. public func extractValues( - as type: Output.Type = Output.self + as outputType: Output.Type = Output.self ) -> Output? { let elements = map { $0.existentialOutputComponent(from: input) @@ -45,31 +49,40 @@ extension AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension AnyRegexOutput: RandomAccessCollection { - /// An individual type-erased output value. + /// An individual match output value. public struct Element { internal let representation: ElementRepresentation internal let input: String - /// The range over which a value was captured. `nil` for no-capture. + /// The range over which a value was captured, if there was a capture. + /// + /// If nothing was captured, `range` is `nil`. public var range: Range? { representation.content?.range } - /// The slice of the input over which a value was captured. `nil` for no-capture. + /// The slice of the input which was captured, if there was a capture. + /// + /// If nothing was captured, `substring` is `nil`. public var substring: Substring? { range.map { input[$0] } } - /// The captured value, `nil` for no-capture. + /// The captured value, if there was a capture. + /// + /// If nothing was captured, `value` is `nil`. public var value: Any? { representation.value(forInput: input) } + /// The type of this capture. public var type: Any.Type { representation.type } - /// The name of this capture, if it has one, otherwise `nil`. + /// The name of this capture, if the capture is named. + /// + /// If the capture is unnamed, `name` is `nil`. public var name: String? { representation.name } @@ -110,7 +123,12 @@ extension AnyRegexOutput: RandomAccessCollection { @available(SwiftStdlib 5.7, *) extension AnyRegexOutput { - /// Access a capture by name. Returns `nil` if no capture with that name was present in the Regex. + /// Accesses the capture with the specified name, if a capture with that name + /// exists. + /// + /// - Parameter name: The name of the capture to access. + /// - Returns: An element providing information about the capture, if there is + /// a capture named `name`; otherwise, `nil`. public subscript(name: String) -> Element? { first { $0.name == name @@ -122,12 +140,17 @@ extension AnyRegexOutput { extension Regex.Match where Output == AnyRegexOutput { /// Accesses the whole match using the `.0` syntax. public subscript( - dynamicMember keyPath: KeyPath<(Substring, _doNotUse: ()), Substring> + dynamicMember _keyPath: KeyPath<(Substring, _doNotUse: ()), Substring> ) -> Substring { anyRegexOutput.input[range] } - /// Access a capture by name. Returns `nil` if there's no capture with that name. + /// Accesses the capture with the specified name, if a capture with that name + /// exists. + /// + /// - Parameter name: The name of the capture to access. + /// - Returns: An element providing information about the capture, if there is + /// a capture named `name`; otherwise, `nil`. public subscript(name: String) -> AnyRegexOutput.Element? { anyRegexOutput.first { $0.name == name @@ -139,9 +162,22 @@ extension Regex.Match where Output == AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension Regex where Output == AnyRegexOutput { - /// Parses and compiles a regular expression, resulting in a type-erased capture list. + /// Creates a regular expression from the given string, using a dynamic + /// capture list. + /// + /// Use this initializer to create a `Regex` instance from a regular + /// expression that you have stored in `pattern`. + /// + /// let simpleDigits = try Regex("[0-9]+") + /// + /// This initializer throws an error if `pattern` uses invalid regular + /// expression syntax. + /// + /// The output type of the new `Regex` is the dynamic ``AnyRegexOutput``. + /// If you know the capture structure of `pattern` ahead of time, use the + /// ``init(_:as:)`` initializer instead. /// - /// - Parameter pattern: The regular expression. + /// - Parameter pattern: A string with regular expression syntax. public init(_ pattern: String) throws { self.init(ast: try parse(pattern, .traditional)) } @@ -153,13 +189,32 @@ extension Regex where Output == AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension Regex { - /// Parses and compiles a regular expression. + /// Creates a regular expression from the given string, using the specified + /// capture type. /// - /// - Parameter pattern: The regular expression. - /// - Parameter as: The desired type for the output. + /// You can use this initializer to create a `Regex` instance from a regular + /// expression that you have stored in `pattern` when you know the capture + /// structure of the regular expression in advance. + /// + /// In this example, the regular expression includes two parenthesized + /// capture groups, so the capture type is `(Substring, Substring, Substring)`. + /// The first substring in the tuple represents the entire match, while the + /// second and third substrings represent the first and second capture group, + /// respectively. + /// + /// let keyAndValue = try Regex("(.+): (.+)", as: (Substring, Substring, Substring).self) + /// + /// This initializer throws an error if `pattern` uses invalid regular + /// expression syntax, or if `outputType` does not match the capture + /// structure declared by `pattern`. If you don't know the capture structure + /// in advance, use the ``init(_:)`` initializer instead. + /// + /// - Parameters: + /// - pattern: A string with regular expression syntax. + /// - outputType: The desired type for the output captures. public init( _ pattern: String, - as: Output.Type = Output.self + as outputType: Output.Type = Output.self ) throws { let regex = Regex(ast: try parse(pattern, .traditional)) @@ -175,13 +230,40 @@ extension Regex { self = regex } - /// Produces a regex that matches `verbatim` exactly, as though every - /// metacharacter in it was escaped. - public init(verbatim: String) { - self.init(node: .quotedLiteral(verbatim)) + /// Creates a regular expression that matches the given string exactly, as + /// though every metacharacter in it was escaped. + /// + /// This example creates a regular expression that matches the string + /// `"(adj)"`, including the parentheses. Although parentheses are regular + /// expression metacharacters, they do not need escaping in the string passed + /// as `verbatimString`. + /// + /// let adjectiveDesignator = Regex(verbatim: "(adj.)") + /// + /// print("awesome (adj.)".contains(adjectiveDesignator)) + /// // Prints "true" + /// print("apple (n.)".contains(adjectiveDesignator)) + /// // Prints "false" + /// + /// - Parameter verbatimString: A string to convert into a regular expression + /// exactly, escaping any metacharacters. + public init(verbatim verbatimString: String) { + self.init(node: .quotedLiteral(verbatimString)) } - /// Returns whether a named-capture with `name` exists + /// Returns a Boolean value indicating whether a named capture with the given + /// name exists. + /// + /// This example shows a regular expression that includes capture groups + /// named `key` and `value`: + /// + /// let regex = try Regex("(?'key'.+?): (?'value'.+)") + /// regex.contains(captureNamed: "key") // true + /// regex.contains(captureNamed: "VALUE") // false + /// regex.contains(captureNamed: "1") // false + /// + /// - Parameter name: The name to look for among the regular expression's + /// capture groups. Capture group names are case sensitive. public func contains(captureNamed name: String) -> Bool { program.tree.captureList.captures.contains(where: { $0.name == name @@ -193,10 +275,14 @@ extension Regex { @available(SwiftStdlib 5.7, *) extension Regex where Output == AnyRegexOutput { - /// Creates a type-erased regex from an existing regex. + /// Creates a regular expression with a dynamic capture list from the given + /// regular expression. /// - /// Use this initializer to fit a regex with strongly-typed captures into the - /// use site of a type-erased regex, i.e. one that was created from a string. + /// You can use this initializer to convert a `Regex` with strongly-typed + /// captures into a `Regex` with `AnyRegexOutput` as its output type. + /// + /// - Parameter regex: A regular expression to convert to use a dynamic + /// capture list. public init(_ regex: Regex) { self.init(node: regex.root) } @@ -204,10 +290,15 @@ extension Regex where Output == AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension Regex.Match where Output == AnyRegexOutput { - /// Creates a type-erased regex match from an existing match. + /// Creates a regular expression match with a dynamic capture list from the + /// given match. + /// + /// You can use this initializer to convert a `Regex.Match` with + /// strongly-typed captures into a match with the type-eraser `AnyRegexOutput` + /// as its output type. /// - /// Use this initializer to fit a regex match with strongly-typed captures into the - /// use site of a type-erased regex match. + /// - Parameter match: A regular expression match to convert to a match with + /// type-erased captures. public init(_ match: Regex.Match) { self.init( anyRegexOutput: match.anyRegexOutput, @@ -218,16 +309,29 @@ extension Regex.Match where Output == AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension Regex { - /// Creates a strongly-typed regex from a type-erased regex. + /// Creates a regular expression with a strongly-typed capture list from the + /// given regular expression. + /// + /// You can use this initializer to convert a regular expression with a + /// dynamic capture list to one with a strongly-typed capture list. If the + /// type you provide as `outputType` doesn't match the capture structure of + /// `regex`, the initializer returns `nil`. /// - /// Use this initializer to create a strongly-typed regex from - /// one that was created from a string. Returns `nil` if the types - /// don't match. + /// let dynamicRegex = try Regex("(.+?): (.+)") + /// if let stronglyTypedRegex = Regex(dynamicRegex, as: (Substring, Substring, Substring).self) { + /// print("Converted properly") + /// } + /// // Prints "Converted properly" + /// + /// - Parameters: + /// - regex: A regular expression to convert to use a strongly-typed capture + /// list. + /// - outputType: The capture structure to use. public init?( - _ erased: Regex, - as: Output.Type = Output.self + _ regex: Regex, + as outputType: Output.Type = Output.self ) { - self.init(node: erased.root) + self.init(node: regex.root) guard _verifyType().0 else { return nil diff --git a/Sources/_StringProcessing/Regex/Core.swift b/Sources/_StringProcessing/Regex/Core.swift index ba40f4f90..5940fd500 100644 --- a/Sources/_StringProcessing/Regex/Core.swift +++ b/Sources/_StringProcessing/Regex/Core.swift @@ -12,19 +12,70 @@ @_implementationOnly import _RegexParser /// A type that represents a regular expression. +/// +/// You can use types that conform to `RegexComponent` as parameters to string +/// searching operations and inside `RegexBuilder` closures. @available(SwiftStdlib 5.7, *) public protocol RegexComponent { + /// The output type for this regular expression. + /// + /// A `Regex` instance's output type depends on whether the `Regex` has + /// captures and how it is created. + /// + /// - A `Regex` created from a string using the ``init(_:)`` initializer + /// has an output type of ``AnyRegexOutput``, whether it has captures or + /// not. + /// - A `Regex` without captures created from a regex literal, the + /// ``init(_:as:)`` initializer, or a `RegexBuilder` closure has a + /// `Substring` output type, where the substring is the portion of the + /// string that was matched. + /// - A `Regex` with captures created from a regex literal or the + /// ``init(_:as:)`` initializer has a tuple of substrings as its output + /// type. The first component of the tuple is the full portion of the string + /// that was matched, with the remaining components holding the captures. associatedtype RegexOutput + + /// The regular expression represented by this component. var regex: Regex { get } } /// A regular expression. /// -/// let regex = try Regex("a(.*)b") -/// let match = "cbaxb".firstMatch(of: regex) -/// print(match.0) // "axb" -/// print(match.1) // "x" +/// Regular expressions are a concise way of describing a pattern, which can +/// help you match or extract portions of a string. You can create a `Regex` +/// instance using regular expression syntax, either in a regex literal or a +/// string. +/// +/// // 'keyAndValue' is created using a regex literal +/// let keyAndValue = /(.+?): (.+)/ +/// // 'simpleDigits' is created from a pattern in a string +/// let simpleDigits = try Regex("[0-9]+") +/// +/// You can use a `Regex` to search for a pattern in a string or substring. +/// Call `contains(_:)` to check for the presence of a pattern, or +/// `firstMatch(of:)` or `matches(of:)` to find matches. +/// +/// let setting = "color: 161 103 230" +/// if setting.contains(simpleDigits) { +/// print("'\(setting)' contains some digits.") +/// } +/// // Prints "'color: 161 103 230' contains some digits." +/// +/// When you find a match, the resulting ``Match`` type includes an +/// ``Match/output`` property that contains the matched substring along with +/// any captures: +/// +/// if let match = setting.firstMatch(of: keyAndValue) { +/// print("Key: \(match.1)") +/// print("Value: \(match.2)") +/// } +/// // Key: color +/// // Value: 161 103 230 /// +/// When you import the `RegexBuilder` module, you can also create `Regex` +/// instances using a clear and flexible declarative syntax. Using this +/// style, you can combine, capture, and transform regexes, `RegexBuilder` +/// types, and custom parsers. @available(SwiftStdlib 5.7, *) public struct Regex: RegexComponent { let program: Program @@ -64,8 +115,8 @@ public struct Regex: RegexComponent { @available(SwiftStdlib 5.7, *) extension Regex { @available(*, deprecated, renamed: "init(verbatim:)") - public init(quoting string: String) { - self.init(node: .quotedLiteral(string)) + public init(quoting _string: String) { + self.init(node: .quotedLiteral(_string)) } } diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 0fb4e0eb8..e5e899ced 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -11,7 +11,7 @@ @available(SwiftStdlib 5.7, *) extension Regex { - /// The result of matching a regex against a string. + /// The result of matching a regular expression against a string. /// /// A `Match` forwards API to the `Output` generic parameter, /// providing direct access to captures. @@ -56,11 +56,12 @@ extension Regex.Match { /// Accesses a capture using the `.0` syntax, even when the match isn't a tuple. @_disfavoredOverload public subscript( - dynamicMember keyPath: KeyPath<(Output, _doNotUse: ()), Output> + dynamicMember _keyPath: KeyPath<(Output, _doNotUse: ()), Output> ) -> Output { output } + // Helper for `subscript(_: Reference)`, defined in RegexBuilder. @_spi(RegexBuilder) public subscript(_ id: ReferenceID) -> Capture { guard let element = anyRegexOutput.first( @@ -76,52 +77,187 @@ extension Regex.Match { @available(SwiftStdlib 5.7, *) extension Regex { - /// Matches a string in its entirety. + /// Returns a match if this regex matches the given string in its entirety. /// - /// - 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(string, in: string.startIndex.. Regex.Match? { - try _match(s, in: s.startIndex.. Regex.Match? { + try _match(string, in: string.startIndex.. Regex.Match? { - try _firstMatch(s, in: s.startIndex.. Regex.Match? { + try _firstMatch(string, in: string.startIndex.. Regex.Match? { - try _match(s.base, in: s.startIndex.. Regex.Match? { + try _match(string.base, in: string.startIndex.. Regex.Match? { - try _match(s.base, in: s.startIndex.. Regex.Match? { + try _match(string.base, in: string.startIndex.. Regex.Match? { - try _firstMatch(s.base, in: s.startIndex.. Regex.Match? { + try _firstMatch(string.base, in: string.startIndex..( - of r: R + of regex: R ) -> Regex.Match? { - try? r.regex.wholeMatch(in: self[...]) + try? regex.regex.wholeMatch(in: self[...]) } - /// Checks for a match against the string, starting at its beginning. + /// Returns a match if this string is matched by the given regex at its start. /// - /// - Parameter r: The regular expression being matched. - /// - Returns: The match, or `nil` if no match was found. + /// - Parameter regex: The regular expression to match. + /// - Returns: The match, if one is found. If there is no match, or a + /// transformation in `regex` throws an error, this method returns `nil`. public func prefixMatch( - of r: R + of regex: R ) -> Regex.Match? { - try? r.regex.prefixMatch(in: self[...]) + try? regex.regex.prefixMatch(in: self[...]) } } diff --git a/Sources/_StringProcessing/Regex/Options.swift b/Sources/_StringProcessing/Regex/Options.swift index 368a5b634..1e58e78d5 100644 --- a/Sources/_StringProcessing/Regex/Options.swift +++ b/Sources/_StringProcessing/Regex/Options.swift @@ -83,8 +83,8 @@ extension Regex { /// /// This method corresponds to applying the `m` option in regex syntax. For /// this behavior in the `RegexBuilder` syntax, see - /// ``Anchor.startOfLine``, ``Anchor.endOfLine``, ``Anchor.startOfSubject``, - /// and ``Anchor.endOfSubject``. + /// `Anchor.startOfLine`, `Anchor.endOfLine`, `Anchor.startOfSubject`, + /// and `Anchor.endOfSubject`. /// /// - Parameter matchLineEndings: A Boolean value indicating whether `^` and /// `$` should match the start and end of lines, respectively. @@ -161,8 +161,13 @@ extension Regex { } } -@available(SwiftStdlib 5.7, *) /// A semantic level to use during regex matching. +/// +/// The semantic level determines whether a regex matches with the same +/// character-based semantics as string comparisons or by matching individual +/// Unicode scalar values. See ``Regex/matchingSemantics(_:)`` for more about +/// changing the semantic level for all or part of a regex. +@available(SwiftStdlib 5.7, *) public struct RegexSemanticLevel: Hashable { internal enum Representation { case graphemeCluster @@ -181,15 +186,18 @@ public struct RegexSemanticLevel: Hashable { /// 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. + /// 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) } } -@available(SwiftStdlib 5.7, *) /// A word boundary algorithm to use during regex matching. +/// +/// See ``Regex/wordBoundaryKind(_:)`` for information about specifying the +/// word boundary kind for all or part of a regex. +@available(SwiftStdlib 5.7, *) public struct RegexWordBoundaryKind: Hashable { internal enum Representation { case unicodeLevel1 @@ -221,6 +229,9 @@ public struct RegexWordBoundaryKind: Hashable { } /// Specifies how much to attempt to match when using a quantifier. +/// +/// See ``Regex/repetitionBehavior(_:)`` for more about specifying the default +/// matching behavior for all or part of a regex. @available(SwiftStdlib 5.7, *) public struct RegexRepetitionBehavior: Hashable { internal enum Kind { diff --git a/Tests/DocumentationTests/RegexBuilderTests.swift b/Tests/DocumentationTests/RegexBuilderTests.swift new file mode 100644 index 000000000..835f6e333 --- /dev/null +++ b/Tests/DocumentationTests/RegexBuilderTests.swift @@ -0,0 +1,202 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 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 +// +//===----------------------------------------------------------------------===// +// +// Tests for the code samples in the RegexBuilder documentation. +// +//===----------------------------------------------------------------------===// + +import XCTest +import _StringProcessing +import RegexBuilder + +class RegexBuilderTests: XCTestCase {} + +extension RegexBuilderTests { + func testCharacterClass_inverted() throws { + let validCharacters = CharacterClass("a"..."z", .anyOf("-_")) + let invalidCharacters = validCharacters.inverted + + let username = "user123" + if username.contains(invalidCharacters) { + print("Invalid username: '\(username)'") + } + // Prints "Invalid username: 'user123'" + + XCTAssertTrue(username.contains(invalidCharacters)) + } + + func testCharacterClass_anyOf() { + let regex1 = /[abcd]+/ + let regex2 = OneOrMore(.anyOf("abcd")) + + // syntax/compilation test + } + + func testChoiceOf() throws { + let regex = Regex { + ChoiceOf { + "CREDIT" + "DEBIT" + } + } + let match = try regex.prefixMatch(in: "DEBIT 04032020 Payroll $69.73") + print(match?.0 as Any) + // Prints "DEBIT" + + XCTAssertEqual(match?.0, "DEBIT") + } + + func testReference() throws { + let kindRef = Reference(Substring.self) + let kindRegex = ChoiceOf { + "CREDIT" + "DEBIT" + } + + let transactionRegex = Regex { + Anchor.startOfLine + Capture(kindRegex, as: kindRef) + OneOrMore(.anyNonNewline) + kindRef + Anchor.endOfLine + } + + let validTransaction = "CREDIT 109912311421 Payroll $69.73 CREDIT" + let invalidTransaction = "DEBIT 00522142123 Expense $5.17 CREDIT" + + print(validTransaction.contains(transactionRegex)) + // Prints "true" + print(invalidTransaction.contains(transactionRegex)) + // Prints "false" + + if let match = validTransaction.firstMatch(of: transactionRegex) { + print(match[kindRef]) + } + // Prints "CREDIT" + + struct Transaction: Equatable { + var id: UInt64 + } + let transactionRef = Reference(Transaction.self) + + let transactionIDRegex = Regex { + Capture(kindRegex, as: kindRef) + OneOrMore(.whitespace) + TryCapture(as: transactionRef) { + OneOrMore(.digit) + } transform: { str in + UInt64(str).map(Transaction.init(id:)) + } + OneOrMore(.anyNonNewline) + kindRef + Anchor.endOfLine + } + + if let match = validTransaction.firstMatch(of: transactionIDRegex) { + print(match[transactionRef]) + } + // Prints "Transaction(id: 109912311421)" + + XCTAssertTrue(validTransaction.contains(transactionRegex)) + XCTAssertFalse(invalidTransaction.contains(transactionRegex)) + + XCTAssertEqual(validTransaction.firstMatch(of: transactionRegex)?[kindRef], "CREDIT") + + XCTAssertEqual( + validTransaction.firstMatch(of: transactionIDRegex)?[transactionRef], + Transaction(id: 109912311421)) + } + + func testCapture() throws { + let transactions = """ + CREDIT 109912311421 Payroll $69.73 + CREDIT 105912031123 Travel $121.54 + DEBIT 107733291022 Refund $8.42 + """ + + let regex = Regex { + "$" + Capture { + OneOrMore(.digit) + "." + Repeat(.digit, count: 2) + } + Anchor.endOfLine + } + + // The type of each match's output is `(Substring, Substring)`. + for match in transactions.matches(of: regex) { + print("Transaction amount: \(match.1)") + } + // Prints "Transaction amount: 69.73" + // Prints "Transaction amount: 121.54" + // Prints "Transaction amount: 8.42" + + let doubleValueRegex = Regex { + "$" + Capture { + OneOrMore(.digit) + "." + Repeat(.digit, count: 2) + } transform: { Double($0)! } + Anchor.endOfLine + } + + // The type of each match's output is `(Substring, Double)`. + for match in transactions.matches(of: doubleValueRegex) { + if match.1 >= 100.0 { + print("Large amount: \(match.1)") + } + } + // Prints "Large amount: 121.54" + + let matchCaptures = transactions.matches(of: regex).map(\.1) + XCTAssertEqual(matchCaptures, ["69.73", "121.54", "8.42"]) + + let doubleValues = transactions.matches(of: doubleValueRegex).map(\.1) + XCTAssertEqual(doubleValues, [69.73, 121.54, 8.42]) + } + + func testTryCapture() throws { + let transactions = """ + CREDIT 109912311421 Payroll $69.73 + CREDIT 105912031123 Travel $121.54 + DEBIT 107733291022 Refund $8.42 + """ + let transactionLimit = 100.0 + + let regex = Regex { + "$" + TryCapture { + OneOrMore(.digit) + "." + Repeat(.digit, count: 2) + } transform: { str -> Double? in + let value = Double(str)! + if value > transactionLimit { + return value + } + return nil + } + Anchor.endOfLine + } + + // The type of each match's output is `(Substring, Double)`. + for match in transactions.matches(of: regex) { + print("Transaction amount: \(match.1)") + } + // Prints "Transaction amount: 121.54" + + let matches = transactions.matches(of: regex) + XCTAssertEqual(matches.count, 1) + XCTAssertEqual(matches[0].1, 121.54) + } +} diff --git a/Tests/DocumentationTests/RegexTests.swift b/Tests/DocumentationTests/RegexTests.swift new file mode 100644 index 000000000..ba3910245 --- /dev/null +++ b/Tests/DocumentationTests/RegexTests.swift @@ -0,0 +1,149 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 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 +// +//===----------------------------------------------------------------------===// +// +// Tests for the code samples in the Regex documentation. +// +//===----------------------------------------------------------------------===// + +import XCTest +import _StringProcessing + +class RegexTests: XCTestCase {} + +extension RegexTests { + func testRegex() throws { + // 'keyAndValue' is created using a regex literal + let keyAndValue = /(.+?): (.+)/ + // 'simpleDigits' is created from a pattern in a string + let simpleDigits = try Regex("[0-9]+") + + let setting = "color: 161 103 230" + if setting.contains(simpleDigits) { + print("'\(setting)' contains some digits.") + } + // Prints "'color: 161 103 230' contains some digits." + + if let match = setting.firstMatch(of: keyAndValue) { + print("Key: \(match.1)") + print("Value: \(match.2)") + } + // Key: color + // Value: 161 103 230 + + XCTAssertTrue(setting.contains(simpleDigits)) + + let match = try XCTUnwrap(setting.firstMatch(of: keyAndValue)) + XCTAssertEqual(match.1, "color") + XCTAssertEqual(match.2, "161 103 230") + } + + func testRegex_init() throws { + let simpleDigits = try Regex("[0-9]+") + + // shouldn't throw + } + + func testRegex_initStringAs() throws { + let keyAndValue = try Regex("(.+): (.+)", as: (Substring, Substring, Substring).self) + + // shouldn't throw + } + + func testRegex_initRegexAs() throws { + let dynamicRegex = try Regex("(.+?): (.+)") + if let stronglyTypedRegex = Regex(dynamicRegex, as: (Substring, Substring, Substring).self) { + print("Converted properly") + } + // Prints "Converted properly" + + XCTAssertNotNil(Regex(dynamicRegex, as: (Substring, Substring, Substring).self)) + } + + func testRegex_initVerbatim() throws { + let adjectiveDesignator = Regex(verbatim: "(adj.)") + + print("awesome (adj.)".contains(adjectiveDesignator)) + // Prints "true" + print("apple (n.)".contains(adjectiveDesignator)) + // Prints "false" + + XCTAssertTrue("awesome (adj.)".contains(adjectiveDesignator)) + XCTAssertFalse("apple (n.)".contains(adjectiveDesignator)) + } + + func testRegex_containsCapture() throws { + let regex = try Regex("(?'key'.+?): (?'value'.+)") + regex.contains(captureNamed: "key") // true + regex.contains(captureNamed: "VALUE") // false + regex.contains(captureNamed: "1") // false + + XCTAssertTrue(regex.contains(captureNamed: "key")) + XCTAssertFalse(regex.contains(captureNamed: "VALUE")) + XCTAssertFalse(regex.contains(captureNamed: "1")) + } +} + +extension RegexTests { + func testRegex_wholeMatchIn() throws { + let digits = /[0-9]+/ + + if let digitsMatch = try digits.wholeMatch(in: "2022") { + print(digitsMatch.0) + } else { + print("No match.") + } + // Prints "2022" + + if let digitsMatch = try digits.wholeMatch(in: "The year is 2022.") { + print(digitsMatch.0) + } else { + print("No match.") + } + // Prints "No match." + + XCTAssertEqual(try digits.wholeMatch(in: "2022")?.0, "2022") + XCTAssertNil(try digits.wholeMatch(in: "The year is 2022.")) + } + + func testRegex_prefixMatchIn() throws { + let titleCaseWord = /[A-Z][A-Za-z]+/ + + if let wordMatch = try titleCaseWord.prefixMatch(in: "Searching in a Regex") { + print(wordMatch.0) + } else { + print("No match.") + } + // Prints "Searching" + + if let wordMatch = try titleCaseWord.prefixMatch(in: "title case word at the End") { + print(wordMatch.0) + } else { + print("No match.") + } + // Prints "No match." + + XCTAssertEqual(try titleCaseWord.prefixMatch(in: "Searching in a Regex")?.0, "Searching") + XCTAssertNil(try titleCaseWord.prefixMatch(in: "title case word at the End")) + } + + func testRegex_firstMatchIn() throws { + let digits = /[0-9]+/ + + if let digitsMatch = try digits.firstMatch(in: "The year is 2022; last year was 2021.") { + print(digitsMatch.0) + } else { + print("No match.") + } + // Prints "2022" + + XCTAssertEqual(try digits.firstMatch(in: "The year is 2022; last year was 2021.")?.0, "2022") + } +} From c7662abfd7cb25198090114c7f23e899f4263d87 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 15 Dec 2022 23:52:37 -0600 Subject: [PATCH 7/7] Set availability for inverted character class test (#621) This feature depends on running with a Swift 5.7 stdlib, and fails when that isn't available. --- Package.swift | 2 +- Tests/DocumentationTests/RegexBuilderTests.swift | 5 +++++ Tests/DocumentationTests/RegexTests.swift | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index baeea543f..b30c402c4 100644 --- a/Package.swift +++ b/Package.swift @@ -93,7 +93,7 @@ let package = Package( name: "DocumentationTests", dependencies: ["_StringProcessing", "RegexBuilder"], swiftSettings: [ - .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]), + availabilityDefinition, .unsafeFlags(["-enable-bare-slash-regex"]), ]), diff --git a/Tests/DocumentationTests/RegexBuilderTests.swift b/Tests/DocumentationTests/RegexBuilderTests.swift index 835f6e333..d0ae36e01 100644 --- a/Tests/DocumentationTests/RegexBuilderTests.swift +++ b/Tests/DocumentationTests/RegexBuilderTests.swift @@ -19,8 +19,13 @@ import RegexBuilder class RegexBuilderTests: XCTestCase {} +@available(SwiftStdlib 5.7, *) extension RegexBuilderTests { func testCharacterClass_inverted() throws { + // `CharacterClass` depends on some standard library SPI that is only + // available in >= macOS 13. The warning for the next line is spurious. + guard #available(macOS 13, *) else { return } + let validCharacters = CharacterClass("a"..."z", .anyOf("-_")) let invalidCharacters = validCharacters.inverted diff --git a/Tests/DocumentationTests/RegexTests.swift b/Tests/DocumentationTests/RegexTests.swift index ba3910245..1394839c9 100644 --- a/Tests/DocumentationTests/RegexTests.swift +++ b/Tests/DocumentationTests/RegexTests.swift @@ -18,6 +18,7 @@ import _StringProcessing class RegexTests: XCTestCase {} +@available(SwiftStdlib 5.7, *) extension RegexTests { func testRegex() throws { // 'keyAndValue' is created using a regex literal @@ -91,6 +92,7 @@ extension RegexTests { } } +@available(SwiftStdlib 5.7, *) extension RegexTests { func testRegex_wholeMatchIn() throws { let digits = /[0-9]+/