aboutsummaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig125
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 {