const std = @import("std"); const scanner = @import("scanner.zig"); const expr = @import("expr.zig"); const parser = @import("parser.zig"); const err = @import("error.zig"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); const args = try std.process.argsAlloc(allocator); defer std.process.argsFree(allocator, args); if (args.len > 2) { std.debug.print("Usage: zloxi [script].", .{}); std.process.exit(64); } else if (args.len == 2) { try runFile(allocator, args[1]); if (err.hasError) { std.process.exit(65); } } else { try runPrompt(allocator); } } fn runFile(alloc: std.mem.Allocator, file_name: []u8) !void { var bytes = try std.fs.cwd().readFileAlloc(alloc, file_name, 1_000_000); defer alloc.free(bytes); try run(alloc, bytes); } fn runPrompt(alloc: std.mem.Allocator) !void { const stdout_file = std.io.getStdOut().writer(); const stdin_file = std.io.getStdIn().reader(); var bw = std.io.bufferedWriter(stdout_file); const stdout = bw.writer(); while (true) { try stdout.print("> ", .{}); try bw.flush(); const line = try stdin_file.readUntilDelimiterOrEofAlloc(alloc, '\n', 1000); if (line == null) { try stdout.print("\n", .{}); break; } defer alloc.free(line.?); try run(alloc, line.?); err.hasError = false; } try bw.flush(); // don't forget to flush! } fn run(allocator: std.mem.Allocator, bytes: []u8) !void { var scan = scanner.Scanner.init(allocator, bytes); defer scan.deinit(); var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); var alloc = arena.allocator(); var parse = parser.Parser{ .tokens = scan.scanTokens(), .allocator = alloc, }; const expression = parse.parse(); if (err.hasError) { return; } expr.AstPrint(expression); std.debug.print("\n", .{}); }