diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 19:01:38 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 8ce3e3c62a22d0e70df4f241ff28de6f6cae78d3 (patch) | |
| tree | f7fb503b298cf82966ae9938a4d065cfea3a96d6 /src | |
| parent | 8948c9ec1b8ade3d1e4ed7103fd4f6d17a8ea23e (diff) | |
| download | pardes-8ce3e3c62a22d0e70df4f241ff28de6f6cae78d3.tar.gz pardes-8ce3e3c62a22d0e70df4f241ff28de6f6cae78d3.zip | |
An Edit with an unclosed { is refused, not run
Edit ,x/area_of/{ answered ok and did nothing: the group ran out of text and ran what it had. sam reads on for the }; an Edit has nothing more to read, so it now fails with unmatched `{', in the words sam uses for the other side.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/sam_edit.zig | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/src/sam_edit.zig b/src/sam_edit.zig index 40221628..e8e90b67 100644 --- a/src/sam_edit.zig +++ b/src/sam_edit.zig @@ -95,6 +95,8 @@ const Parser = struct { i: usize = 0, /// The last pattern given, for an empty one (edit.c:562, getregexp). lastpat: []const u8 = "", + /// The last `parse` that answered null met a `}`, not the end. + braced: bool = false, why: *Why, fn getch(ps: *Parser) ?u8 { @@ -326,12 +328,18 @@ const Parser = struct { var last: ?*Cmd = null; while (true) { if (ps.skipbl() == '\n') ps.i += 1; - const next = (try ps.parse(nest + 1)) orelse break; + ps.braced = false; + const next = (try ps.parse(nest + 1)) orelse { + // sam reads on for the `}`; an Edit has no more to read. + if (!ps.braced) return fail(ps.why, "unmatched `{{'", .{}); + break; + }; if (last) |l| l.next = next else cmd.sub = next; last = next; } }, '}' => { + ps.braced = true; try ps.atnl(); if (nest == 0) return fail(ps.why, "right brace with no left brace", .{}); return null; @@ -655,6 +663,8 @@ test "an Edit that fails halfway changes nothing, and says why in acme's words" .{ "k", "unknown command k" }, .{ ",x/a/{\na/1/\ni/2/\n}", "changes out of sequence" }, .{ "}", "right brace with no left brace" }, + .{ ",x/foo/{", "unmatched `{'" }, + .{ ",x/foo/{\nd", "unmatched `{'" }, .{ "w /tmp/x", "w is not supported in pardes" }, .{ ",s/(a)/\\1/", "no \\1: mvzr keeps no submatches" }, .{ "1 m 1,2", "move overlaps itself" }, |
