update: refactor for new parser style

This commit is contained in:
Lucas F. 2026-01-17 17:38:03 -03:00
parent f09689d539
commit 3fa37f9613

View file

@ -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;
}