1 const std = @import("std");
2 const Allocator = std.mem.Allocator;
3 const Expr = @import("expr.zig").Expr;
4 const Token = @import("Token.zig");
6 pub fn print(allocator: Allocator, expr: *const Expr) Allocator.Error![]const u8 {
7 return switch (expr.*) {
8 .binary => |binary| try parenthesize(allocator, binary.operator.lexeme, &.{ binary.left, binary.right }),
9 .grouping => |grouping| try parenthesize(allocator, "group", &.{grouping.expression}),
10 .literal => |literal| switch (literal.value) {
11 .nil => try allocator.dupe(u8, "nil"),
12 .boolean => |boolean| try std.fmt.allocPrint(allocator, "{}", .{boolean}),
13 .string => |string| try allocator.dupe(u8, string),
14 .number => |number| try std.fmt.allocPrint(allocator, "{}", .{number}),
16 .unary => |unary| try parenthesize(allocator, unary.operator.lexeme, &.{unary.right}),
20 fn parenthesize(allocator: Allocator, name: []const u8, exprs: []const *const Expr) ![]const u8 {
21 var builder: std.ArrayList(u8) = .empty;
23 try builder.append(allocator, '(');
24 try builder.appendSlice(allocator, name);
26 try builder.append(allocator, ' ');
27 const printed = try print(allocator, expr);
28 defer allocator.free(printed);
29 try builder.appendSlice(allocator, printed);
31 try builder.append(allocator, ')');
33 return try builder.toOwnedSlice(allocator);