diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-07-19 20:18:15 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-07-19 20:18:15 +0200 |
| commit | ae10b7d764d9587ab92a682781f8479107e8dff0 (patch) | |
| tree | 13e060f304ca1cac98ae1e71a2a6e27d9c5fb269 /src/argument.zig | |
| parent | d138a622dcc77302cc452c52946f6202b6a03f5e (diff) | |
add pex
Diffstat (limited to 'src/argument.zig')
| -rw-r--r-- | src/argument.zig | 341 |
1 files changed, 174 insertions, 167 deletions
diff --git a/src/argument.zig b/src/argument.zig index 7912397..81172fb 100644 --- a/src/argument.zig +++ b/src/argument.zig @@ -2,223 +2,230 @@ const std = @import("std"); pub const Grammar = @import("grammar.zig"); fn help(err: ?anyerror) noreturn { - const stderr = std.io.getStdErr().writer(); + const stderr = std.io.getStdErr().writer(); - if (err) |e| { - stderr.print("error: {s}\n", .{@errorName(e)}) catch unreachable; - } + if (err) |e| { + stderr.print("error: {s}\n", .{@errorName(e)}) catch unreachable; + } - stderr.writeAll( - \\mry [command] [options] - \\ - \\Commands: - \\ - \\ generate [grammar] [options] - \\ Options: - \\ -e, --entry label Name of the entry point. (default: main) - \\ - \\ -o, --output entry Output string to file - \\ By default stdout will be used. - \\ - \\ -c, --count n Number of texts to generate. (default: 1) - \\ - \\ -n, --non-empty Only output texts which are non-empty. - \\ - \\ -m, --min-length n Minimum length of sentential string. - \\ - \\ benchmark [grammar] [options] - \\ Options: - \\ -e, --entry label Name of the entry point. (default: main) - \\ - \\ -i, --input entry Specify input source, if the path - \\ points to a directory it will scan - \\ all files in it. By default stdin will - \\ be used as input. - \\ - \\General Options - \\ -h, --help Print usage - \\ - ) catch unreachable; - std.process.exit(@intFromBool(err != null)); + stderr.writeAll( + \\mry [command] [options] + \\ + \\Commands: + \\ + \\ generate [grammar] [options] + \\ Options: + \\ -e, --entry label Name of the entry point. (default: main) + \\ + \\ -o, --output entry Output string to file + \\ By default stdout will be used. + \\ + \\ -c, --count n Number of texts to generate. (default: 1) + \\ + \\ -n, --non-empty Only output texts which are non-empty. + \\ + \\ -m, --min-length n Minimum length of sentential string. + \\ + \\ benchmark [grammar] [options] + \\ Options: + \\ -e, --entry label Name of the entry point. (default: main) + \\ + \\ -i, --input entry Specify input source, if the path + \\ points to a directory it will scan + \\ all files in it. By default stdin will + \\ be used as input. + \\ + \\ --csv output in CSV format. + \\ + \\General Options + \\ -h, --help Print usage + \\ + ) catch unreachable; + std.process.exit(@intFromBool(err != null)); } fn check(arg_or_null: ?[]const u8) []const u8 { - const arg = arg_or_null orelse help(error.MissingArgument); + const arg = arg_or_null orelse help(error.MissingArgument); - if (std.mem.eql(u8, arg, "-h") or std.mem.eql(u8, arg, "--help")) { - help(null); - } - return arg; + if (std.mem.eql(u8, arg, "-h") or std.mem.eql(u8, arg, "--help")) { + help(null); + } + return arg; } fn parse_enum(T: type, arg: []const u8) T { - return std.meta.stringToEnum(T, arg) orelse help(error.InvalidArgument); + return std.meta.stringToEnum(T, arg) orelse help(error.InvalidArgument); } fn parse_int(n: []const u8) usize { - return std.fmt.parseInt(usize, n, 10) catch |e| help(e); + return std.fmt.parseInt(usize, n, 10) catch |e| help(e); } fn check_flags(arg: []const u8, comptime flags: []const []const u8) bool { - inline for (flags) |flag| { - if (std.mem.eql(u8, arg, flag)) { - return true; - } - } + inline for (flags) |flag| { + if (std.mem.eql(u8, arg, flag)) { + return true; + } + } - return false; + return false; } pub const Mode = enum { - benchmark, - generate, + benchmark, + generate, }; pub const Entry = struct { - const Self = @This(); + const Self = @This(); - name: []const u8, - file: std.fs.File, + name: []const u8, + file: std.fs.File, - pub fn open(path: []const u8, writer: bool) Self { - var cwd = std.fs.cwd(); + pub fn open(path: []const u8, writer: bool) Self { + var cwd = std.fs.cwd(); - return Self { - .name = path, - .file = (if (writer) cwd.createFile(path, .{}) - else cwd.openFile(path, .{})) catch |e| help(e) - }; - } + return Self { + .name = path, + .file = (if (writer) cwd.createFile(path, .{}) + else cwd.openFile(path, .{})) catch |e| help(e) + }; + } - pub fn read_file(path: []const u8, allocator: std.mem.Allocator) []const u8 { - var cwd = std.fs.cwd(); + pub fn read_file(path: []const u8, allocator: std.mem.Allocator) []const u8 { + var cwd = std.fs.cwd(); - var file = cwd.openFile(path, .{}) catch |e| help(e); - defer file.close(); - const stat = file.stat() catch |e| help(e); + var file = cwd.openFile(path, .{}) catch |e| help(e); + defer file.close(); + const stat = file.stat() catch |e| help(e); - return file.readToEndAlloc(allocator, stat.size) catch |e| help(e); - } + return file.readToEndAlloc(allocator, stat.size) catch |e| help(e); + } - pub fn stdin() Self { - return Self { - .name = "[stdin]", - .file = std.io.getStdIn(), - }; - } + pub fn stdin() Self { + return Self { + .name = "[stdin]", + .file = std.io.getStdIn(), + }; + } - pub fn stdout() Self { - return Self { - .name = "[stdout]", - .file = std.io.getStdOut(), - }; - } + pub fn stdout() Self { + return Self { + .name = "[stdout]", + .file = std.io.getStdOut(), + }; + } }; pub const BenchmarkArgs = struct { - input: Entry, - grammar: Grammar, - entry: []const u8, + input: Entry, + grammar: Grammar, + entry: []const u8, + csv: bool, }; pub const GenerateArgs = struct { - count: usize, - min_length: usize, - output: Entry, - grammar: Grammar, - entry: []const u8, + count: usize, + min_length: usize, + output: Entry, + grammar: Grammar, + entry: []const u8, }; pub const Args = union(Mode) { - const Self = @This(); + const Self = @This(); - benchmark: BenchmarkArgs, - generate: GenerateArgs, + benchmark: BenchmarkArgs, + generate: GenerateArgs, - pub fn parse(allocator: std.mem.Allocator) Self { - var args = std.process.args(); - _ = args.next(); + pub fn parse(allocator: std.mem.Allocator) Self { + var args = std.process.args(); + _ = args.next(); - const mode = parse_enum(Mode, check(args.next())); + const mode = parse_enum(Mode, check(args.next())); - const text = Entry.read_file(check(args.next()), allocator); - defer allocator.free(text); + const text = Entry.read_file(check(args.next()), allocator); + defer allocator.free(text); - switch (mode) { - .benchmark => { - var input: ?Entry = null; - var entry: []const u8 = "main"; + switch (mode) { + .benchmark => { + var input: ?Entry = null; + var entry: []const u8 = "main"; + var csv = false; - while (args.next()) |arg| { - if (check_flags(arg, &[_][]const u8 { "-i", "--input" })) { - input = Entry.open(check(args.next()), false); - } else if (check_flags(arg, &[_][]const u8 { "-e", "--entry" })) { - entry = check(args.next()); - } else help(error.InvalidArgument); - } + while (args.next()) |arg| { + if (check_flags(arg, &[_][]const u8 { "-i", "--input" })) { + input = Entry.open(check(args.next()), false); + } else if (check_flags(arg, &[_][]const u8 { "-e", "--entry" })) { + entry = check(args.next()); + } else if (check_flags(arg, &[_][]const u8 { "--csv" })) { + csv = true; + } else help(error.InvalidArgument); + } - const grammar = Grammar.parse( - entry, - text, - allocator - ) catch |e| help(e); + const grammar = Grammar.parse( + entry, + text, + allocator + ) catch |e| help(e); - return Self { - .benchmark = .{ - .input = input orelse Entry.stdin(), - .grammar = grammar, - .entry = entry, - }, - }; - }, + return Self { + .benchmark = .{ + .input = input orelse Entry.stdin(), + .grammar = grammar, + .entry = entry, + .csv = csv, + }, + }; + }, - .generate => { - var count: usize = 1; - var output: ?Entry = null; - var min_length: usize = 0; - var entry: []const u8 = "main"; + .generate => { + var count: usize = 1; + var output: ?Entry = null; + var min_length: usize = 0; + var entry: []const u8 = "main"; - while (args.next()) |arg| { - if (check_flags(arg, &[_][]const u8 { "-o", "--output" })) { - output = Entry.open(check(args.next()), true); - } else if (check_flags(arg, &[_][]const u8 { "-c", "--count" })) { - count = parse_int(check(args.next())); - } else if (check_flags(arg, &[_][]const u8 { "-n", "--non-empty" })) { - min_length = 1; - } else if (check_flags(arg, &[_][]const u8 { "-m", "--min-length" })) { - min_length = parse_int(check(args.next())); - } else if (check_flags(arg, &[_][]const u8 { "-e", "--entry" })) { - entry = check(args.next()); - } else help(error.InvalidArgument); - } + while (args.next()) |arg| { + if (check_flags(arg, &[_][]const u8 { "-o", "--output" })) { + output = Entry.open(check(args.next()), true); + } else if (check_flags(arg, &[_][]const u8 { "-c", "--count" })) { + count = parse_int(check(args.next())); + } else if (check_flags(arg, &[_][]const u8 { "-n", "--non-empty" })) { + min_length = 1; + } else if (check_flags(arg, &[_][]const u8 { "-m", "--min-length" })) { + min_length = parse_int(check(args.next())); + } else if (check_flags(arg, &[_][]const u8 { "-e", "--entry" })) { + entry = check(args.next()); + } else help(error.InvalidArgument); + } - const grammar = Grammar.parse( - entry, - text, - allocator - ) catch |e| help(e); + const grammar = Grammar.parse( + entry, + text, + allocator + ) catch |e| help(e); - return Self { - .generate = .{ - .count = count, - .min_length = min_length, - .output = output orelse Entry.stdout(), - .grammar = grammar, - .entry = entry, - }, - }; - }, - } - } + return Self { + .generate = .{ + .count = count, + .min_length = min_length, + .output = output orelse Entry.stdout(), + .grammar = grammar, + .entry = entry, + }, + }; + }, + } + } - pub fn deinit(self: *Self) void { - switch (self.*) { - .benchmark => |*rec| { - rec.grammar.deinit(); - }, - .generate => |*gen| { - gen.grammar.deinit(); - } - } - } + pub fn deinit(self: *Self) void { + switch (self.*) { + .benchmark => |*rec| { + rec.grammar.deinit(); + }, + .generate => |*gen| { + gen.grammar.deinit(); + } + } + } }; |