]> Repositories - zlox.git/commitdiff
Refactor and add test
authorAyo Reis <hey@ayoreis.com>
Wed, 25 Feb 2026 18:45:23 +0000 (18:45 +0000)
committerAyo Reis <hey@ayoreis.com>
Wed, 25 Feb 2026 18:45:23 +0000 (18:45 +0000)
src/AstPrinter.zig [new file with mode: 0644]
src/ast_printer.zig [deleted file]

diff --git a/src/AstPrinter.zig b/src/AstPrinter.zig
new file mode 100644 (file)
index 0000000..c83d58b
--- /dev/null
@@ -0,0 +1,81 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const AstPrinter = @This();
+const Expr = @import("expr.zig").Expr;
+const Token = @import("Token.zig");
+
+allocator: Allocator,
+
+pub fn init(allocator: Allocator) AstPrinter {
+    return .{
+        .allocator = allocator,
+    };
+}
+
+pub fn print(self: *const AstPrinter, expr: *const Expr) Allocator.Error![]const u8 {
+    return switch (expr.*) {
+        .binary => |binary| visitBinaryExpr(self, binary),
+        .grouping => |grouping| visitGroupingExpr(self, grouping),
+        .literal => |literal| visitLiteralExpr(self, literal),
+        .unary => |unary| visitUnaryExpr(self, unary),
+    };
+}
+
+fn visitBinaryExpr(self: *const AstPrinter, expr: Expr.Binary) ![]const u8 {
+    return self.parenthesize(expr.operator.lexeme, &.{ expr.left, expr.right });
+}
+
+fn visitGroupingExpr(self: *const AstPrinter, expr: Expr.Grouping) ![]const u8 {
+    return self.parenthesize("group", &.{expr.expression});
+}
+
+fn visitLiteralExpr(self: *const AstPrinter, expr: Expr.Literal) ![]const u8 {
+    return switch (expr.value) {
+        .string => |string| self.allocator.dupe(u8, string),
+        .number => |number| std.fmt.allocPrint(self.allocator, "{}", .{number}),
+        .boolean => |boolean| std.fmt.allocPrint(self.allocator, "{}", .{boolean}),
+        .nil => self.allocator.dupe(u8, "nil"),
+    };
+}
+
+fn visitUnaryExpr(self: *const AstPrinter, expr: Expr.Unary) ![]const u8 {
+    return self.parenthesize(expr.operator.lexeme, &.{expr.right});
+}
+
+fn parenthesize(self: *const AstPrinter, name: []const u8, exprs: []const *const Expr) ![]const u8 {
+    var builder: std.ArrayList(u8) = .empty;
+
+    try builder.append(self.allocator, '(');
+    try builder.appendSlice(self.allocator, name);
+    for (exprs) |expr| {
+        try builder.append(self.allocator, ' ');
+        const printed = try print(self, expr);
+        defer self.allocator.free(printed);
+        try builder.appendSlice(self.allocator, printed);
+    }
+    try builder.append(self.allocator, ')');
+
+    return builder.toOwnedSlice(self.allocator);
+}
+
+test {
+    const allocator = std.testing.allocator;
+
+    const expression = Expr{
+        .binary = .init(
+            &.{ .unary = .init(
+                .init(.minus, "-", null, 1),
+                &.{ .literal = .init(.{ .number = 123 }) },
+            ) },
+            .init(.star, "*", null, 1),
+            &.{ .grouping = .init(
+                &.{ .literal = .init(.{ .number = 45.67 }) },
+            ) },
+        ),
+    };
+
+    const ast_printer = AstPrinter.init(allocator);
+    const printed = try ast_printer.print(&expression);
+    defer allocator.free(printed);
+    std.debug.print("{s}\n", .{printed});
+}
diff --git a/src/ast_printer.zig b/src/ast_printer.zig
deleted file mode 100644 (file)
index 2df8c8e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-const Expr = @import("expr.zig").Expr;
-const Token = @import("Token.zig");
-
-pub fn print(allocator: Allocator, expr: *const Expr) Allocator.Error![]const u8 {
-    return switch (expr.*) {
-        .binary => |binary| parenthesize(allocator, binary.operator.lexeme, &.{ binary.left, binary.right }),
-        .grouping => |grouping| parenthesize(allocator, "group", &.{grouping.expression}),
-        .literal => |literal| switch (literal.value) {
-            .string => |string| allocator.dupe(u8, string),
-            .number => |number| std.fmt.allocPrint(allocator, "{}", .{number}),
-            .boolean => |boolean| std.fmt.allocPrint(allocator, "{}", .{boolean}),
-            .nil => allocator.dupe(u8, "nil"),
-        },
-        .unary => |unary| parenthesize(allocator, unary.operator.lexeme, &.{unary.right}),
-    };
-}
-
-fn parenthesize(allocator: Allocator, name: []const u8, exprs: []const *const Expr) ![]const u8 {
-    var builder: std.ArrayList(u8) = .empty;
-
-    try builder.append(allocator, '(');
-    try builder.appendSlice(allocator, name);
-    for (exprs) |expr| {
-        try builder.append(allocator, ' ');
-        const printed = try print(allocator, expr);
-        defer allocator.free(printed);
-        try builder.appendSlice(allocator, printed);
-    }
-    try builder.append(allocator, ')');
-
-    return builder.toOwnedSlice(allocator);
-}