Skip to content

parser: add (?:...) non-capturing and (?<name>...) named capture group syntax#4

Open
robertream wants to merge 2 commits into2kai2kai2:mainfrom
robertream:add-ui-compile-fail-named-captures
Open

parser: add (?:...) non-capturing and (?<name>...) named capture group syntax#4
robertream wants to merge 2 commits into2kai2kai2:mainfrom
robertream:add-ui-compile-fail-named-captures

Conversation

@robertream
Copy link

@robertream robertream commented Mar 6, 2026

Extends the POSIX ERE parser with two non-standard but widely-used group syntaxes:

  • (?:...) — non-capturing group: parsed and matched but produces no StartCapture/EndCapture transitions, so N stays smaller
  • (?<name>...) — named capture group: behaves identically to an unnamed group at the engine level; name is available via ERE::group_names()

New parser variants: NonCapturingSubexpression, NamedSubexpression.
New error: InvalidGroupName (empty or unclosed name).
New method: ERE::group_names() — depth-first walk returning Vec<Option<String>> in group-number order, mirroring the simplified tree traversal.

attr-macro: add named struct field binding with #[group(N)]

Extends __compile_regex_attr to handle Fields::Named in addition to the existing Fields::Unnamed (tuple struct) path:

  • Fields without #[group(N)]: matched to capture groups by field name via ERE::group_names() — field order is independent of regex group order
  • Fields with #[group(N)]: bound to explicit capture group index N
  • #[group(N)] attributes are stripped from the emitted struct so the compiler does not see an unknown attribute
  • Out-of-bounds #[group(N)] index emits a clear compile error instead of panicking

Also adds doc comment for Regex::exec describing the [Option<&str>; N] return shape and when None is returned.

tests: add coverage for named groups, non-capturing groups, and #[group(N)]

  • compile_regex_group_extensions: verifies mixed (?<name>...)/(?:...) pattern compiles as Regex<3> across all four engines (non-capturing group excluded from N, named groups count same as unnamed)
  • non_capturing_group, named_capture_group_tuple_struct, named_field_struct: attr-macro smoke tests for new syntax with tuple and named structs
  • compile_fail tests via trybuild: unknown_field_name and group_index_out_of_bounds confirm macro emits clear compile errors

docs: document named groups, non-capturing groups, and #[group(N)] (with doc tests)

  • README: add “Named Groups and Non-Capturing Groups” section with live code examples for (?:...) and (?<name>...), plus a rust,ignore example for #[group(N)] (feature-gated, so not doc-tested by default)
  • ROADMAP: mark (?:...) non-capturing groups as [x] shipped; add [x] entry for (?<name>...) named capture groups
  • ere-macros: extend #[regex(...)] docs with two live doc-test examples — named struct with field-order independence, and optional named group mapping to Option<&'a str>

Validation

  • cargo test --all-features

Closes #2

…p syntax

Extends the POSIX ERE parser with two non-standard but widely-used group
syntaxes:

- `(?:...)` — non-capturing group: parsed and matched but produces no
  StartCapture/EndCapture transitions, so N stays smaller
- `(?<name>...)` — named capture group: behaves identically to an unnamed
  group at the engine level; name is available via ERE::group_names()

New parser variants: NonCapturingSubexpression, NamedSubexpression.
New error: InvalidGroupName (empty or unclosed name).
New method: ERE::group_names() — depth-first walk returning Vec<Option<String>>
in group-number order, mirroring the simplified tree traversal.

attr-macro: add named struct field binding with #[group(N)]

Extends __compile_regex_attr to handle Fields::Named in addition to the
existing Fields::Unnamed (tuple struct) path:

- Fields without #[group(N)]: matched to capture groups by field name
  via ERE::group_names() — field order is independent of regex group order
- Fields with #[group(N)]: bound to explicit capture group index N
- #[group(N)] attributes are stripped from the emitted struct so the
  compiler does not see an unknown attribute
- Out-of-bounds #[group(N)] index emits a clear compile error instead
  of panicking

Also adds doc comment for Regex::exec describing the [Option<&str>; N]
return shape and when None is returned.

tests: add coverage for named groups, non-capturing groups, and #[group(N)]

- compile_regex_group_extensions: verifies mixed (?<name>...)/(?:...) pattern
  compiles as Regex<3> across all four engines (non-capturing group excluded
  from N, named groups count same as unnamed)
- non_capturing_group, named_capture_group_tuple_struct, named_field_struct:
  attr-macro smoke tests for new syntax with tuple and named structs
- compile_fail tests via trybuild: unknown_field_name and
  group_index_out_of_bounds confirm macro emits clear compile errors

docs: document named groups, non-capturing groups, and #[group(N)] (with doc tests)

- README: add 'Named Groups and Non-Capturing Groups' section with live
  code examples for (?:...) and (?<name>...), plus a rust,ignore example
  for #[group(N)] (feature-gated, so not doc-tested by default)
- ROADMAP: mark (?:...) non-capturing groups as [x] shipped; add [x] entry
  for (?<name>...) named capture groups
- ere-macros: extend #[regex(...)] doc with two live doc-test examples —
  named struct with field-order independence, and optional named group
  mapping to Option<&'a str>
@robertream robertream changed the title Add UI compile-fail coverage for named capture bindings parser: add (?:...) non-capturing and (?<name>...) named capture group syntax Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support named capture groups

1 participant