Build your own regex engine
Stage 7 of 8v2 · 4e350638

Lazy quantifiers and replacement

Implement lazy repetition and capture expansion in replacements.

Build it in your language

The tester treats your program as a black box: any language works. These are just the most convenient ones for this project.

Lazy Quantifiers (+?, *?) and Text Replacement

Appending ? to a quantifier creates a lazy quantifier matching the fewest characters possible. The replace operation substitutes matches, substituting group placeholders like $1.

Mental Model: Minimal Expansion and $N Substitution

  • <.+?> over "<a><b>": stops at "<a>" rather than spanning to the final >.
  • Template "[$1]" injects group 1's capture "a" -> "[a]".

Your Goal in this Stage

Implement lazy quantifiers and op: "replace" with all: true and group backreferences.

Input Format

json
{
  "op": "replace",
  "pattern": "<(.+?)>",
  "text": "<a><b>",
  "replacement": "[$1]",
  "all": true
}

Output Format

json
{
  "text": "[a][b]"
}

Step-by-Step Implementation Guide

  1. Lazy quantifiers: Try minimum repetitions first, growing only when required.
  2. String replacement: Interpolate $1, $2 with group captures.
  3. Global replacement: Repeat across text when all: true.
  4. Emit output: Print JSON object.

Acceptance Criteria

  • ✅ Minimal matching with lazy quantifiers.
  • ✅ Replaces capture references $1, $2.

Output and errors

Multiline examples are formatted for readability. Emit compact JSON without optional spaces, with properties in the order shown by the output examples, and a final newline. Keep logs off stdout. Tests compare exact text. Invalid inputs use stderr containing error, empty stdout, and exit 1. Valid inputs exit 0. Serialize integer results as JSON integers.

Replacement rules

$0 means the complete match; $1 through $9 mean numbered captures. A reference to a nonexistent group remains literal: (a) on a with $1-$9 produces a-$9. An existing optional group that did not participate contributes an empty string. With all: false, replace only the first match; with all: true, replace non-overlapping matches from left to right. Advance one character after an empty match to avoid an infinite loop.