diff --git a/build.zig b/build.zig index ee624d8..0a6a141 100644 --- a/build.zig +++ b/build.zig @@ -81,6 +81,7 @@ pub fn build(b: *std.Build) void { .{ .name = "zdt_prov", .module = mod }, }, }), + .use_llvm = true, }); // This declares intent for the executable to be installed into the diff --git a/src/parser.zig b/src/parser.zig index 4d884e1..7332b9e 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -236,6 +236,7 @@ pub const Node = struct { .tag => if (self.tag) |t| { allocator.free(t.name); allocator.free(t.args); + allocator.free(t.raw); }, .if_block => if (self.@"if") |ib| { allocator.free(ib.condition); @@ -245,6 +246,8 @@ pub const Node = struct { const false_copy = ib.false_body; for (false_copy) |n| n.deinit(allocator); allocator.free(ib.false_body); + allocator.free(ib.raw_open); + allocator.free(ib.raw_close); }, .for_block => if (self.@"for") |fb| { allocator.free(fb.loop_var); @@ -255,7 +258,10 @@ pub const Node = struct { const empty_copy = fb.empty_body; for (empty_copy) |n| n.deinit(allocator); allocator.free(fb.empty_body); + allocator.free(fb.raw_open); + allocator.free(fb.raw_close); }, + .include => if (self.include) |inc| allocator.free(inc.template_name), .with_block => if (self.with) |w| { for (w.assignments) |a| { allocator.free(a.key); @@ -265,13 +271,20 @@ pub const Node = struct { const body_copy = w.body; for (body_copy) |n| n.deinit(allocator); allocator.free(w.body); + allocator.free(w.raw_open); + allocator.free(w.raw_close); }, + .now => if (self.now) |n| allocator.free(n.format), + .extends => if (self.extends) |e| allocator.free(e.parent_name), .block => if (self.block) |b| { allocator.free(b.name); const body_copy = b.body; for (body_copy) |n| n.deinit(allocator); allocator.free(b.body); + allocator.free(b.raw_open); + allocator.free(b.raw_close); }, + .super => {}, .filter_block => if (self.filter_block) |fb| { allocator.free(fb.filters); const body_copy = fb.body; @@ -282,16 +295,16 @@ pub const Node = struct { const body_copy = ae.body; for (body_copy) |n| n.deinit(allocator); allocator.free(ae.body); + allocator.free(ae.raw_open); + allocator.free(ae.raw_close); }, .spaceless => if (self.spaceless) |sl| { const body_copy = sl.body; for (body_copy) |n| n.deinit(allocator); allocator.free(sl.body); + allocator.free(sl.raw_open); + allocator.free(sl.raw_close); }, - .include => if (self.include) |inc| allocator.free(inc.template_name), - .now => if (self.now) |n| allocator.free(n.format), - .extends => if (self.extends) |e| allocator.free(e.parent_name), - .super => {}, .url => if (self.url) |u| { allocator.free(u.name); for (u.args) |a| allocator.free(a); @@ -318,6 +331,8 @@ pub const Node = struct { .debug => {}, .partialdef => if (self.partialdef) |pd| { allocator.free(pd.name); + allocator.free(pd.raw_open); + allocator.free(pd.raw_close); for (pd.body) |n| n.deinit(allocator); allocator.free(pd.body); }, @@ -344,6 +359,344 @@ pub const Node = struct { .templatetag => {}, } } + + pub fn clone(self: Node, allocator: std.mem.Allocator) !Node { + switch (self.type) { + .text => { + return Node{ + .type = .text, + .text = .{ .content = try allocator.dupe(u8, self.text.?.content) }, + }; + }, + + .variable => { + const filters_copy = try allocator.alloc(Filter, self.variable.?.filters.len); + errdefer allocator.free(filters_copy); + + for (self.variable.?.filters, 0..) |f, i| { + filters_copy[i] = .{ + .name = try allocator.dupe(u8, f.name), + .arg = if (f.arg) |a| try allocator.dupe(u8, a) else null, + }; + } + + return Node{ + .type = .variable, + .variable = .{ + .expr = try allocator.dupe(u8, self.variable.?.expr), + .filters = filters_copy, + }, + }; + }, + + .if_block => { + const true_body_copy = try allocator.alloc(Node, self.@"if".?.true_body.len); + errdefer allocator.free(true_body_copy); + + for (self.@"if".?.true_body, 0..) |child, j| { + true_body_copy[j] = try child.clone(allocator); + } + + const false_body_copy = try allocator.alloc(Node, self.@"if".?.false_body.len); + errdefer allocator.free(false_body_copy); + + for (self.@"if".?.false_body, 0..) |child, j| { + false_body_copy[j] = try child.clone(allocator); + } + + return Node{ + .type = .if_block, + .@"if" = .{ + .condition = try allocator.dupe(u8, self.@"if".?.condition), + .true_body = true_body_copy, + .false_body = false_body_copy, + .raw_open = try allocator.dupe(u8, self.@"if".?.raw_open), + .raw_close = try allocator.dupe(u8, self.@"if".?.raw_close), + }, + }; + }, + + .for_block => { + const body_copy = try allocator.alloc(Node, self.@"for".?.body.len); + errdefer allocator.free(body_copy); + + for (self.@"for".?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + const empty_body_copy = try allocator.alloc(Node, self.@"for".?.empty_body.len); + errdefer allocator.free(empty_body_copy); + + for (self.@"for".?.empty_body, 0..) |child, j| { + empty_body_copy[j] = try child.clone(allocator); + } + + return Node{ + .type = .for_block, + .@"for" = .{ + .loop_var = try allocator.dupe(u8, self.@"for".?.loop_var), + .iterable = try allocator.dupe(u8, self.@"for".?.iterable), + .body = body_copy, + .empty_body = empty_body_copy, + .raw_open = try allocator.dupe(u8, self.@"for".?.raw_open), + .raw_close = try allocator.dupe(u8, self.@"for".?.raw_close), + }, + }; + }, + + .block => { + const body_copy = try allocator.alloc(Node, self.block.?.body.len); + errdefer allocator.free(body_copy); + + for (self.block.?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + return Node{ + .type = .block, + .block = .{ + .name = try allocator.dupe(u8, self.block.?.name), + .body = body_copy, + .raw_open = try allocator.dupe(u8, self.block.?.raw_open), + .raw_close = try allocator.dupe(u8, self.block.?.raw_close), + }, + }; + }, + + .extends => { + return Node{ + .type = .extends, + .extends = .{ + .parent_name = try allocator.dupe(u8, self.extends.?.parent_name), + }, + }; + }, + + .super => { + return Node{ + .type = .super, + }; + }, + .tag => { + return Node{ + .type = .tag, + .tag = .{ + .name = try allocator.dupe(u8, self.tag.?.name), + .args = try allocator.dupe(u8, self.tag.?.args), + .raw = try allocator.dupe(u8, self.tag.?.raw), + }, + }; + }, + .include => { + return Node{ + .type = .include, + .include = .{ + .template_name = try allocator.dupe(u8, self.include.?.template_name), + }, + }; + }, + .with_block => { + const body_copy = try allocator.alloc(Node, self.block.?.body.len); + errdefer allocator.free(body_copy); + + for (self.block.?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + const assignments_copy = try allocator.alloc(Assignment, self.with.?.assignments.len); + errdefer allocator.free(assignments_copy); + + for (self.with.?.assignments, 0..) |f, i| { + assignments_copy[i] = .{ + .key = try allocator.dupe(u8, f.key), + .value_expr = try allocator.dupe(u8, f.value_expr), + .is_literal = f.is_literal, + }; + } + + return Node{ + .type = .with_block, + .with = .{ + .assignments = assignments_copy, + .body = body_copy, + .raw_open = try allocator.dupe(u8, self.with.?.raw_open), + .raw_close = try allocator.dupe(u8, self.with.?.raw_close), + }, + }; + }, + .now => { + return Node{ .type = .now, .now = .{ .format = try allocator.dupe(u8, self.now.?.format) } }; + }, + .filter_block => { + const body_copy = try allocator.alloc(Node, self.filter_block.?.body.len); + errdefer allocator.free(body_copy); + + for (self.filter_block.?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + return Node{ + .type = .filter_block, + .filter_block = .{ + .filters = try allocator.dupe(u8, self.filter_block.?.filters), + .body = body_copy, + .raw_open = try allocator.dupe(u8, self.filter_block.?.raw_open), + .raw_close = try allocator.dupe(u8, self.filter_block.?.raw_close), + }, + }; + }, + .autoescape => { + const body_copy = try allocator.alloc(Node, self.autoescape.?.body.len); + errdefer allocator.free(body_copy); + + for (self.autoescape.?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + return Node{ + .type = .autoescape, + .autoescape = .{ + .body = body_copy, + .raw_open = try allocator.dupe(u8, self.autoescape.?.raw_open), + .raw_close = try allocator.dupe(u8, self.autoescape.?.raw_close), + .enabled = self.autoescape.?.enabled, + }, + }; + }, + .spaceless => { + const body_copy = try allocator.alloc(Node, self.spaceless.?.body.len); + errdefer allocator.free(body_copy); + + for (self.spaceless.?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + return Node{ + .type = .spaceless, + .spaceless = .{ + .body = body_copy, + .raw_open = try allocator.dupe(u8, self.spaceless.?.raw_open), + .raw_close = try allocator.dupe(u8, self.spaceless.?.raw_close), + }, + }; + }, + .url => { + const args_copy = try allocator.alloc([]const u8, self.url.?.args.len); + errdefer allocator.free(args_copy); + + for (self.url.?.args, 0..) |f, i| { + args_copy[i] = try allocator.dupe(u8, f); + } + + return Node{ .type = .url, .url = .{ + .name = try allocator.dupe(u8, self.url.?.name), + .args = args_copy, + } }; + }, + .cycle => { + const values_copy = try allocator.alloc([]const u8, self.cycle.?.values.len); + errdefer allocator.free(values_copy); + + for (self.cycle.?.values, 0..) |f, i| { + values_copy[i] = try allocator.dupe(u8, f); + } + + return Node{ .type = .cycle, .cycle = .{ .values = values_copy } }; + }, + .firstof => { + const values_copy = try allocator.alloc([]const u8, self.firstof.?.values.len); + errdefer allocator.free(values_copy); + + for (self.firstof.?.values, 0..) |f, i| { + values_copy[i] = try allocator.dupe(u8, f); + } + + return Node{ .type = .firstof, .firstof = .{ .values = values_copy } }; + }, + .load => { + const libraries_copy = try allocator.alloc([]const u8, self.load.?.libraries.len); + errdefer allocator.free(libraries_copy); + + for (self.load.?.libraries, 0..) |f, i| { + libraries_copy[i] = try allocator.dupe(u8, f); + } + + return Node{ .type = .load, .load = .{ .libraries = libraries_copy } }; + }, + .csrf_token => { + return Node{ + .type = .csrf_token, + }; + }, + .lorem => { + return Node{ + .type = .lorem, + .lorem = .{ + .count = if (self.lorem.?.count) |c| try allocator.dupe(u8, c) else null, + .method = if (self.lorem.?.method) |m| try allocator.dupe(u8, m) else null, + .format = if (self.lorem.?.format) |f| try allocator.dupe(u8, f) else null, + }, + }; + }, + .debug => { + return Node{ .type = .debug }; + }, + .partialdef => { + const body_copy = try allocator.alloc(Node, self.partialdef.?.body.len); + errdefer allocator.free(body_copy); + + for (self.partialdef.?.body, 0..) |child, j| { + body_copy[j] = try child.clone(allocator); + } + + return Node{ .type = .partialdef, .partialdef = .{ + .name = try allocator.dupe(u8, self.partialdef.?.name), + .body = body_copy, + .raw_open = try allocator.dupe(u8, self.partialdef.?.raw_open), + .raw_close = try allocator.dupe(u8, self.partialdef.?.raw_close), + } }; + }, + .partial => { + return Node{ .type = .partial, .partial = .{ + .name = try allocator.dupe(u8, self.partial.?.name), + } }; + }, + .querystring => { + const modifications = try allocator.alloc([]const u8, self.querystring.?.modifications.len); + errdefer allocator.free(modifications); + + for (self.querystring.?.modifications, 0..) |f, i| { + modifications[i] = try allocator.dupe(u8, f); + } + + return Node{ .type = .querystring, .querystring = .{ + .modifications = modifications, + } }; + }, + .regroup => { + return Node{ .type = .regroup, .regroup = .{ + .source = try allocator.dupe(u8, self.regroup.?.source), + .by = try allocator.dupe(u8, self.regroup.?.by), + .as_var = try allocator.dupe(u8, self.regroup.?.as_var), + } }; + }, + .resetcycle => { + return Node{ .type = .resetcycle, .resetcycle = .{ + .cycle_name = if (self.resetcycle.?.cycle_name) |n| try allocator.dupe(u8, n) else null, + } }; + }, + .widthratio => { + return Node{ .type = .widthratio, .widthratio = .{ + .value = try allocator.dupe(u8, self.widthratio.?.value), + .max_value = try allocator.dupe(u8, self.widthratio.?.max_value), + .divisor = if (self.widthratio.?.divisor) |d| try allocator.dupe(u8, d) else null, + } }; + }, + .templatetag => { + return Node{ .type = .templatetag, .templatetag = .{ .kind = self.templatetag.?.kind } }; + }, + } + } }; pub const Parser = struct {