Regex: A Parsed Regular Expression#

class my.regex.meta.Regex.Regex(*args: str | Atom | Iterable[Atom] | Self)#

A mutable representation of a regex expression, valid or otherwise.

A Regex is essentially a list of Atom objects: it can be indexed, sliced, iterated, compared, and concatenated, and it serializes back to the raw pattern text via str().

Examples

Parse an expression into atoms and read its parts:

>>> expr = Regex(r'ab(?:cd)+[ef]\d?')
>>> list(expr)
['a', 'b', '(?:cd)+', '[ef]', '\\d?']
>>> str(expr)
'ab(?:cd)+[ef]\\d?'

I Initial Methods#

classmethod Regex.atomize(expr: str | Buffer | Self) → Generator[Atom]#

Break a regex expression into its atomic components.

Parameters:

expr – The raw regular expression string to atomize.

Yields:

Atomic regex components (characters, groups, character sets, etc.), each carrying its quantifier.

Examples

Groups and sets are atoms too, no matter how long they are:

>>> from my import Regex
>>> list(Regex.atomize(r'ab?(?:cd|ef)[xyz]+'))
['a', 'b?', '(?:cd|ef)', '[xyz]+']
classmethod Regex.empty() → Self#

Create a new ‘empty’ instance, holding just one empty Atom.

Regex.copy() → Self#

Create a deep copy of this Regex instance (as Atoms are immutable).

II Primary Methods#

classmethod Regex.group_iterator(text: ~my.types.Buffer.Buffer | str | list[str], mask: ~my.regex.meta.GroupKind.GroupKind = <GroupKind: 0>, mode: 'all' | 'roots' | 'leaves' = 'all') → Iterator[GroupAtom]#

Iterate over all groups in the given pattern (e.g. (?:abc)).

Parameters:
  • text – Text to search for groups (will be converted to Buffer).

  • mask – Optional GroupKind filter to yield only matching group types.

  • mode – ‘all’ by default, ‘roots’ to exclude nested groups, or ‘leaves’ for the opposite.

Yields:

A GroupAtom for each group found, populated with its span, kind, name, and body.

Examples

Filter for one kind of group with a mask:

>>> from my import Regex, GroupKind
>>> groups = Regex.group_iterator(r'(?P<a>x)(?P<b>y)', mask=GroupKind.NAMED)
>>> [group.name for group in groups]
['a', 'b']
classmethod Regex.set_iterator(text: Buffer | str | list[str]) → Iterator[SetAtom]#

Find and yield all the character sets (e.g. [A-Za-z]) in the given text.

Parameters:

text – Text to search for character sets.

Yields:

A SetAtom for each root-level character set found, populated with its span and body.

Examples

Iterate the sets of a pattern:

>>> [s.body for s in Regex.set_iterator(r'[a-z]+[0-9]')]
['a-z', '0-9']

III Properties#

property Regex.first: Atom#

The first Atom in this expression, or an empty Atom if this expression is empty.

property Regex.last: Atom#

The last Atom in this expression, or an empty Atom if this expression is empty.

property Regex.one: Atom#

The sole Atom in this expression, or an empty Atom if this expression is empty.

property Regex.spans: list[tuple[int, int]]#

The raw-text (start, end) spans of each Atom in this expression.

IV Methods#

Regex.quantify(quantifier: str | Quantifier, overwrite: bool = False) → Self#

Create a new version of this expression that has the requested quantifier applied to it.

Handles patterns that need to be wrapped before a quantifier is applied.

Parameters:
  • quantifier – The quantifier string to apply (e.g. ?, +, *, {2,5}).

  • overwrite – Whether to replace an existing expr-level quantifier rather than wrapping it.

Returns:

A new, quantified Regex (the original is NOT modified).

Examples

Multi-atom expressions are wrapped before quantification; single atoms are not:

>>> str(Regex(r'abc').quantify('+'))
'(?:abc)+'
>>> str(Regex(r'a').quantify('+'))
'a+'
classmethod Regex.is_split(expr: str | Atom | Self) → bool#

Check if the given expression contains any top-level | splitters.

Examples

Splitters inside groups do not count:

>>> Regex.is_split(r'a|b'), Regex.is_split(r'(?:a|b)')
(True, False)
classmethod Regex.is_atomic(expr: str | Atom | Self) → bool#

Check if the given expression is atomic (i.e. composed of a single atom).

Examples

A whole group is one atom; two literals are not:

>>> Regex.is_atomic(r'(?:a|b)'), Regex.is_atomic(r'ab')
(True, False)
Regex.split() → Iterator[Self]#

Split the Regex instance into branches at top-level | atoms.

Examples

Split an alternation into its branches:

>>> [str(branch) for branch in Regex(r'foo|bar|baz').split()]
['foo', 'bar', 'baz']
Regex.startswith(other: str | Atom | Self) → bool#

Check if this Regex starts with the given pattern.

Regex.endswith(other: str | Atom | Self) → bool#

Check if this Regex ends with the given pattern.