update: block and extends
This commit is contained in:
parent
13ad344005
commit
da8076a1d9
1 changed files with 127 additions and 10 deletions
137
src/renderer.zig
137
src/renderer.zig
|
|
@ -52,6 +52,69 @@ pub const Renderer = struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn checkForExtends(self: *const Renderer, nodes: []parser.Node) ?parser.Node {
|
||||
_ = self;
|
||||
for (nodes) |n| {
|
||||
if (n.type == .extends) return n;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn readTemplateFile(self: *const Renderer, path: []const u8) RenderError![]const u8 {
|
||||
const max_size = 10 * 1024 * 1024;
|
||||
const base_template = std.fs.cwd().readFileAlloc(self.allocator, path, max_size) catch |err| switch (err) {
|
||||
error.FileNotFound => return RenderError.FileNotFound,
|
||||
error.AccessDenied => return RenderError.AccessDenied,
|
||||
error.FileTooBig => return RenderError.FileTooBig,
|
||||
error.NoSpaceLeft => return RenderError.NoSpaceLeft,
|
||||
error.OutOfMemory => return RenderError.OutOfMemory,
|
||||
else => return RenderError.Unexpected,
|
||||
};
|
||||
return base_template;
|
||||
}
|
||||
|
||||
pub fn render(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
||||
const base_template = try self.readTemplateFile(template);
|
||||
return self.renderString(base_template, writer);
|
||||
}
|
||||
|
||||
pub fn renderString_bkp(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
var p = parser.Parser.init(template);
|
||||
const nodes = try p.parse(alloc);
|
||||
defer {
|
||||
for (nodes) |node| node.deinit(alloc);
|
||||
alloc.free(nodes);
|
||||
}
|
||||
|
||||
const has_extends = self.checkForExtends(nodes);
|
||||
|
||||
if (has_extends) {
|
||||
for (nodes) |node| {
|
||||
if (node.type == .extends) {
|
||||
const base_template = try self.readTemplateFile(node.extends.?.parent_name);
|
||||
defer self.allocator.free(base_template);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
try self.renderWithInheritance(alloc, base_nodes, nodes, writer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (nodes) |node| {
|
||||
try self.renderNode(alloc, nodes, node, writer, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
|
|
@ -64,12 +127,52 @@ pub const Renderer = struct {
|
|||
alloc.free(nodes);
|
||||
}
|
||||
|
||||
for (nodes) |node| {
|
||||
try self.renderNode(alloc, node, writer, null);
|
||||
const block_extends = self.checkForExtends(nodes);
|
||||
|
||||
if (block_extends) |ext| {
|
||||
const base_template = try self.readTemplateFile(ext.extends.?.parent_name);
|
||||
defer self.allocator.free(base_template);
|
||||
|
||||
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);
|
||||
}
|
||||
try self.renderWithInheritance(alloc, base_nodes, nodes, writer);
|
||||
} else {
|
||||
for (nodes) |node| {
|
||||
try self.renderNode(alloc, nodes, node, writer, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn renderNode(self: *const Renderer, alloc: Allocator, node: parser.Node, writer: anytype, context: ?*Context) RenderError!void {
|
||||
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;
|
||||
|
||||
// Procura no filho
|
||||
const child_block = self.findChildBlock(child_nodes, block_name);
|
||||
if (child_block) |child| {
|
||||
// Renderiza só o filho
|
||||
for (child.body) |child_node| {
|
||||
try self.renderNode(alloc, child_nodes, child_node, writer, null);
|
||||
}
|
||||
} else {
|
||||
// Renderiza o do pai
|
||||
for (base_node.block.?.body) |child| {
|
||||
try self.renderNode(alloc, child_nodes, child, writer, null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Qualquer outra coisa no base
|
||||
try self.renderNode(alloc, child_nodes, base_node, writer, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn renderNode(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, node: parser.Node, writer: anytype, context: ?*Context) RenderError!void {
|
||||
switch (node.type) {
|
||||
.text => try writer.writeAll(node.text.?.content),
|
||||
.variable => {
|
||||
|
|
@ -77,7 +180,7 @@ pub const Renderer = struct {
|
|||
var value: Value = Value.null;
|
||||
if (context != null) {
|
||||
value = context.?.get(var_name) orelse Value.null;
|
||||
}else{
|
||||
} else {
|
||||
value = self.context.get(var_name) orelse Value.null;
|
||||
}
|
||||
|
||||
|
|
@ -104,17 +207,16 @@ pub const Renderer = struct {
|
|||
try self.valueToString(alloc, &buf, value);
|
||||
try writer.writeAll(buf.items);
|
||||
},
|
||||
|
||||
.if_block => {
|
||||
const condition = self.evaluateCondition(node.@"if".?.condition) catch return false;
|
||||
|
||||
if (condition) {
|
||||
for (node.@"if".?.true_body) |child| {
|
||||
try self.renderNode(alloc, child, writer, null);
|
||||
try self.renderNode(alloc, nodes, child, writer, null);
|
||||
}
|
||||
} else {
|
||||
for (node.@"if".?.false_body) |child| {
|
||||
try self.renderNode(alloc, child, writer, null);
|
||||
try self.renderNode(alloc, nodes, child, writer, null);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -129,20 +231,35 @@ pub const Renderer = struct {
|
|||
var ctx = Context.init(alloc);
|
||||
defer ctx.deinit();
|
||||
|
||||
try ctx.set(node.@"for".?.loop_var,item);
|
||||
try ctx.set(node.@"for".?.loop_var, item);
|
||||
|
||||
for (node.@"for".?.body) |child| {
|
||||
try self.renderNode(alloc, child, writer, &ctx);
|
||||
try self.renderNode(alloc, nodes, child, writer, &ctx);
|
||||
}
|
||||
for (node.@"for".?.empty_body) |child| {
|
||||
try self.renderNode(alloc, child, writer, &ctx);
|
||||
try self.renderNode(alloc, nodes, child, writer, &ctx);
|
||||
}
|
||||
}
|
||||
},
|
||||
.super => std.debug.print("\n\ntenho SUPER!!\n\n", .{}),
|
||||
.block => {
|
||||
for (node.block.?.body) |child| {
|
||||
try self.renderNode(alloc, nodes, child, writer, null);
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
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.?;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) !void {
|
||||
_ = self;
|
||||
var w = buf.writer(alloc);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue