1 const std = @import("std");
2 const Allocator = std.mem.Allocator;
3 const Scanner = @import("Scanner.zig");
8 var gpa: std.heap.DebugAllocator(.{}) = .init;
9 defer _ = gpa.deinit();
10 const allocator = gpa.allocator();
11 const args = try std.process.argsAlloc(allocator);
12 defer std.process.argsFree(allocator, args);
15 var stdout_writer = std.fs.File.stdout().writer(&.{});
16 const stdout = &stdout_writer.interface;
17 try stdout.writeAll("Usage: zlox [script]\n");
19 } else if (args.len == 2) {
20 return runFile(allocator, args[1]);
22 try runPrompt(allocator);
28 fn runFile(allocator: Allocator, path: []const u8) !u8 {
29 const bytes = try std.fs.cwd().readFileAlloc(allocator, path, std.math.maxInt(usize));
30 defer allocator.free(bytes);
31 try run(allocator, bytes);
33 // Indicate an error in the exit code.
34 if (hadError) return 65;
39 fn runPrompt(allocator: Allocator) !void {
40 var stdin_buffer: [1024]u8 = undefined;
41 var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer);
42 const stdin = &stdin_reader.interface;
43 var stdout_writer = std.fs.File.stdout().writer(&.{});
44 const stdout = &stdout_writer.interface;
47 try stdout.writeAll("> ");
48 const line = try stdin.takeDelimiter('\n');
49 if (line == null) break;
50 try run(allocator, line.?);
55 fn run(allocator: Allocator, source: []const u8) !void {
56 var scanner = Scanner.init(source);
57 const tokens = try scanner.scanTokens(allocator);
58 defer allocator.free(tokens);
60 // For now, just print the tokens.
61 for (tokens) |token| {
62 std.debug.print("{f}\n", .{token});
66 pub fn @"error"(line: u32, message: []const u8) !void {
67 try report(line, "", message);
70 var stderr_buffer: [1024]u8 = undefined;
71 var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
72 const stderr = &stderr_writer.interface;
74 fn report(line: u32, where: []const u8, message: []const u8) !void {
75 try stderr.print("[line {}] Error{s}: {s}\n", .{ line, where, message });