Skip to content

feat(dummies): validate named group names and reject balancing groups - #271

Merged
Reefact merged 2 commits into
mainfrom
claude/issue-209-discussion-5z4wjd
Jul 21, 2026
Merged

feat(dummies): validate named group names and reject balancing groups#271
Reefact merged 2 commits into
mainfrom
claude/issue-209-discussion-5z4wjd

Conversation

@Reefact

@Reefact Reefact commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

The regex parser now validates named group names as the real .NET engine would, rejecting invalid names and balancing groups that manipulate the capture stack. This ensures that patterns accepted by Dummies stay aligned with patterns accepted by .NET, preventing silent mis-generation of non-regular constructs.

Type of change

  • New feature
  • Tests

Changes

  • Named group name validation: Added ValidateGroupName() method that checks group names according to .NET rules:

    • Rejects balancing groups ((?<name1-name2>…) / (?<-name>…)) as unsupported, since they manipulate the capture stack (non-regular)
    • Validates numeric group names (those starting with a digit) as positive integers with no leading zero
    • Validates non-numeric names as word characters (letter, digit, underscore) only
    • Throws ArgumentException for malformed names, mirroring the real engine
    • Throws UnsupportedRegexException for balancing groups, even when the target group is undefined (divergence from .NET's malformed-pattern verdict is accepted since the generator lacks a capture-group table)
  • Updated SkipGroupName() signature: Now accepts a position parameter to enable proper error reporting, and calls ValidateGroupName() after parsing the name

  • Updated documentation:

    • RegexParser class documentation now mentions that group names are validated
    • UnsupportedRegexException documentation updated to list balancing groups as a refused construct
    • Comprehensive XML documentation added to ValidateGroupName() explaining the validation rules and the deliberate divergence from .NET on undefined balancing-group targets
  • Added unit tests:

    • AnyPatternTests.AnyPatternTests(): Added valid patterns with explicitly-numbered groups and named groups containing digits
    • BalancingGroupsAreRefused(): Tests that balancing groups are rejected in both syntaxes and whether the target is defined or not
    • InvalidGroupNamesAreRejected(): Tests that invalid names (leading zeros, non-word characters, reserved group 0) are rejected as malformed

Testing

  • dotnet build FirstClassErrors.sln
  • dotnet test FirstClassErrors.sln

Architecture decisions

  • No architectural decision in this pull request

Related issues

https://claude.ai/code/session_01RjjDWNEx4riWGjx19FmPN9

claude and others added 2 commits July 21, 2026 15:19
SkipGroupName scanned a named-group name to its terminator without
validating it, so two well-formed .NET constructs slipped through as
ordinary named groups:

- a balancing group '(?<-name>…)' / '(?<name1-name2>…)' is non-regular
  (it pops the capture stack, the backreference family). Lowering it to
  a plain named group mis-generated: '(?<a>y)?(?<-a>x)' has language
  {"yx"}, yet the generator could emit "x" — the exact silently
  non-matching value ADR-0025 forbids;
- an invalid group name (a space, a dot, a bad numeric form) was
  accepted where the real engine rejects it.

Validate the captured name at the call site: a '-' is refused as an
unsupported balancing group, including when its target is undefined
(where .NET reports a malformed pattern instead — telling the two apart
would need a capture table the generator deliberately does not keep, so
the divergence is only in the error kind, both reject and neither
mis-generates); a name opening with a digit must be a positive group
number with no leading zero ('1', '10'; not '0', '01', '1a'); any other
name must be word characters. Numbered and ordinary named groups keep
parsing and generating unchanged, in both the '(?<…>)' and '(?'…')'
syntaxes.

Refs: #209
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjjDWNEx4riWGjx19FmPN9
@Reefact
Reefact merged commit ceef914 into main Jul 21, 2026
15 checks passed
@Reefact
Reefact deleted the claude/issue-209-discussion-5z4wjd branch July 21, 2026 15:33
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.

2 participants