Skip to content

Instantly share code, notes, and snippets.

@robnadin
Last active July 24, 2024 09:03
Show Gist options
  • Save robnadin/128d73aa4b5f4011ad0cdb2bbca0ea4f to your computer and use it in GitHub Desktop.
Save robnadin/128d73aa4b5f4011ad0cdb2bbca0ea4f to your computer and use it in GitHub Desktop.
import RegexBuilder
extension Regex {
/// Transforms the output of a regex component using the provided transformation function.
///
/// - Parameter transform: A closure that takes the output of the regex and transforms it to a new output type.
/// - Returns: A new `Regex` instance that applies the transformation function to its output.
public func mapOutput<NewOutput>(_ transform: @escaping (Output) throws -> NewOutput) -> Regex<NewOutput> {
Regex<NewOutput> {
MapOutput(innerRegex: self, transform: transform)
}
}
}
private struct MapOutput<Output, NewOutput>: CustomConsumingRegexComponent {
typealias RegexOutput = NewOutput
let innerRegex: Regex<Output>
let transform: (Output) throws -> NewOutput
func consuming(
_ input: String,
startingAt index: String.Index,
in bounds: Range<String.Index>) throws -> (upperBound: String.Index, output: NewOutput)?
{
guard index != bounds.upperBound, let match = input[index..<bounds.upperBound].prefixMatch(of: innerRegex) else {
return nil
}
let output = try transform(match.output)
return (match.range.upperBound, output)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment