From b8a1a81be5b0b8d7b63e3900ecb28a3731fffe33 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 21 Apr 2022 14:26:50 -0500 Subject: [PATCH 1/3] Adds RegexBuilder.CharacterClass.anyUnicodeScalar (#315) This provides a RegexBuilder API that represents the same as `\O` in regex syntax. --- Sources/RegexBuilder/CharacterClass.swift | 4 ++++ .../_StringProcessing/_CharacterClassModel.swift | 15 ++++++++++++++- Tests/RegexTests/MatchTests.swift | 12 +++++------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Sources/RegexBuilder/CharacterClass.swift b/Sources/RegexBuilder/CharacterClass.swift index d163c336b..8d0cde435 100644 --- a/Sources/RegexBuilder/CharacterClass.swift +++ b/Sources/RegexBuilder/CharacterClass.swift @@ -60,6 +60,10 @@ extension RegexComponent where Self == CharacterClass { public static var anyGrapheme: CharacterClass { .init(unconverted: .anyGrapheme) } + + public static var anyUnicodeScalar: CharacterClass { + .init(unconverted: .anyUnicodeScalar) + } public static var whitespace: CharacterClass { .init(unconverted: .whitespace) diff --git a/Sources/_StringProcessing/_CharacterClassModel.swift b/Sources/_StringProcessing/_CharacterClassModel.swift index c9762f00e..670a26c79 100644 --- a/Sources/_StringProcessing/_CharacterClassModel.swift +++ b/Sources/_StringProcessing/_CharacterClassModel.swift @@ -33,6 +33,8 @@ public struct _CharacterClassModel: Hashable { case any /// Any grapheme cluster case anyGrapheme + /// Any Unicode scalar + case anyScalar /// Character.isDigit case digit /// Character.isHexDigit @@ -155,8 +157,12 @@ public struct _CharacterClassModel: Hashable { case .graphemeCluster: let c = str[i] var matched: Bool + var next = str.index(after: i) switch cc { case .any, .anyGrapheme: matched = true + case .anyScalar: + matched = true + next = str.unicodeScalars.index(after: i) case .digit: matched = c.isNumber && (c.isASCII || !options.usesASCIIDigits) case .hexDigit: @@ -174,12 +180,13 @@ public struct _CharacterClassModel: Hashable { if isInverted { matched.toggle() } - return matched ? str.index(after: i) : nil + return matched ? next : nil case .unicodeScalar: let c = str.unicodeScalars[i] var matched: Bool switch cc { case .any: matched = true + case .anyScalar: matched = true case .anyGrapheme: fatalError("Not matched in this mode") case .digit: matched = c.properties.numericType != nil && (c.isASCII || !options.usesASCIIDigits) @@ -224,6 +231,10 @@ extension _CharacterClassModel { .init(cc: .anyGrapheme, matchLevel: .graphemeCluster) } + public static var anyUnicodeScalar: _CharacterClassModel { + .init(cc: .any, matchLevel: .unicodeScalar) + } + public static var whitespace: _CharacterClassModel { .init(cc: .whitespace, matchLevel: .graphemeCluster) } @@ -275,6 +286,7 @@ extension _CharacterClassModel.Representation: CustomStringConvertible { switch self { case .any: return "" case .anyGrapheme: return "" + case .anyScalar: return "" case .digit: return "" case .hexDigit: return "" case .horizontalWhitespace: return "" @@ -431,6 +443,7 @@ extension AST.Atom.EscapedBuiltin { case .notWordCharacter: return .word.inverted case .graphemeCluster: return .anyGrapheme + case .trueAnychar: return .anyUnicodeScalar default: return nil diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index b1287fc8b..5d5ab7394 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -1483,13 +1483,11 @@ extension RegexTests { (eDecomposed, false)) // FIXME: \O is unsupported - firstMatchTest(#"\O\u{301}"#, input: eDecomposed, match: eDecomposed, - xfail: true) - firstMatchTest(#"e\O"#, input: eDecomposed, match: eDecomposed, - xfail: true) - firstMatchTest(#"\O\u{301}"#, input: eComposed, match: nil, - xfail: true) - firstMatchTest(#"e\O"#, input: eComposed, match: nil, + firstMatchTest(#"(?u)\O\u{301}"#, input: eDecomposed, match: eDecomposed) + firstMatchTest(#"(?u)e\O"#, input: eDecomposed, match: eDecomposed, + xfail: true) + firstMatchTest(#"\O"#, input: eComposed, match: eComposed) + firstMatchTest(#"\O"#, input: eDecomposed, match: nil, xfail: true) matchTest( From 82fcf4a73c2442588b218af316638d77041fb7d6 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 21 Apr 2022 14:36:28 -0500 Subject: [PATCH 2/3] Allow setting any of the three quant behaviors (#311) This also moves QuantificationBehavior from the RegexBuilder module down to _StringProcessing, and renames it to RegexRepetitionBehavior. --- Sources/RegexBuilder/DSL.swift | 44 +-- Sources/RegexBuilder/Variadics.swift | 308 +++++++++--------- .../VariadicsGenerator.swift | 10 +- .../Regex/AST/MatchingOptions.swift | 4 + Sources/_StringProcessing/ByteCodeGen.swift | 4 +- .../_StringProcessing/MatchingOptions.swift | 34 +- Sources/_StringProcessing/Regex/Options.swift | 66 +++- Tests/RegexBuilderTests/RegexDSLTests.swift | 101 ++++-- 8 files changed, 332 insertions(+), 239 deletions(-) diff --git a/Sources/RegexBuilder/DSL.swift b/Sources/RegexBuilder/DSL.swift index 86ec0bee5..4020e2035 100644 --- a/Sources/RegexBuilder/DSL.swift +++ b/Sources/RegexBuilder/DSL.swift @@ -94,40 +94,20 @@ extension UnicodeScalar: RegexComponent { // Note: Quantifiers are currently gyb'd. -/// Specifies how much to attempt to match when using a quantifier. -@available(SwiftStdlib 5.7, *) -public struct QuantificationBehavior { - internal enum Kind { - case eagerly - case reluctantly - case possessively - } - - var kind: Kind - - internal var astKind: AST.Quantification.Kind { - switch kind { - case .eagerly: return .eager - case .reluctantly: return .reluctant - case .possessively: return .possessive - } - } -} - extension DSLTree.Node { /// Generates a DSLTree node for a repeated range of the given DSLTree node. /// Individual public API functions are in the generated Variadics.swift file. @available(SwiftStdlib 5.7, *) static func repeating( _ range: Range, - _ behavior: QuantificationBehavior?, + _ behavior: RegexRepetitionBehavior?, _ node: DSLTree.Node ) -> DSLTree.Node { // TODO: Throw these as errors assert(range.lowerBound >= 0, "Cannot specify a negative lower bound") assert(!range.isEmpty, "Cannot specify an empty range") - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default switch (range.lowerBound, range.upperBound) { case (0, Int.max): // 0... @@ -147,26 +127,6 @@ extension DSLTree.Node { } } -@available(SwiftStdlib 5.7, *) -extension QuantificationBehavior { - /// Match as much of the input string as possible, backtracking when - /// necessary. - public static var eagerly: QuantificationBehavior { - .init(kind: .eagerly) - } - - /// Match as little of the input string as possible, expanding the matched - /// region as necessary to complete a match. - public static var reluctantly: QuantificationBehavior { - .init(kind: .reluctantly) - } - - /// Match as much of the input string as possible, performing no backtracking. - public static var possessively: QuantificationBehavior { - .init(kind: .possessively) - } -} - @available(SwiftStdlib 5.7, *) public struct OneOrMore: _BuiltinRegexComponent { public var regex: Regex diff --git a/Sources/RegexBuilder/Variadics.swift b/Sources/RegexBuilder/Variadics.swift index 0f8d71a3f..eaa1530cc 100644 --- a/Sources/RegexBuilder/Variadics.swift +++ b/Sources/RegexBuilder/Variadics.swift @@ -616,9 +616,9 @@ extension Optionally { @_disfavoredOverload public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == Substring { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -628,10 +628,10 @@ extension Optionally { @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == Substring { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -651,9 +651,9 @@ extension ZeroOrMore { @_disfavoredOverload public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == Substring { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -663,10 +663,10 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == Substring { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -678,9 +678,9 @@ extension OneOrMore { @_disfavoredOverload public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == Substring { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -690,10 +690,10 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) @_disfavoredOverload public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == Substring { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -728,7 +728,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == Substring, R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == Substring, R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -759,10 +759,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -781,9 +781,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -792,10 +792,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -806,9 +806,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -817,10 +817,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0), Component.RegexOutput == (W, C0) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -852,7 +852,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?), Component.RegexOutput == (W, C0), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -882,10 +882,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -904,9 +904,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -915,10 +915,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -929,9 +929,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -940,10 +940,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1), Component.RegexOutput == (W, C0, C1) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -975,7 +975,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?), Component.RegexOutput == (W, C0, C1), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1005,10 +1005,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1027,9 +1027,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1038,10 +1038,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1052,9 +1052,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1063,10 +1063,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2), Component.RegexOutput == (W, C0, C1, C2) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1098,7 +1098,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?), Component.RegexOutput == (W, C0, C1, C2), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1128,10 +1128,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1150,9 +1150,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1161,10 +1161,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1175,9 +1175,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1186,10 +1186,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3), Component.RegexOutput == (W, C0, C1, C2, C3) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1221,7 +1221,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?), Component.RegexOutput == (W, C0, C1, C2, C3), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1251,10 +1251,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1273,9 +1273,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1284,10 +1284,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1298,9 +1298,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1309,10 +1309,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3, C4), Component.RegexOutput == (W, C0, C1, C2, C3, C4) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1344,7 +1344,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?), Component.RegexOutput == (W, C0, C1, C2, C3, C4), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1374,10 +1374,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1396,9 +1396,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1407,10 +1407,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1421,9 +1421,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1432,10 +1432,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1467,7 +1467,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1497,10 +1497,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1519,9 +1519,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1530,10 +1530,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1544,9 +1544,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1555,10 +1555,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1590,7 +1590,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1620,10 +1620,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1642,9 +1642,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1653,10 +1653,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1667,9 +1667,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1678,10 +1678,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1713,7 +1713,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1743,10 +1743,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1765,9 +1765,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1776,10 +1776,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1790,9 +1790,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1801,10 +1801,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1836,7 +1836,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component.regex.root)) } } @@ -1866,10 +1866,10 @@ extension Optionally { extension Optionally { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrOne, kind, component().regex.root)) } } @@ -1888,9 +1888,9 @@ extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component.regex.root)) } } @@ -1899,10 +1899,10 @@ extension ZeroOrMore { extension ZeroOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.zeroOrMore, kind, component().regex.root)) } } @@ -1913,9 +1913,9 @@ extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component.regex.root)) } } @@ -1924,10 +1924,10 @@ extension OneOrMore { extension OneOrMore { @available(SwiftStdlib 5.7, *) public init( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.oneOrMore, kind, component().regex.root)) } } @@ -1959,7 +1959,7 @@ extension Repeat { public init( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ expression: R, - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @RegexComponentBuilder _ component: () -> Component ) where RegexOutput == (Substring, C0?, C1?, C2?, C3?, C4?, C5?, C6?, C7?, C8?, C9?), Component.RegexOutput == (W, C0, C1, C2, C3, C4, C5, C6, C7, C8, C9), R.Bound == Int { self.init(node: .repeating(expression.relative(to: 0..( _ component: Component, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) \(params.whereClauseForInit) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.\(kind.astQuantifierAmount), kind, component.regex.root)) } } @@ -390,10 +390,10 @@ struct VariadicsGenerator: ParsableCommand { \(defaultAvailableAttr) \(params.disfavored)\ public init<\(params.genericParams)>( - _ behavior: QuantificationBehavior? = nil, + _ behavior: RegexRepetitionBehavior? = nil, @\(concatBuilderName) _ component: () -> Component ) \(params.whereClauseForInit) { - let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.astKind) } ?? .default + let kind: DSLTree.QuantificationKind = behavior.map { .explicit($0.dslTreeKind) } ?? .default self.init(node: .quantification(.\(kind.astQuantifierAmount), kind, component().regex.root)) } } @@ -509,7 +509,7 @@ struct VariadicsGenerator: ParsableCommand { public init<\(params.genericParams), R: RangeExpression>( _ component: Component, _ expression: R, - _ behavior: QuantificationBehavior? = nil + _ behavior: RegexRepetitionBehavior? = nil ) \(params.repeatingWhereClause) { self.init(node: .repeating(expression.relative(to: 0.. Regex { - wrapInOption(.reluctantByDefault, addingIf: useReluctantQuantifiers) + /// Passing `.eager` or `.reluctant` to this method corresponds to applying + /// the `(?-U)` or `(?U)` option in regex syntax, respectively. + /// + /// - Parameter behavior: The default behavior to use for quantifiers. + public func repetitionBehavior(_ behavior: RegexRepetitionBehavior) -> Regex { + if behavior == .possessive { + return wrapInOption(.possessiveByDefault, addingIf: true) + } else { + return wrapInOption(.reluctantByDefault, addingIf: behavior == .reluctant) + } } /// Returns a regular expression that matches with the specified semantic @@ -183,6 +189,46 @@ public struct RegexWordBoundaryKind: Hashable { } } +/// Specifies how much to attempt to match when using a quantifier. +@available(SwiftStdlib 5.7, *) +public struct RegexRepetitionBehavior: Hashable { + internal enum Kind { + case eager + case reluctant + case possessive + } + + var kind: Kind + + @_spi(RegexBuilder) public var dslTreeKind: DSLTree._AST.QuantificationKind { + switch kind { + case .eager: return .eager + case .reluctant: return .reluctant + case .possessive: return .possessive + } + } +} + +@available(SwiftStdlib 5.7, *) +extension RegexRepetitionBehavior { + /// Match as much of the input string as possible, backtracking when + /// necessary. + public static var eager: Self { + .init(kind: .eager) + } + + /// Match as little of the input string as possible, expanding the matched + /// region as necessary to complete a match. + public static var reluctant: Self { + .init(kind: .reluctant) + } + + /// Match as much of the input string as possible, performing no backtracking. + public static var possessive: Self { + .init(kind: .possessive) + } +} + // MARK: - Helper method @available(SwiftStdlib 5.7, *) diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift index 03fc21d49..7d1151189 100644 --- a/Tests/RegexBuilderTests/RegexDSLTests.swift +++ b/Tests/RegexBuilderTests/RegexDSLTests.swift @@ -272,7 +272,7 @@ class RegexDSLTests: XCTestCase { OneOrMore(.word) Anchor.wordBoundary } - OneOrMore(.any, .reluctantly) + OneOrMore(.any, .reluctant) "stop" " " @@ -281,7 +281,7 @@ class RegexDSLTests: XCTestCase { Anchor.wordBoundary } .wordBoundaryKind(.unicodeLevel1) - OneOrMore(.any, .reluctantly) + OneOrMore(.any, .reluctant) "stop" } } @@ -293,14 +293,14 @@ class RegexDSLTests: XCTestCase { Capture { // Reluctant behavior due to option OneOrMore(.anyOf("abcd")) - .reluctantQuantifiers() + .repetitionBehavior(.reluctant) } ZeroOrMore("a"..."z") Capture { // Eager behavior due to explicit parameter, despite option - OneOrMore(.digit, .eagerly) - .reluctantQuantifiers() + OneOrMore(.digit, .eager) + .repetitionBehavior(.reluctant) } ZeroOrMore(.digit) } @@ -319,6 +319,7 @@ class RegexDSLTests: XCTestCase { } func testQuantificationBehavior() throws { + // Eager by default try _testDSLCaptures( ("abc1def2", ("abc1def2", "2")), matchType: (Substring, Substring).self, ==) @@ -328,41 +329,93 @@ class RegexDSLTests: XCTestCase { ZeroOrMore(.any) } + // Explicitly reluctant try _testDSLCaptures( ("abc1def2", ("abc1def2", "1")), matchType: (Substring, Substring).self, ==) { - OneOrMore(.word, .reluctantly) + OneOrMore(.word, .reluctant) Capture(.digit) ZeroOrMore(.any) } - -#if os(macOS) - try XCTExpectFailure("'relucantCaptures()' API should only affect regex literals") { - try _testDSLCaptures( - ("abc1def2", ("abc1def2", "2")), - matchType: (Substring, Substring).self, ==) - { - Regex { - OneOrMore(.word) - Capture(.digit) - ZeroOrMore(.any) - }.reluctantQuantifiers() - } - } -#endif - + // Explicitly reluctant overrides default option try _testDSLCaptures( ("abc1def2", ("abc1def2", "1")), matchType: (Substring, Substring).self, ==) { - OneOrMore(.reluctantly) { + OneOrMore(.reluctant) { .word - } + }.repetitionBehavior(.possessive) Capture(.digit) ZeroOrMore(.any) } + // Default set to reluctant + try _testDSLCaptures( + ("abc1def2", ("abc1def2", "1")), + matchType: (Substring, Substring).self, ==) + { + Regex { + OneOrMore(.word) + Capture(.digit) + ZeroOrMore(.any) + }.repetitionBehavior(.reluctant) + } + // Default set to reluctant applies to regex syntax + try _testDSLCaptures( + ("abc1def2", ("abc1def2", "1")), + matchType: (Substring, Substring).self, ==) + { + try! Regex(#"\w+(\d).*"#, as: (Substring, Substring).self) + .repetitionBehavior(.reluctant) + } + // Explicitly possessive + try _testDSLCaptures( + ("aaaa", nil), + matchType: Substring.self, ==) + { + Regex { + OneOrMore("a", .possessive) + "a" + } + } + // Default set to possessive + try _testDSLCaptures( + ("aaaa", nil), + matchType: Substring.self, ==) + { + Regex { + OneOrMore("a") + "a" + }.repetitionBehavior(.possessive) + } + // More specific default set to eager + try _testDSLCaptures( + ("aaaa", ("aaaa", "aaa")), + matchType: (Substring, Substring).self, ==) + { + Regex { + Capture { + OneOrMore("a") + .repetitionBehavior(.eager) + } + OneOrMore("a") + }.repetitionBehavior(.possessive) + } + // More specific default set to reluctant + try _testDSLCaptures( + ("aaaa", ("aaaa", "a")), + matchType: (Substring, Substring).self, ==) + { + Regex { + Capture { + OneOrMore("a") + .repetitionBehavior(.reluctant) + } + OneOrMore("a") + }.repetitionBehavior(.possessive) + } + try _testDSLCaptures( ("abc1def2", "abc1def2"), matchType: Substring.self, ==) From eba03934d4743638a008af258f41a460048e2713 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Thu, 21 Apr 2022 14:47:34 -0500 Subject: [PATCH 3/3] Fixup for missing AST import separation This will go back when 182da3bb462055f50e9b67aae626d43fe70025a6 is merged into the 5.7 branch. --- Sources/_StringProcessing/Regex/Options.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/_StringProcessing/Regex/Options.swift b/Sources/_StringProcessing/Regex/Options.swift index 47a4ba06f..b5a70fc84 100644 --- a/Sources/_StringProcessing/Regex/Options.swift +++ b/Sources/_StringProcessing/Regex/Options.swift @@ -200,7 +200,7 @@ public struct RegexRepetitionBehavior: Hashable { var kind: Kind - @_spi(RegexBuilder) public var dslTreeKind: DSLTree._AST.QuantificationKind { + @_spi(RegexBuilder) public var dslTreeKind: AST.Quantification.Kind { switch kind { case .eager: return .eager case .reluctant: return .reluctant