update: add extends,block and super into parser

This commit is contained in:
Lucas F. 2026-01-03 15:32:12 -03:00
parent 3019009325
commit 261c02f59b
3 changed files with 551 additions and 285 deletions

View file

@ -9,15 +9,26 @@ pub const NodeType = enum {
include,
with_block,
now,
// extends, // <--- novo
// block, // <--- novo
// super, // <--- novo (para {{ block.super }})
extends, // <--- novo
block, // <--- novo
super, // <--- novo (para {{ block.super }})
};
pub const NowNode = struct {
format: []const u8,
};
pub const ExtendsNode = struct {
parent_name: []const u8,
};
pub const BlockNode = struct {
name: []const u8,
body: []Node,
raw_open: []const u8,
raw_close: []const u8,
};
pub const Assignment = struct {
key: []const u8,
value_expr: []const u8,
@ -76,6 +87,9 @@ pub const Node = struct {
include: ?IncludeNode = null,
with: ?WithNode = null,
now: ?NowNode = null,
extends: ?ExtendsNode = null,
block: ?BlockNode = null,
super: bool = false, // para {{ block.super }}
pub fn deinit(self: Node, allocator: std.mem.Allocator) void {
switch (self.type) {
@ -119,6 +133,16 @@ pub const Node = struct {
.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);
for (b.body) |n| n.deinit(allocator);
allocator.free(b.body);
// raw_open e raw_close são slices originais não free
},
.super => {},
}
}
};
@ -218,6 +242,70 @@ pub const Parser = struct {
return try list.toOwnedSlice(allocator);
}
fn parseBlockBlock(self: *Parser, allocator: std.mem.Allocator, name: []const u8, raw_open: []const u8) !Node {
var body = std.ArrayList(Node){};
defer body.deinit(allocator);
var depth: usize = 1;
while (self.pos < self.template.len and depth > 0) {
if (try self.parseText(allocator)) |node| {
try body.append(allocator, node);
continue;
}
if (try self.parseVariable(allocator)) |node| {
if (node.variable) |v| {
if (std.mem.eql(u8, v.content, "block.super")) {
try body.append(allocator, Node{ .type = .super, .super = true });
allocator.free(v.content);
continue;
}
}
try body.append(allocator, node);
continue;
}
if (try self.parseTag(allocator)) |tag_node| {
const tag_name = tag_node.tag.?.name;
if (std.mem.eql(u8, tag_name, "block")) {
depth += 1;
try body.append(allocator, tag_node);
continue;
}
if (std.mem.eql(u8, tag_name, "endblock")) {
depth -= 1;
const raw_close = tag_node.tag.?.raw;
allocator.free(tag_node.tag.?.name);
allocator.free(tag_node.tag.?.args);
if (depth == 0) {
return Node{
.type = .block,
.block = .{
.name = name,
.body = try body.toOwnedSlice(allocator),
.raw_open = raw_open,
.raw_close = raw_close,
},
};
}
try body.append(allocator, tag_node);
continue;
}
try body.append(allocator, tag_node);
} else {
self.advance(1);
}
}
return error.UnclosedBlock;
}
fn parseWithBlock(self: *Parser, allocator: std.mem.Allocator, assignments: []const Assignment, raw_open: []const u8) !Node {
std.debug.print("Vou verificar se sou bloco with\n", .{});
var body = std.ArrayList(Node){};
@ -627,6 +715,44 @@ pub const Parser = struct {
continue;
}
if (std.mem.eql(u8, tag_name, "extends")) {
const parent = std.mem.trim(u8, node.tag.?.args, " \t\"");
const duped = try allocator.dupe(u8, parent);
allocator.free(node.tag.?.name);
allocator.free(node.tag.?.args);
std.debug.print("3.0 - na real sou um extends\n", .{});
std.debug.print("===================================\n", .{});
try list.append(allocator, Node{
.type = .extends,
.extends = .{ .parent_name = duped },
});
continue;
}
if (std.mem.eql(u8, tag_name, "block")) {
const block_name_raw = node.tag.?.args;
const raw_open = node.tag.?.raw;
const block_name = std.mem.trim(u8, block_name_raw, " \t\r\n");
// DUPE O NOME ANTES DE LIBERAR A TAG
const duped_name = try allocator.dupe(u8, block_name);
// Agora libera a tag open
allocator.free(node.tag.?.name);
allocator.free(node.tag.?.args);
std.debug.print("3.0 - na real sou um block\n", .{});
std.debug.print("===================================\n", .{});
const block_node = try self.parseBlockBlock(allocator, duped_name, raw_open);
try list.append(allocator, block_node);
continue;
}
if (std.mem.eql(u8, tag_name, "now")) {
const args = node.tag.?.args;