authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 11:24:15+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 15:49:43+02:00
logb2c3c33eef468634a2fc47b19bfb2e6f51a1a9b4
tree9fa9992724acfd1a460e5cbd853af95d6528a5c5
parent06b1896a619d13a8b3471dc119d2076f04f85b93
signaturelock-open Commit is signed but in an unrecognized format.

build: check if parser oracle must be regenerated


2 files changed, 37 insertions(+), 12 deletions(-)

build.zig+15-6
......@@ -720,18 +720,27 @@ pub fn build(b: *std.Build) !void {
720720 check_mingw_step.dependOn(&check_mingw_run.step);
721721
722722 {
723 const gpo_step = b.step("gen-parser-oracle", "Regenerate lib/std/zig/parser_generated_oracle.zig from doc/langref/grammar.peg");
724 const gpo_exe = b.addExecutable(.{
723 const gen_oracle_exe = b.addExecutable(.{
725724 .name = "gen_parser_oracle",
726725 .root_module = b.createModule(.{
727726 .root_source_file = b.path("tools/gen_parser_oracle.zig"),
728727 .target = b.graph.host,
729728 }),
730729 });
731 const gpo_run = b.addRunArtifact(gpo_exe);
732 gpo_run.addFileArg(b.path("doc/langref/grammar.peg"));
733 gpo_run.addFileArg(b.path("lib/std/zig/parser_generated_oracle.zig"));
734 gpo_step.dependOn(&gpo_run.step);
730
731 const gen_oracle_step = b.step("gen-parser-oracle", "Regenerate lib/std/zig/parser_generated_oracle.zig from doc/langref/grammar.peg");
732 const gen_oracle_run = b.addRunArtifact(gen_oracle_exe);
733 gen_oracle_run.addFileArg(b.path("doc/langref/grammar.peg"));
734 gen_oracle_run.addFileArg(b.path("lib/std/zig/parser_generated_oracle.zig"));
735 gen_oracle_step.dependOn(&gen_oracle_run.step);
736
737 const check_oracle_step = b.step("check-parser-oracle", "Check if doc/langref/grammar.peg was modified without regenerating the oracle");
738 const check_oracle_run = b.addRunArtifact(gen_oracle_exe);
739 check_oracle_run.addFileArg(b.path("doc/langref/grammar.peg"));
740 check_oracle_run.addFileArg(b.path("lib/std/zig/parser_generated_oracle.zig"));
741 check_oracle_run.addArg("--check");
742 check_oracle_step.dependOn(&check_oracle_run.step);
743 test_step.dependOn(check_oracle_step);
735744 }
736745
737746 const test_incremental_step = b.step("test-incremental", "Run the incremental compilation test cases");
tools/gen_parser_oracle.zig+22-6
......@@ -1,5 +1,6 @@
11//! Example usage:
22//! zig build gen-parser-oracle
3//! zig build check-parser-oracle
34
45// This program implements a subset of the PEG grammar definition
56// in the peg(1) man page.
......@@ -22,6 +23,7 @@ pub fn main(init: std.process.Init) !void {
2223
2324 const grammar_path = args[1];
2425 const out_path = args[2];
26 const check = args.len > 3 and mem.eql(u8, args[3], "--check");
2527
2628 const grammar = try Io.Dir.cwd().readFileAlloc(io, grammar_path, gpa, .unlimited);
2729 defer gpa.free(grammar);
......@@ -53,13 +55,27 @@ pub fn main(init: std.process.Init) !void {
5355 return error.ParseError;
5456 }
5557
56 var out_file = try Io.Dir.cwd().createFile(io, out_path, .{});
57 var out_buffer: [4096]u8 = undefined;
58 var out_writer = out_file.writer(io, &out_buffer);
59 const out = &out_writer.interface;
58 if (check) {
59 const current = try Io.Dir.cwd().readFileAlloc(io, out_path, gpa, .unlimited);
60 defer gpa.free(current);
61 var aw: Io.Writer.Allocating = .init(gpa);
62 defer aw.deinit();
63 try tree.render(gpa, &aw.writer, .{});
64 if (!mem.eql(u8, current, aw.written())) {
65 std.log.err("grammar.peg modified without regenerating oracle", .{});
66 std.log.info("Run zig build gen-parser-oracle to regenerate", .{});
67 std.process.exit(1);
68 }
69 } else {
70 var out_file = try Io.Dir.cwd().createFile(io, out_path, .{});
71 defer out_file.close(io);
72 var out_buffer: [4096]u8 = undefined;
73 var out_writer = out_file.writer(io, &out_buffer);
74 const out = &out_writer.interface;
6075
61 try tree.render(gpa, out, .{});
62 try out.flush();
76 try tree.render(gpa, out, .{});
77 try out.flush();
78 }
6379}
6480
6581const Generator = struct {