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);
32 // Indicate an error in the exit code.
33 if (hadError) return 65;
37 fn runPrompt(allocator: Allocator) !void {
38 var stdin_buffer: [1024]u8 = undefined;
39 var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer);
40 const stdin = &stdin_reader.interface;
41 var stdout_writer = std.fs.File.stdout().writer(&.{});
42 const stdout = &stdout_writer.interface;
45 try stdout.writeAll("> ");
46 const line = try stdin.takeDelimiter('\n');
47 if (line == null) break;
48 try run(allocator, line.?);
53 fn run(allocator: Allocator, source: []const u8) !void {
54 var scanner = Scanner.init(source);
55 const tokens = try scanner.scanTokens(allocator);
56 defer allocator.free(tokens);
58 // For now, just print the tokens.
59 for (tokens) |token| {
60 std.debug.print("{f}\n", .{token});
64 pub fn @"error"(line: u32, message: []const u8) !void {
65 try report(line, "", message);
68 var stderr_buffer: [1024]u8 = undefined;
69 var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
70 const stderr = &stderr_writer.interface;
72 fn report(line: u32, where: []const u8, message: []const u8) !void {
73 try stderr.print("[line {}] Error{s}: {s}\n", .{ line, where, message });