From 3fa37f9613ce7a4760cbc0fd54149d63a2b172e9 Mon Sep 17 00:00:00 2001 From: "Lucas F." Date: Sat, 17 Jan 2026 17:38:03 -0300 Subject: [PATCH] update: refactor for new parser style --- src/renderer.zig | 202 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 193 insertions(+), 9 deletions(-) diff --git a/src/renderer.zig b/src/renderer.zig index 97d7d83..a827a30 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -36,7 +36,8 @@ pub const Renderer = struct { fn checkForExtends(self: *const Renderer, nodes: []parser.Node) ?parser.Node { _ = self; for (nodes) |n| { - if (n.type == .extends) return n; + // if (n.type == .extends) return n; + if (n.type == .tag and n.tag.?.kind == .extends) return n; } return null; } @@ -60,15 +61,29 @@ pub const Renderer = struct { const extends_node = self.checkForExtends(nodes); if (extends_node) |ext| { - const base_template = try self.readTemplateFile(ext.extends.?.parent_name); + // const base_template = try self.readTemplateFile(ext.extends.?.parent_name); + const base_template = try self.readTemplateFile(ext.tag.?.body.extends.parent_name); defer self.allocator.free(base_template); + std.debug.print("template_path: {s}\n", .{ext.tag.?.body.extends.parent_name}); var base_parser = parser.Parser.init(base_template); const base_nodes = try base_parser.parse(alloc); defer { for (base_nodes) |n| n.deinit(alloc); alloc.free(base_nodes); } + // std.debug.print("base_nodes: {any}\n", .{base_nodes}); + for (nodes) |node| { + if (node.type == .tag) { + std.debug.print("tag: {any}\n", .{node.tag.?.kind}); + } + if (node.type == .text) { + std.debug.print("text: {s}\n", .{node.text.?.content}); + } + if (node.type == .variable) { + std.debug.print("variable: {s}\n", .{node.variable.?.expr}); + } + } try self.renderWithInheritance(alloc, base_nodes, nodes, writer); } else { for (nodes) |node| { @@ -122,19 +137,18 @@ pub const Renderer = struct { fn renderWithInheritance(self: *const Renderer, alloc: Allocator, base_nodes: []parser.Node, child_nodes: []parser.Node, writer: anytype) RenderError!void { for (base_nodes) |base_node| { - if (base_node.type == .block) { - const block_name = base_node.block.?.name; + if (base_node.type == .tag and base_node.tag.?.kind == .block) { + const block_name = base_node.tag.?.body.block.name; - // Procura no filho const child_block = self.findChildBlock(child_nodes, block_name); if (child_block) |child| { // Renderiza o filho, passando o conteúdo do pai para block.super for (child.body) |child_node| { - try self.renderNode(alloc, child_nodes, child_node, writer, null, base_node.block.?.body); + try self.renderNode(alloc, child_nodes, child_node, writer, null, base_node.tag.?.body.block.body); } } else { // Renderiza o do pai - for (base_node.block.?.body) |child| { + for (base_node.tag.?.body.block.body) |child| { try self.renderNode(alloc, child_nodes, child, writer, null, null); } } @@ -145,6 +159,175 @@ pub const Renderer = struct { } fn renderNode(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, node: parser.Node, writer: anytype, context: ?*Context, parent_block_nodes: ?[]parser.Node) RenderError!void { + switch (node.type) { + .text => try writer.writeAll(node.text.?.content), + .variable => { + const var_name = node.variable.?.expr; + var value: Value = Value.null; + if (context != null) { + value = context.?.get(var_name) orelse Value.null; + } else { + value = self.context.get(var_name) orelse Value.null; + } + + var is_safe = false; + + for (node.variable.?.filters) |f| { + const filter_fn = builtin_filters.get(f.name) orelse return error.UnknownFilter; + + // const arg = if (f.arg) |a| Value{ .string = a } else null; + var arg: Value = Value.null; + if (f.arg) |a| { + arg = Value{ .string = a }; + const result = try std.fmt.parseInt(i64, a, 10); + if (std.math.maxInt(i64) < result) return error.Overflow; + arg = Value{ .int = result }; + } + value = try filter_fn(alloc, value, arg); + + if (std.mem.eql(u8, f.name, "safe")) is_safe = true; + } + + if (!is_safe) { + if (builtin_filters.get("escape")) |escape_fn| { + value = try escape_fn(alloc, value, null); + } + } + + var buf = ArrayListUnmanaged(u8){}; + defer buf.deinit(alloc); + + try self.valueToString(alloc, &buf, value); + try writer.writeAll(buf.items); + }, + .tag => { + switch (node.tag.?.kind) { + .if_block => { + const condition = try self.evaluateCondition(alloc, node.tag.?.body.@"if".condition); + + if (condition) { + for (node.tag.?.body.@"if".true_body) |child| { + try self.renderNode(alloc, nodes, child, writer, null, null); + } + } else { + for (node.tag.?.body.@"if".false_body) |child| { + try self.renderNode(alloc, nodes, child, writer, null, null); + } + } + }, + .include => { + const included_template = try self.readTemplateFile(node.tag.?.body.include.template_path); + defer alloc.free(included_template); + + var included_parser = parser.Parser.init(included_template); + const included_nodes = try included_parser.parse(alloc); + defer { + for (included_nodes) |n| n.deinit(alloc); + alloc.free(included_nodes); + } + + // Renderiza o include no contexto atual (sem novo contexto) + for (included_nodes) |included_node| { + try self.renderNode(alloc, nodes, included_node, writer, context, null); + } + }, + .for_block => { + const list_value = self.context.get(node.tag.?.body.@"for".iterable) orelse Value.null; + const list = switch (list_value) { + .list => |l| l, + else => return, + }; + + for (list) |item| { + var ctx = Context.init(alloc); + defer ctx.deinit(); + + try ctx.set(node.tag.?.body.@"for".loop_var, item); + + for (node.tag.?.body.@"for".body) |child| { + try self.renderNode(alloc, nodes, child, writer, &ctx, null); + } + + if (node.tag.?.body.@"for".body.len == 0) { + for (node.tag.?.body.@"for".empty_body) |child| { + try self.renderNode(alloc, nodes, child, writer, &ctx, null); + } + } + } + }, + .super => { + if (parent_block_nodes) |parent| { + for (parent) |child| { + try self.renderNode(alloc, nodes, child, writer, null, null); + } + } + }, + .block => { + for (node.tag.?.body.block.body) |child| { + const parent_content = parent_block_nodes orelse node.tag.?.body.block.body; + try self.renderNode(alloc, nodes, child, writer, null, parent_content); + } + }, + .widthratio => { + var divisor: Value = Value{ .float = 1.0 }; + var float_divisor: f64 = 1.0; + + var value: Value = Value{ .float = 1.0 }; + var float_value: f64 = 1.0; + + var max_value: Value = Value{ .float = 1.0 }; + var float_max_value: f64 = 1.0; + + if (!std.mem.eql(u8, node.tag.?.body.widthratio.value, "")) { + value = Value{ .string = node.tag.?.body.widthratio.value }; + if (self.context.get(node.tag.?.body.widthratio.value)) |v| { + value = v; + } + float_value = switch (value) { + .int => @as(f64, @floatFromInt(value.int)), + .float => value.float, + .string => std.fmt.parseFloat(f64, value.string) catch 1.0, + else => 1.0, + }; + } + + if (!std.mem.eql(u8, node.tag.?.body.widthratio.max_value, "")) { + max_value = Value{ .string = node.tag.?.body.widthratio.max_value }; + if (self.context.get(node.tag.?.body.widthratio.max_value)) |v| { + max_value = v; + } + float_max_value = switch (max_value) { + .int => @as(f64, @floatFromInt(max_value.int)), + .float => max_value.float, + .string => std.fmt.parseFloat(f64, max_value.string) catch 1.0, + else => 1.0, + }; + } + + if (node.tag.?.body.widthratio.divisor) |div| { + divisor = Value{ .string = div }; + if (self.context.get(div)) |d| { + divisor = d; + } + float_divisor = switch (divisor) { + .int => @as(f64, @floatFromInt(divisor.int)), + .float => divisor.float, + .string => std.fmt.parseFloat(f64, divisor.string) catch 0.0, + else => 1.0, + }; + } + + const ratio = (float_value / float_max_value) * float_divisor; + + try writer.writeAll(std.fmt.allocPrint(alloc, "{d}", .{ratio}) catch "0"); + }, + else => {}, + } + }, + } + } + + fn renderNode_old(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, node: parser.Node, writer: anytype, context: ?*Context, parent_block_nodes: ?[]parser.Node) RenderError!void { switch (node.type) { .text => try writer.writeAll(node.text.?.content), .variable => { @@ -312,8 +495,9 @@ pub const Renderer = struct { fn findChildBlock(self: *const Renderer, nodes: []parser.Node, name: []const u8) ?parser.BlockNode { _ = self; for (nodes) |n| { - if (n.type != .block) continue; - if (std.mem.eql(u8, n.block.?.name, name)) return n.block.?; + if (n.type != .tag) continue; + if (n.tag.?.kind != .block) continue; + if (std.mem.eql(u8, n.tag.?.body.block.name, name)) return n.tag.?.body.block; } return null; }