authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-07 14:22:17+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 15:48:03+02:00
logfe44dffa12470397146d079445ea4409961e734b
treefbedb4bc32ee973e06e2261db9ff33b5c1345587
parent5bafdbf9d8d8006cb1e3a7f3e69b059c58443489
signaturelock-open Commit is signed but in an unrecognized format.

grammar: eliminate ContainerField backtracking

For in depth reasoning, see commit 296b39c32324 (grammar: fix ParamDeclList worst-case exponential time)

2 files changed, 28 insertions(+), 36 deletions(-)

doc/langref/grammar.peg+4-3
......@@ -39,9 +39,10 @@
3939Root <- ContainerMembers skip eof
4040
4141# *** Top level ***
42ContainerMembers <- container_doc_comment? ContainerDecl* !ContainerDeclPrefix
43 (!ContainerDeclPrefix ContainerField COMMA)*
44 (!ContainerDeclPrefix ContainerField / ContainerDecl*)
42ContainerMembers <- container_doc_comment? ContainerDecl* ContainerMembersRest
43ContainerMembersRest
44 <- !ContainerDeclPrefix ContainerField (COMMA ContainerMembersRest)?
45 / ContainerDecl*
4546
4647ContainerDecl <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl
4748
lib/std/zig/parser_generated_oracle.zig+24-33
......@@ -16,6 +16,7 @@ pub fn parse(source: []const u8) Error!bool {
1616const Def = enum {
1717 defRoot,
1818 defContainerMembers,
19 defContainerMembersRest,
1920 defContainerDecl,
2021 defContainerDeclPrefix,
2122 defTestDecl,
......@@ -289,7 +290,7 @@ const Def = enum {
289290const Parser = struct {
290291 source: []const u8,
291292 i: usize,
292 depths: [271]u8,
293 depths: [272]u8,
293294 pub fn parseRoot(p: *Parser) Error!bool {
294295 const def_index = @intFromEnum(Def.defRoot);
295296 if (p.depths[def_index] > max_depth) return error.MaxDepth;
......@@ -316,47 +317,37 @@ const Parser = struct {
316317 i_1 += 1;
317318 }
318319 break :blk_1 true;
319 } and blk_1: {
320 } and try p.parseContainerMembersRest()) break :blk_0 true;
321 p.i = pos_0;
322 break :blk_0 false;
323 };
324 }
325 pub fn parseContainerMembersRest(p: *Parser) Error!bool {
326 const def_index = @intFromEnum(Def.defContainerMembersRest);
327 if (p.depths[def_index] > max_depth) return error.MaxDepth;
328 p.depths[def_index] += 1;
329 defer p.depths[def_index] -= 1;
330 return blk_0: {
331 const pos_0 = p.i;
332 if (blk_1: {
320333 const pos_1 = p.i;
321334 const match_1 = try p.parseContainerDeclPrefix();
322335 p.i = pos_1;
323336 break :blk_1 !match_1;
324 } and blk_1: {
337 } and try p.parseContainerField() and (blk_3: {
338 const pos_3 = p.i;
339 if (try p.parseCOMMA() and try p.parseContainerMembersRest()) break :blk_3 true;
340 p.i = pos_3;
341 break :blk_3 false;
342 } or true)) break :blk_0 true;
343 p.i = pos_0;
344 if (blk_1: {
325345 var i_1: usize = 0;
326 while (blk_3: {
327 const pos_3 = p.i;
328 if (blk_4: {
329 const pos_4 = p.i;
330 const match_4 = try p.parseContainerDeclPrefix();
331 p.i = pos_4;
332 break :blk_4 !match_4;
333 } and try p.parseContainerField() and try p.parseCOMMA()) break :blk_3 true;
334 p.i = pos_3;
335 break :blk_3 false;
336 }) {
346 while (try p.parseContainerDecl()) {
337347 if (i_1 > max_depth) return error.MaxDepth;
338348 i_1 += 1;
339349 }
340350 break :blk_1 true;
341 } and blk_2: {
342 const pos_2 = p.i;
343 if (blk_3: {
344 const pos_3 = p.i;
345 const match_3 = try p.parseContainerDeclPrefix();
346 p.i = pos_3;
347 break :blk_3 !match_3;
348 } and try p.parseContainerField()) break :blk_2 true;
349 p.i = pos_2;
350 if (blk_3: {
351 var i_3: usize = 0;
352 while (try p.parseContainerDecl()) {
353 if (i_3 > max_depth) return error.MaxDepth;
354 i_3 += 1;
355 }
356 break :blk_3 true;
357 }) break :blk_2 true;
358 p.i = pos_2;
359 break :blk_2 false;
360351 }) break :blk_0 true;
361352 p.i = pos_0;
362353 break :blk_0 false;