return result;
}
- pub fn clone(self: Expression, allocator: Allocator) error{OutOfMemory}!Expression {
+ pub fn clone(
+ self: Expression,
+ allocator: Allocator,
+ ) error{OutOfMemory}!Expression {
const result = Expression{
.quote = self.quote,
.tag = switch (self.tag) {
.nil, .t, .integer, .float => self.tag,
-
.string => |string| .{
.string = try allocator.dupe(u8, string),
},
-
.keyword => |keyword| .{
.keyword = try allocator.dupe(u8, keyword),
},
-
.symbol => |symbol| .{
.symbol = try allocator.dupe(u8, symbol),
},
-
.list => |list| .{
.list = try cloneExpressionList(list, allocator),
},
-
.funcall => |funcall| .{
.funcall = try cloneExpressionList(funcall, allocator),
},
alloc: Allocator,
quote: ?QuoteTag,
) ParseError!Expression {
- var result = Expression{
- .tag = undefined,
- };
-
+ var result = Expression{ .tag = undefined };
const token = tokenizer.peek();
const token_value = tokenizer.tokenValue(token);
+
switch (token.tag) {
.eof => return error.EndOfFile,
.quote => {
_ = tokenizer.next();
- const expr = Expression.parse(
- tokenizer,
- alloc,
- quote orelse .quote,
- ) catch |err| switch (err) {
- error.EndOfFile => {
- log.warn("Unexpected end of file after '", .{});
- return error.IncompleteExpression;
- },
- else => return err,
+ const expr = Expression.parse(tokenizer, alloc, quote orelse .quote) catch |err| {
+ switch (err) {
+ error.EndOfFile => {
+ log.warn("Unexpected end of file after '", .{});
+ return error.IncompleteExpression;
+ },
+ else => return err,
+ }
};
const quoted = try alloc.create(Expression);
quoted.* = expr;
.backquote => {
_ = tokenizer.next();
- const expr = Expression.parse(
- tokenizer,
- alloc,
- quote orelse .backquote,
- ) catch |err| switch (err) {
- error.EndOfFile => {
- log.warn("Unexpected end of file after `", .{});
- return error.IncompleteExpression;
- },
- else => return err,
+ const expr = Expression.parse(tokenizer, alloc, quote orelse .backquote) catch |err| {
+ switch (err) {
+ error.EndOfFile => {
+ log.warn("Unexpected end of file after `", .{});
+ return error.IncompleteExpression;
+ },
+ else => return err,
+ }
};
const quoted = try alloc.create(Expression);
quoted.* = expr;
.comma => {
_ = tokenizer.next();
- const next_quote: ?QuoteTag = if (quote) |q| switch (q) {
- .backquote => null,
- .quote => .quote,
- } else null;
- const expr = Expression.parse(
- tokenizer,
- alloc,
- next_quote,
- ) catch |err| switch (err) {
- error.EndOfFile => {
- log.warn("Unexpected end of file after ,", .{});
- return error.IncompleteExpression;
- },
- else => return err,
+ const next_quote: ?QuoteTag =
+ if (quote) |q|
+ switch (q) {
+ .backquote => null,
+ .quote => .quote,
+ }
+ else
+ null;
+ const expr = Expression.parse(tokenizer, alloc, next_quote) catch |err| {
+ switch (err) {
+ error.EndOfFile => {
+ log.warn("Unexpected end of file after ,", .{});
+ return error.IncompleteExpression;
+ },
+ else => return err,
+ }
};
result = .{
.tag = expr.tag,
.integer => {
_ = tokenizer.next();
- const value = std.fmt.parseInt(i64, token_value, 10) catch |err| switch (err) {
- error.Overflow => {
- log.debug("Input number `{s}` is too large", .{token_value});
- return error.InvalidToken;
- },
- // tokenizer should have handled this case
- error.InvalidCharacter => unreachable,
+ const value = std.fmt.parseInt(i64, token_value, 10) catch |err| {
+ switch (err) {
+ error.Overflow => {
+ log.debug("Input number `{s}` is too large", .{token_value});
+ return error.InvalidToken;
+ },
+ // tokenizer should have handled this case
+ error.InvalidCharacter => unreachable,
+ }
};
result.tag = .{ .integer = value };
},
.float => {
_ = tokenizer.next();
- const value = std.fmt.parseFloat(f64, token_value) catch |err| switch (err) {
- // tokenizer should have handled this case
- error.InvalidCharacter => unreachable,
+ const value = std.fmt.parseFloat(f64, token_value) catch |err| {
+ switch (err) {
+ // tokenizer should have handled this case
+ error.InvalidCharacter => unreachable,
+ }
};
result.tag = .{ .float = value };
},
.identifier => {
_ = tokenizer.next();
const value = token_value;
- result.tag = if (std.mem.eql(u8, value, "nil"))
- .nil
- else if (std.mem.eql(u8, value, "t"))
- .t
- else
- .{ .symbol = value };
+ result.tag =
+ if (std.mem.eql(u8, value, "nil"))
+ .nil
+ else if (std.mem.eql(u8, value, "t"))
+ .t
+ else
+ .{ .symbol = value };
},
.l_paren => {
.{ .funcall = list };
break;
}
+
if (Expression.parse(tokenizer, alloc, quote)) |expr| {
const elem = try alloc.create(Expression);
elem.* = expr;
}
},
- .r_paren => return error.UnmatchedParenthesis,
+ .r_paren => {
+ return error.UnmatchedParenthesis;
+ },
else => {
_ = tokenizer.next();
}
switch (self.tag) {
- .nil => try writer.print("nil", .{}),
- .t => try writer.print("t", .{}),
- .integer => |value| try writer.print("{}", .{value}),
- .float => |value| try writer.print("{}", .{value}),
- .string => |value| try writer.print("\"{s}\"", .{value}),
- .keyword, .symbol => |value| try writer.print("{s}", .{value}),
+ .nil => {
+ try writer.print("nil", .{});
+ },
+ .t => {
+ try writer.print("t", .{});
+ },
+ .integer => |value| {
+ try writer.print("{}", .{value});
+ },
+ .float => |value| {
+ try writer.print("{}", .{value});
+ },
+ .string => |value| {
+ try writer.print("\"{s}\"", .{value});
+ },
+ .keyword, .symbol => |value| {
+ try writer.print("{s}", .{value});
+ },
.list, .funcall => |list| {
try writer.print("(", .{});
var it = list.first;
+
while (it) |node| : (it = node.next) {
const elem: *Expression = @fieldParentPtr("node", node);
+
try writer.print("{f}", .{elem.*});
if (node.next != null) {
try writer.print(" ", .{});
}
try writer.print(")", .{});
},
- .quoted => |value| try writer.print("{f}", .{value.*}),
+ .quoted => |value| {
+ try writer.print("{f}", .{value.*});
+ },
}
}
pub fn deinit(self: Expression, allocator: Allocator) void {
switch (self.tag) {
.nil, .t, .integer, .float => {},
- .string, .keyword, .symbol => |string| allocator.free(string),
- .list, .funcall => |list| deinitExpressionList(list, allocator),
+ .string, .keyword, .symbol => |string| {
+ allocator.free(string);
+ },
+ .list, .funcall => |list| {
+ deinitExpressionList(list, allocator);
+ },
.quoted => |quoted| {
quoted.*.deinit(allocator);
allocator.destroy(quoted);