Skip to content

feat(core): language inclusion for regular Coregexes. - #324

Merged
SimY4 merged 2 commits into
mainfrom
nfa-inclusion
Nov 12, 2026
Merged

SimY4 merged 2 commits into
mainfrom
nfa-inclusion

Conversation

@SimY4

@SimY4 SimY4 commented Nov 12, 2026

Copy link
Copy Markdown
Owner

New exact language operations on Coregex, decided on a Thompson NFA built from the regex:

  • isSubsetOf(Coregex): whether every string fully matched by this regex is matched by the other.
  • difference(Coregex): the shortest string matched by this regex but not by the other.
  • intersection(Coregex): the shortest string matched by both.

The search walks the product of this NFA with the lazily determinized other NFA, pruning pairs with antichains, so subset checks stay fast even with nested repetitions.

Non-regular constructs (back references, atomic groups, possessive quantifiers, lookarounds, word boundaries) and ASCII approximations of UNICODE_CHARACTER_CLASS char classes are rejected with UnsupportedOperationException. Anchors (^, \A, $, \z, \Z) are supported at the input boundary, where they are no-ops under Matcher#matches().

Lookaround generation via NFA.

New exact language operations on Coregex, decided on a Thompson NFA built from the regex:
- `isSubsetOf(Coregex)`: whether every string fully matched by this regex is matched by the other.
- `difference(Coregex)`: the shortest string matched by this regex but not by the other.
- `intersection(Coregex)`: the shortest string matched by both.

The search walks the product of this NFA with the lazily determinized other NFA, pruning pairs with antichains, so subset checks stay fast even with nested repetitions.

Non-regular constructs (back references, atomic groups, possessive quantifiers, lookarounds, word boundaries) and ASCII approximations of UNICODE_CHARACTER_CLASS char classes are rejected with UnsupportedOperationException. Anchors (`^`, `\A`, `$`, `\z`, `\Z`) are supported at the input boundary, where they are no-ops under Matcher#matches().
Lookarounds used to be checked by Coregex#match() against the whole input generated before (lookbehind) or after (lookahead), rather than a suffix or prefix of it. Negative lookarounds could generate non-matching strings, e.g. `ba(?<!a)` or `(?!a)[ab]b`, and positive ones failed to generate at all, e.g. `b[ab](?<=a)`, `(?=a)[ab]b` or `ab\b`.

Lookarounds are now checked with an NFA: the input generated so far has to match `[\s\S]*body` for lookbehind, the rest of the input has to match `body[\s\S]*` for lookahead. Anchors and word boundaries are encoded with standard lookarounds accordingly.

Lookaround bodies have to be regular now: back references, nested lookarounds and possessive quantifiers inside lookarounds are rejected with UnsupportedOperationException.
@SimY4
SimY4 merged commit 4a1870e into main Nov 12, 2026
6 checks passed
@SimY4
SimY4 deleted the nfa-inclusion branch November 12, 2026 07:40
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.

1 participant