Skip to content

Instantly share code, notes, and snippets.

@oatberry
Created May 3, 2020 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oatberry/fc89cba8e3bdbeaf9e474949f838cc7a to your computer and use it in GitHub Desktop.
Save oatberry/fc89cba8e3bdbeaf9e474949f838cc7a to your computer and use it in GitHub Desktop.
const std = @import("std");
pub const Expr = union(enum) {
Literal: union(enum) {
Number: f64,
String: []const u8,
True,
False,
Nil,
},
Unary: union(enum) {
Negative: *Expr,
Not: *Expr,
},
Binary: struct {
l_expr: *Expr,
r_expr: *Expr,
operator: Operator,
},
Grouping: *Expr,
pub fn number(n: f64) Expr {
return .{ .Literal = .{ .Number = n } };
}
pub fn string(str: []const u8) Expr {
return .{ .Literal = .{ .String = str } };
}
pub const True: Expr = .{ .Literal = .True };
pub const False: Expr = .{ .Literal = .False };
pub const Nil: Expr = .{ .Literal = .Nil };
pub fn negative(expr: *Expr) Expr {
return .{ .Unary = .{ .Negative = expr } };
}
pub fn not(expr: *Expr) Expr {
return .{ .Unary = .{ .Not = expr } };
}
pub fn binary(operator: Operator, l_expr: *Expr, r_expr: *Expr) Expr {
return .{ .Binary = .{ .l_expr = l_expr, .r_expr = r_expr, .operator = operator } };
}
pub fn grouping(expr: *Expr) Expr {
return .{ .Grouping = expr };
}
pub fn format(
self: Expr,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
out_stream: var,
) !void {
const f = std.fmt.format;
return switch (self) {
.Literal => |literal| switch (literal) {
.Number => |n| f(out_stream, "{}", .{n}),
.String => |s| f(out_stream, "{}", .{s}),
.True => f(out_stream, "true", .{}),
.False => f(out_stream, "false", .{}),
.Nil => f(out_stream, "nil", .{}),
},
.Unary => |unary| switch (unary) {
.Negative => |expr| f(out_stream, "(- {})", .{expr}),
.Not => |expr| f(out_stream, "(! {})", .{expr}),
},
.Binary => |binary| f(out_stream, "({} {} {})", .{ switch (binary.operator) {
.Equal => "==",
.NotEqual => "!=",
.LessThan => "<",
.LessThanEqual => "<=",
.GreaterThan => ">",
.GreaterThanEqual => ">=",
.Plus => "+",
.Minus => "-",
.Multiply => "*",
.Divide => "/",
}, binary.l_expr, binary.r_expr }),
else => {},
};
}
};
const Operator = enum {
Equal,
NotEqual,
LessThan,
LessThanEqual,
GreaterThan,
GreaterThanEqual,
Plus,
Minus,
Multiply,
Divide,
};
test "expr" {
const warn = std.debug.warn;
warn("\n{}\n", .{Expr.True});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment