Repository navigation
Commit ae12284
committed
refactor: replace regex matcher with linear-time two-ended scan
The regex-based URI template matcher required an ever-growing set of
parse-time adjacency checks to reject templates that would cause
catastrophic backtracking. Python's re module is a backtracking engine,
so any pair of greedy groups with overlapping character classes and a
failing suffix produces O(n^k) match time. Enumerating every such
combination proved intractable — each fix revealed another bypass.
This replaces the regex matcher with a two-ended linear scan:
- Templates are flattened into a sequence of literal and capture atoms,
with operator prefixes/separators lowered to explicit literals.
- A template may contain at most one multi-segment variable ({+var},
{#var}, or explode). This is the only structural restriction.
- The suffix is scanned right-to-left: literals via endswith, bounded
variables via rfind of the preceding literal. This matches regex
greedy-first semantics exactly for templates without a greedy var.
- If a greedy var exists, the prefix is scanned left-to-right with
lazy anchor-finding, and the greedy var gets whatever remains between
prefix_end and suffix_start.
Every URI character is visited O(1) times per atom. There is no
backtracking; a failed anchor search returns None immediately.
Removes _check_ambiguous_adjacency (80 lines of state tracking),
_build_pattern, _expression_pattern, and the _pattern field. Templates
previously rejected for adjacency ({+a}{b}, {a}{+b}, prefix/{+path}{.ext})
are now accepted and match in linear time. The only rejected patterns
are those with two or more multi-segment variables, which are
inherently ambiguous regardless of algorithm.1 parent 19822fb commit ae12284
2 files changed
Lines changed: 446 additions & 264 deletions
0 commit comments