Skip to content

fix(dummies): align StringMatching dialect edges with the real engine - #273

Merged
Reefact merged 2 commits into
mainfrom
claude/issue-210-discussion-yidclt
Jul 21, 2026
Merged

fix(dummies): align StringMatching dialect edges with the real engine#273
Reefact merged 2 commits into
mainfrom
claude/issue-210-discussion-yidclt

Conversation

@Reefact

@Reefact Reefact commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

Corrects four cosmetic edges in the Dummies regex subsystem (StringMatching), all of which failed in the safe direction (a refusal or a wrong message, never a mis-generated value). They share one spine: a pattern the real .NET engine accepts must never surface as ArgumentException, which the parser advertises as meaning "malformed / the engine rejects it".

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Analyzer / diagnostic change
  • Tests
  • Documentation
  • Build / CI / tooling

Changes

  • Honest over-limit message (RegexNode.cs): the ceiling exception blamed "a nested unbounded quantifier expanding without bound" even for a purely bounded pattern such as (a{1000}){1000} (1,000,000 characters, no unbounded quantifier at all). It now states the fact and offers both possible causes. The ceiling is a resource guard, not a satisfiability conflict, so the pattern still parses and fails at generation.
  • Repeated and quantified boundary anchors are no-ops (RegexParser.cs): ^^, $$, ^*, $?, ^{2} are all no-ops the engine accepts and matches, yet ^^abc was accepted while abc$$ was refused. A run of, or a quantifier on, a boundary anchor is now consumed as the no-op it is, closing the ^^/$$ asymmetry. A misplaced anchor (a^, $a) is still refused.
  • Leading -[ in a class is a literal hyphen (RegexParser.cs): [-[x]] is {-,[,x} then a literal ] to the engine, not a subtraction. -[ is now treated as subtraction only when a base member precedes it — which also correctly refuses the member-preceding forms [a-[x]] / [ab-[b]] the engine reads as subtraction (previously mis-reported as a malformed out-of-order range).
  • Negated class over the empty universe (RegexParser.cs): a negated class that excludes every printable-ASCII character ([^\x20-\x7E], [^\s\S]) is well-formed and regular; it is now refused as UnsupportedRegexException (a universe limit) with a tailored message, instead of ArgumentException ("malformed"). This changes the exception type for these patterns.
  • Oracle-backed invariant test (AnyPatternTests.cs): a theory asserts that every listed .NET-accepted pattern generates or is refused as unsupported, never as malformed — guarding the whole rejection channel, not just these instances. The newly-accepted patterns are also added to the existing real-engine oracle theory.

Testing

  • dotnet build FirstClassErrors.sln (0 warnings, 0 errors)
  • dotnet test FirstClassErrors.sln (all projects pass; Dummies.UnitTests 260/260)
  • Analyzer tests pass (FirstClassErrors.Analyzers.UnitTests 132/132)

Documentation

  • Public API / error documentation updated
  • README / doc/ updated
  • French translation (doc/handwritten/for-users/README.fr.md) updated if user-facing behavior changed
  • No documentation change required

In-code XML dialect docs on RegexParser / RegexGenerationContext were updated to match the new behavior. No user-facing dialect reference exists to sync (ADR-0025's "document the supported dialect" follow-up is still open) and the README does not document the regex dialect, so no doc/ or French-translation change applies.

Architecture decisions

  • No architectural decision in this pull request

Checked against the ADR base: the change stays within the decided scope of ADR-0025 (generate from a home-grown regular subset; two-channel rejection taxonomy). The reinforced invariant — a .NET-accepted pattern is never reported as malformed — is a consequence of that taxonomy, not a new lasting decision, so no ADR is drafted or superseded.

Related issues

Closes #210

🤖 Generated with Claude Code


Generated by Claude Code

claude and others added 2 commits July 21, 2026 16:08
Four cosmetic StringMatching edges from the ADR-0025 dialect, all
failing in the safe direction (a refusal or a wrong message, never a
mis-generated value), share one spine: a pattern the real .NET engine
accepts must never surface as ArgumentException — the taxonomy the
parser advertises (ArgumentException == malformed == the engine
rejects it).

- The over-limit message blamed "a nested unbounded quantifier
  expanding without bound" even for a purely bounded pattern such as
  (a{1000}){1000}, which asks for 1,000,000 characters with no
  unbounded quantifier at all. State the fact and offer both causes;
  the ceiling is a resource guard, not a satisfiability conflict, so
  the pattern still parses and fails at generation.
- Repeated and quantified boundary anchors are no-ops the engine
  accepts and matches (^^, $$, ^*, $?, ^{2}), yet ^^abc was accepted
  while abc$$ was refused. Consume a run of, or a quantifier on, a
  boundary anchor as the no-op it is — closing the ^^/$$ asymmetry.
- A leading '-[' in a class is an ordinary hyphen to the engine
  ([-[x]] = {-,[,x} then ']'), not a subtraction, yet it was refused.
  Treat '-[' as subtraction only when a base member precedes — which
  also correctly refuses the member-preceding forms [a-[x]] / [ab-[b]]
  the engine reads as subtraction (previously mis-reported as a
  malformed out-of-order range).
- A negated class that excludes the whole printable-ASCII universe
  ([^\x20-\x7E], [^\s\S]) is well-formed and regular; refuse it as
  UnsupportedRegexException (a universe limit) with a tailored message,
  not as a malformed pattern.

An oracle-backed theory pins the spine: every listed .NET-accepted
pattern generates or is refused as unsupported, never as malformed.

Refs: #210
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zJD4hf5JiKGt3D5HducWT
@Reefact
Reefact enabled auto-merge July 21, 2026 18:46
@Reefact
Reefact merged commit 7663f73 into main Jul 21, 2026
15 checks passed
@Reefact
Reefact deleted the claude/issue-210-discussion-yidclt branch July 21, 2026 18:49
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.

Dummies: minor StringMatching dialect edges (limit message, conservative refusals, negated-class taxonomy)

2 participants