regex: fold 5b — parse_repetition leaf (ha:486-545)

Dead until the { arm lands (tranche-A precedent); 13-row direct
private-fn table, error texts byte-exact. Hare's verbatim
((void|size),(void|size),size) tuple return can't cross a union
boundary yet — cstage's (tuple|error) return store is cgen-unwired and
wwstage's variant-match rejects the tuple case arm (filed #47) — so it
respells as the private repparts struct per the scope-fold5 §3
pre-signed fallback; graduates back to the tuple when #47 closes.
Riders: call-result .N tuple read loud-rejects (filed #48, bind-first
local); strings.index's standing i32 convention (#8) stays internal,
widened at each size boundary; ha:494's same-name re-bind is rejected,
second local feb.
This commit is contained in:
2026-06-05 04:33:33 +09:00
parent 26d375410e
commit c0c15945be
2 changed files with 180 additions and 0 deletions

View File

@@ -2137,6 +2137,90 @@ type smcase = struct {
};
};
// ---- fold 5b: repetition ----------------------------------------------
// parse_repetition rows (regex.ha:486-545) — DIRECT private-fn table
// (the leaf fn lands ahead of its `{`-arm consumer; tranche-A
// precedent). Expectations hand-executed from Hare's own code paths:
// the input is everything AFTER `{` (compile passes iterstr's rest),
// single-arg `{n}` sets max = min and replen = len(n) (ha:500-503,
// 539-541); two-arg replen = len(min) + 1 + len(max) (ha:543); an
// empty min is 0 (ha:524) while an empty max stays void (ha:527 —
// the `{n,}` open bound); a `,` BEYOND the first `}` is not a
// two-arg form (ha:499). The two error texts are byte-exact
// (ha:492/521/531-536). max_void distinguishes "expect void" from
// "expect maxv"; err != "" rows expect that exact error.
type prrow = struct {
input: str,
minv: size,
maxv: size,
max_void: bool,
replen: size,
err: str,
};
@test fn parse_repetition_cases() void = {
let rows: [13]prrow = [
prrow { input = "2}", minv = 2, maxv = 2, max_void = false,
replen = 1, err = "" },
prrow { input = "2}$", minv = 2, maxv = 2, max_void = false,
replen = 1, err = "" },
// comma AFTER the endbrace — still single-arg (ha:499)
prrow { input = "2},5", minv = 2, maxv = 2, max_void = false,
replen = 1, err = "" },
prrow { input = "1,2}", minv = 1, maxv = 2, max_void = false,
replen = 3, err = "" },
prrow { input = ",2}", minv = 0, maxv = 2, max_void = false,
replen = 2, err = "" },
prrow { input = ",0}", minv = 0, maxv = 0, max_void = false,
replen = 2, err = "" },
prrow { input = "2,}", minv = 2, maxv = 0, max_void = true,
replen = 2, err = "" },
prrow { input = ",}", minv = 0, maxv = 0, max_void = true,
replen = 1, err = "" },
prrow { input = "12,34}xyz", minv = 12, maxv = 34,
max_void = false, replen = 5, err = "" },
prrow { input = "-1,2}", minv = 0, maxv = 0, max_void = false,
replen = 0, err = "Negative repetition count '{-n}'" },
prrow { input = "x,2}", minv = 0, maxv = 0, max_void = false,
replen = 0,
err = "Repetition expression syntax error '{n}'" },
prrow { input = "0,-2}", minv = 0, maxv = 0, max_void = false,
replen = 0, err = "Negative repetition count '{-n}'" },
// no endbrace at all (ha:491-493)
prrow { input = "2", minv = 0, maxv = 0, max_void = false,
replen = 0,
err = "Repetition expression syntax error '{n}'" },
];
let i: i32 = 0;
for (i < len(rows)) {
let r: (repparts | error) = parse_repetition(rows[i].input);
match (r) {
case let t: repparts => {
if (rows[i].err.len > 0) { fail(); };
// .min is always size after a successful parse
// (ha:523-525 — empty min defaults to 0)
if (!(t.min is size)) { fail(); };
if (t.min as size != rows[i].minv) { fail(); };
if (rows[i].max_void) {
if (!(t.max is void)) { fail(); };
} else {
if (!(t.max is size)) { fail(); };
if (t.max as size != rows[i].maxv) { fail(); };
};
if (t.replen != rows[i].replen) { fail(); };
};
case let e: regex.error => {
if (rows[i].err.len == 0) { fail(); };
if (strings.compare((e: str), rows[i].err) != 0) {
fail();
};
};
};
i += 1;
};
};
export fn main() i32 = {
signalled = 1; lit_and_match();
signalled = 2; size_aliases_distinct();
@@ -2180,5 +2264,6 @@ export fn main() i32 = {
signalled = 40; fold5_find_cases();
signalled = 41; fold5_optional_group();
signalled = 42; fold5_submatches();
signalled = 43; parse_repetition_cases();
return 0;
};