const std = @import("std"); const scanners = @import("scanner.zig"); const Allocator = std.mem.Allocator; pub const Result = error{ Ok, CompileError, }; fn run(allocator: *Allocator, data: []u8) !void { var stdout_file = try std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; var scanner = scanners.Scanner.init(allocator, data); while (true) { var tok_opt = scanner.nextToken() catch |err| { try stdout.print( "error at '{}': {}\n", scanner.currentLexeme(), err, ); return Result.CompileError; }; if (tok_opt) |tok| { if (tok.ttype == .EOF) break; try stdout.print("{x}\n", tok); } } return Result.Ok; } fn runFile(allocator: *Allocator, path: []const u8) !void { var file = try std.fs.File.openRead(path); defer file.close(); const total_bytes = try file.getEndPos(); var slice = try allocator.alloc(u8, total_bytes); _ = try file.read(slice); run(allocator, slice) catch |err| { switch (err) { Result.Ok => {}, Result.CompileError => std.os.exit(65), else => return err, } }; } fn runPrompt(allocator: *Allocator) !void { var stdout_file = try std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; while (true) { try stdout.print("> "); var buffer = try std.Buffer.init(allocator, ""[0..]); var line = std.io.readLine(&buffer) catch |err| { if (err == error.EndOfStream) return; return err; }; run(allocator, line) catch |err| { switch (err) { Result.Ok => {}, Result.CompileError => blk: { try stdout.print("compile error.\n"); }, else => return err, } }; } } pub fn main() anyerror!void { var da = std.heap.DirectAllocator.init(); var arena = std.heap.ArenaAllocator.init(&da.allocator); defer arena.deinit(); var allocator = &arena.allocator; var stdout_file = try std.io.getStdOut(); var stdout = &stdout_file.outStream().stream; var args_it = std.process.args(); _ = args_it.next(allocator); var filePath = try (args_it.next(allocator) orelse { try runPrompt(allocator); return; }); try runFile(allocator, filePath); }