def get_top_level_matching_pairs(
expression: str,
mapping: dict[str, str],
) -> list[tuple[int, int, int, int]]:
def head_starts_with_one_from(match_targets: Iterable[str]) -> Optional[str]:
for m in match_targets:
if expression.startswith(m, i):
return m
return None
res = []
queue = []
i = 0
while i < len(expression):
if open := head_starts_with_one_from(mapping.keys()):
queue.append((i, mapping[open]open))
i += len(open)
elif close := head_starts_with_one_from(mapping.values()):
if not queue:
# raise closing sequence without an opening.
index, matchfirst_match = queue.pop()
match = mapping[first_match]
if match != close:
# raise mismatched opening and closing characters.
if not queue: # This closing token closes a top-level opening sequence, so add the result
res.append((index, index + len(matchfirst_match), i, i + len(close)))
i += len(close)
else:
i += 1
return res