1 const std = @import("std");
2 const Allocator = std.mem.Allocator;
3 const Scanner = @import("Scanner.zig");
4 const Token = @import("Token.zig");
5 const Parser = @import("Parser.zig");
6 const ast_printer = @import("ast_printer.zig");
11 var gpa: std.heap.DebugAllocator(.{}) = .init;
12 defer _ = gpa.deinit();
13 const allocator = gpa.allocator();
14 const args = try std.process.argsAlloc(allocator);
15 defer std.process.argsFree(allocator, args);
18 var stdout_writer = std.fs.File.stdout().writer(&.{});
19 const stdout = &stdout_writer.interface;
20 try stdout.writeAll("Usage: zlox [script]\n");
22 } else if (args.len == 2) {
23 return runFile(allocator, args[1]);
25 try runPrompt(allocator);
31 fn runFile(allocator: Allocator, path: []const u8) !u8 {
32 const bytes = try std.fs.cwd().readFileAlloc(allocator, path, std.math.maxInt(usize));
33 defer allocator.free(bytes);
34 try run(allocator, bytes);
36 // Indicate an error in the exit code.
37 if (hadError) return 65;
42 fn runPrompt(allocator: Allocator) !void {
43 var stdin_buffer: [1024]u8 = undefined;
44 var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer);
45 const stdin = &stdin_reader.interface;
46 var stdout_writer = std.fs.File.stdout().writer(&.{});
47 const stdout = &stdout_writer.interface;
50 try stdout.writeAll("> ");
51 const line = try stdin.takeDelimiter('\n');
52 if (line == null) break;
53 try run(allocator, line.?);
58 fn run(allocator: Allocator, source: []const u8) !void {
59 var scanner = Scanner.init(allocator, source);
60 const tokens = try scanner.scanTokens();
61 defer allocator.free(tokens);
62 var parser = try Parser.init(allocator, tokens);
63 defer parser.deinit();
64 const expression = try parser.parse();
66 // Stop if there was a syntax error.
69 const printed = try ast_printer.print(allocator, expression.?);
70 defer allocator.free(printed);
71 std.debug.print("{s}\n", .{printed});
74 pub fn @"error"(line: u32, message: []const u8) !void {
75 try report(line, "", message);
78 var stderr_buffer: [1024]u8 = undefined;
79 var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
80 const stderr = &stderr_writer.interface;
82 fn report(line: u32, where: []const u8, message: []const u8) !void {
83 try stderr.print("[line {}] Error{s}: {s}\n", .{ line, where, message });
88 pub fn parse_error(allocator: Allocator, token: Token, message: []const u8) !void {
89 if (token.type == .eof) {
90 try report(token.line, " at end", message);
92 try report(token.line, try std.fmt.allocPrint(allocator, " at '{s}'", .{token.lexeme}), message);