<commit_before># Strongly Typed Regex Captures

Authors: [<NAME>](https://github.com/rxwei), [<NAME>](https://github.com/kylemacomber)

## Revision history

- **v1**
    - [Initial pitch](https://forums.swift.org/t/pitch-strongly-typed-regex-captures/53391).
- **v2**
    - Includes entire match in `Regex`'s generic parameter.
    - Fixes Quantification and Alternation capture types to be consistent with traditional back reference numbering.

## Introduction

Capturing groups are a commonly used component of regular expressions as they
allow the programmer to extract information from matched input. A capturing
group collects multiple characters together as a single unit that can be
[backreferenced](https://www.regular-expressions.info/backref.html) within the
regular expression and accessed in the result of a successful match. For
example, the following regular expression contains the capturing groups `(cd*)`
and `(ef)`.

```swift
// Regex literal syntax:
let regex = /ab(cd*)(ef)gh/
// => `Regex<(Substring, Substring, Substring)>`

// Equivalent result builder syntax:
//     let regex = Pattern {
//         "ab"
//         Group {
//             "c"
//             Repeat("d")
//         }.capture()
//         "ef".capture()
//         "gh"
//     }

if let match = "abcddddefgh".firstMatch(of: regex) {
    print(match) // => ("abcddddefgh", "cdddd", "ef")
}
```

>_**Note:** The `Regex` type includes, and `firstMatch(of:)` returns, the entire
match as the "0th capture"._

We introduce a generic type `Regex<Match>`, which treats the type of captures
as part of a regular expression's type information for clarity, type safety, and
convenience. As we explore a fundamental design aspect of the regular expression
feature, this pitch discusses the following topics:

- A type definition of the generic type `Regex<Match>` and `firstMatch(of:)`
  method.
- Capture type inference and composition in regular expression literals and the
  forthcoming result builder syntax.
- New language features which this design may require.

The focus of this pitch is the structural properties of capture types and how
regular expression patterns compose to form new capture types. The semantics of
string matching, its effect on the capture types (i.e.
`UnicodeScalarView.SubSequence` or `Substring`), and the result builder syntax
will be discussed in future pitches.

For background on Declarative String Processing, see related topics:
- [Declarative String Processing Overview](https://forums.swift.org/t/declarative-string-processing-overview/52459)
- [Regular Expression Literals](https://forums.swift.org/t/pitch-regular-expression-literals/52820)
- [Character Classes for String Processing](https://forums.swift.org/t/pitch-character-classes-for-string-processing/52920)
<commit_msg>"0th capture" -> "0th element"<commit_after># Strongly Typed Regex Captures

Authors: [<NAME>](https://github.com/rxwei), [<NAME>](https://github.com/kylemacomber)

## Revision history

- **v1**
    - [Initial pitch](https://forums.swift.org/t/pitch-strongly-typed-regex-captures/53391).
- **v2**
    - Includes entire match in `Regex`'s generic parameter.
    - Fixes Quantification and Alternation capture types to be consistent with traditional back reference numbering.

## Introduction

Capturing groups are a commonly used component of regular expressions as they
allow the programmer to extract information from matched input. A capturing
group collects multiple characters together as a single unit that can be
[backreferenced](https://www.regular-expressions.info/backref.html) within the
regular expression and accessed in the result of a successful match. For
example, the following regular expression contains the capturing groups `(cd*)`
and `(ef)`.

```swift
// Regex literal syntax:
let regex = /ab(cd*)(ef)gh/
// => `Regex<(Substring, Substring, Substring)>`

// Equivalent result builder syntax:
//     let regex = Pattern {
//         "ab"
//         Group {
//             "c"
//             Repeat("d")
//         }.capture()
//         "ef".capture()
//         "gh"
//     }

if let match = "abcddddefgh".firstMatch(of: regex) {
    print(match) // => ("abcddddefgh", "cdddd", "ef")
}
```

>_**Note:** The `Regex` type includes, and `firstMatch(of:)` returns, the entire
match as the "0th element"._

We introduce a generic type `Regex<Match>`, which treats the type of captures
as part of a regular expression's type information for clarity, type safety, and
convenience. As we explore a fundamental design aspect of the regular expression
feature, this pitch discusses the following topics:

- A type definition of the generic type `Regex<Match>` and `firstMatch(of:)`
  method.
- Capture type inference and composition in regular expression literals and the
  forthcoming result builder syntax.
- New language features which this design may require.

The focus of this pitch is the structural properties of capture types and how
regular expression patterns compose to form new capture types. The semantics of
string matching, its effect on the capture types (i.e.
`UnicodeScalarView.SubSequence` or `Substring`), and the result builder syntax
will be discussed in future pitches.

For background on Declarative String Processing, see related topics:
- [Declarative String Processing Overview](https://forums.swift.org/t/declarative-string-processing-overview/52459)
- [Regular Expression Literals](https://forums.swift.org/t/pitch-regular-expression-literals/52820)
- [Character Classes for String Processing](https://forums.swift.org/t/pitch-character-classes-for-string-processing/52920)

{'fraction_non_alphanumeric': 0.10760734010333155, 'fraction_numerical': 0.0085515766969535, 'mean_word_length': 4.057657657657658, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 20, 'https://': 14, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4256599', 'n_tokens_mistral': 1608, 'n_tokens_neox': 1509, 'n_words': 591}