update: block and extends
This commit is contained in:
parent
13ad344005
commit
da8076a1d9
1 changed files with 127 additions and 10 deletions
135
src/renderer.zig
135
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 {
|
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
|
||||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|
@ -64,12 +127,52 @@ pub const Renderer = struct {
|
||||||
alloc.free(nodes);
|
alloc.free(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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| {
|
for (nodes) |node| {
|
||||||
try self.renderNode(alloc, node, writer, null);
|
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) {
|
switch (node.type) {
|
||||||
.text => try writer.writeAll(node.text.?.content),
|
.text => try writer.writeAll(node.text.?.content),
|
||||||
.variable => {
|
.variable => {
|
||||||
|
|
@ -77,7 +180,7 @@ pub const Renderer = struct {
|
||||||
var value: Value = Value.null;
|
var value: Value = Value.null;
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
value = context.?.get(var_name) orelse Value.null;
|
value = context.?.get(var_name) orelse Value.null;
|
||||||
}else{
|
} else {
|
||||||
value = self.context.get(var_name) orelse Value.null;
|
value = self.context.get(var_name) orelse Value.null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,17 +207,16 @@ pub const Renderer = struct {
|
||||||
try self.valueToString(alloc, &buf, value);
|
try self.valueToString(alloc, &buf, value);
|
||||||
try writer.writeAll(buf.items);
|
try writer.writeAll(buf.items);
|
||||||
},
|
},
|
||||||
|
|
||||||
.if_block => {
|
.if_block => {
|
||||||
const condition = self.evaluateCondition(node.@"if".?.condition) catch return false;
|
const condition = self.evaluateCondition(node.@"if".?.condition) catch return false;
|
||||||
|
|
||||||
if (condition) {
|
if (condition) {
|
||||||
for (node.@"if".?.true_body) |child| {
|
for (node.@"if".?.true_body) |child| {
|
||||||
try self.renderNode(alloc, child, writer, null);
|
try self.renderNode(alloc, nodes, child, writer, null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (node.@"if".?.false_body) |child| {
|
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);
|
var ctx = Context.init(alloc);
|
||||||
defer ctx.deinit();
|
defer ctx.deinit();
|
||||||
|
|
||||||
try ctx.set(node.@"for".?.loop_var,item);
|
try ctx.set(node.@"for".?.loop_var, item);
|
||||||
|
|
||||||
for (node.@"for".?.body) |child| {
|
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| {
|
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 => {},
|
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 {
|
fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
var w = buf.writer(alloc);
|
var w = buf.writer(alloc);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue