diff options
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 125 |
1 files changed, 104 insertions, 21 deletions
diff --git a/src/main.zig b/src/main.zig index 7a0513e..4dec1f1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,18 +1,107 @@ const std = @import("std"); pub const Grammar = @import("grammar.zig"); +pub const gss = @import("gss.zig"); pub const recognizer = @import("recognizer.zig"); +pub const argument = @import("argument.zig"); +pub const Generator = @import("generator.zig").Generator; -fn help() !noreturn { - const stderr = std.io.getStdErr().writer(); - try stderr.print("gll [grammar] [input]\n", .{}); - std.process.exit(1); +const Args = argument.Args; +const RecognizeArgs = argument.RecognizeArgs; +const GenerateArgs = argument.GenerateArgs; + +fn write_result( + writer: anytype, + is_tty: bool, + name: []const u8, + index: usize, + input: []const u8, + accepted: bool, +) !void { + if (is_tty) { + try writer.print("{s}[{}] {s}\x1b[0m: \"\x1b[3m{s}\x1b[0m\"\n", .{ + name, + index, + if (accepted) "\x1b[32maccept" + else "\x1b[31mreject", + input, + }); + } else { + try writer.print("{s}[{}] {s}: \"{s}\"\n", .{ + name, + index, + if (accepted) "accept" + else "reject", + input, + }); + } } -fn read_whole_file(path: []const u8, allocator: std.mem.Allocator) ![]const u8 { - const file = try std.fs.cwd().openFile(path, .{}); - defer file.close(); - const stat = try file.stat(); - return file.readToEndAlloc(allocator, stat.size); +fn recognize(args: *RecognizeArgs, allocator: std.mem.Allocator) !void { + const stdout = std.io.getStdOut(); + const writer = std.io.getStdOut().writer(); + + var reader = args.input.file.reader(); + var index: usize = 0; + const stderr = std.io.getStdErr(); + + if (args.input.file.isTty()) { + try stderr.writeAll("> "); + } + + var read_arena = std.heap.ArenaAllocator.init(allocator); + defer read_arena.deinit(); + + while (try reader.readUntilDelimiterOrEofAlloc( + read_arena.allocator(), + '\n', + std.math.maxInt(usize) + )) |buffer| { + + const trimmed = std.mem.trim(u8, buffer, &std.ascii.whitespace); + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + + try write_result( + writer, + stdout.isTty(), + args.input.name, + index, + trimmed, + try recognizer.check( + &args.grammar, + trimmed, + arena.allocator() + )); + + index += 1; + + if (args.input.file.isTty()) { + try stderr.writeAll("> "); + } + } +} + +fn generate(args: *GenerateArgs, allocator: std.mem.Allocator) !void { + var writer = args.output.file.writer(); + var count: usize = 0; + + var generator = Generator(struct { + const Self = @This(); + + pub fn next(_: *Self, n: usize) usize { + return std.crypto.random.uintLessThan(usize, n); + } + }){}; + + while (count < args.count) { + const text = try generator.sentential_from_grammar(&args.grammar, 1000, allocator); + defer allocator.free(text); + + if (args.empty or text.len > 0) { + try writer.print("{s}\n", .{text}); + count += 1; + } + } } pub fn main() !void { @@ -23,20 +112,14 @@ pub fn main() !void { @panic("memory leak detected"); } } - - var args = std.process.args(); - _ = args.next(); - - const grammar_path = args.next() orelse try help(); - const input_path = args.next() orelse try help(); - const grammar_text = try read_whole_file(grammar_path, allocator); - defer allocator.free(grammar_text); - const input = try read_whole_file(input_path, allocator); - defer allocator.free(input); + var arguments = Args.parse(allocator); + defer arguments.deinit(allocator); - var grammar = try Grammar.parse(grammar_text, allocator); - defer grammar.deinit(allocator); + try switch(arguments) { + .recognize => |*args| recognize(args, allocator), + .generate => |*args| generate(args, allocator), + }; } test { |