Quantifier: The Final Part of a Regex Atom#

class my.regex.meta.Quantifier.Quantifier(data: str | Self = '', extra: '' | '?' | '+' | None = None)#

Subatomic syntax that specifies how many times the atom is allowed to occur.

Examples

Inspect a quantifier’s range and traits:

>>> quant = Quantifier('{2,4}')
>>> quant.range, quant.is_ranged, quant.is_optional
((2, 4), True, False)

The lazy/possessive suffix is separated from the base:

>>> Quantifier('*+').base, Quantifier('*+').extra
('*', '+')

I Initial Methods#

classmethod Quantifier.from_range(r0: int, r1: int, extra: '' | '?' | '+' | None = None) → Self#

Create a Quantifier from a range of occurrences, choosing the shortest valid syntax.

Parameters:
  • r0 – Minimum number of occurrences (must be non-negative).

  • r1 – Maximum number of occurrences, or a negative value for “unbounded”.

  • extra – Optional lazy (?) or possessive (+) suffix to append.

Returns:

The simplest quantifier expressing the range.

Raises:

ValueError – If the minimum is negative.

Examples

Common ranges collapse to their shorthand forms:

>>> str(Quantifier.from_range(0, 1)), str(Quantifier.from_range(1, -1))
('?', '+')
>>> str(Quantifier.from_range(2, 5)), str(Quantifier.from_range(3, 3))
('{2,5}', '{3}')

II Primary Methods#

Quantifier.join(other: str | Self) → Self | None#

Combine this quantifier with another into a single equivalent quantifier, if possible.

If the two quantifiers cannot be simply combined, return None to indicate that nested groups are needed. Also available via the & operator.

Parameters:

other – The quantifier to combine with this one.

Returns:

The combined quantifier, or None if nesting is required.

Examples

Multiply out compatible quantifiers; incompatible pairs return None:

>>> Quantifier('{2,3}').join('{2,3}')
Quantifier('{4,9}')
>>> Quantifier('+').join('*')
Quantifier('*')
>>> Quantifier('{3,5}').join('?') is None
True
Quantifier.as_optional() → Self | None#

Create a copy of this quantifier made optional, if possible (e.g. + -> *).

Unlike as_required(), this function may not always succeed, as there are valid quantifiers that cannot be made optional without wrapping them (i.e. (?:...)?) – namely, this applies to range quantifiers that start beyond 1 (e.g. {3,5}).

Returns:

The optional copy, or None if this quantifier cannot be made optional in place.

Examples

Loosen a quantifier to permit zero occurrences:

>>> Quantifier('+').as_optional()
Quantifier('*')
>>> Quantifier('{3,5}').as_optional() is None
True
Quantifier.as_required() → Self#

Create a copy of this quantifier made NON-optional (e.g. * -> +).

Examples

Force at least one occurrence:

>>> Quantifier('*').as_required()
Quantifier('+')
>>> Quantifier('{0,4}').as_required()
Quantifier('{1,4}')

III Overrides#

Quantifier.startswith(prefix: str) → bool#

Check if the quantifier starts with the given prefix.

Quantifier.endswith(suffix: str) → bool#

Check if the quantifier ends with the given suffix.

IV Properties#

property Quantifier.base: str#

The quantifier’s text without its lazy/possessive extra suffix (e.g. *+ -> *).

property Quantifier.extra: '' | '?' | '+'#

The “extra” part of the quantifier (i.e. the lazy ? or possessive +).

property Quantifier.is_simple: bool#

Whether the quantifier is “simple” (i.e. empty or ?).

property Quantifier.is_basic: bool#

Whether the quantifier is “basic” (i.e. empty, ?, *, or +).

property Quantifier.is_ranged: bool#

Whether the quantifier is a range (i.e. starts with {).

property Quantifier.is_optional: bool#

Whether the quantifier allows zero occurrences.

property Quantifier.is_lazy: bool#

Whether the quantifier is lazy (i.e. ends with extra ?).

property Quantifier.is_possessive: bool#

Whether the quantifier is possessive (i.e. ends with extra +).

property Quantifier.range: tuple[int, int]#

The (min, max) occurrences of a ranged quantifier, with -1 marking “not applicable”.

Non-ranged quantifiers yield (-1, -1); an open-ended range like {2,} yields (2, -1).