Add if statements to templating engine
This commit is contained in:
parent
5bb9742ab9
commit
c9af99d08f
2 changed files with 49 additions and 5 deletions
|
@ -8,11 +8,13 @@ pub fn main() !void {
|
|||
&.{ "5", "4", "3", "2", "1" },
|
||||
&.{ "5", "4", "3", "2", "1" },
|
||||
},
|
||||
.qux = true,
|
||||
.quxx = false,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn execute(writer: anytype, comptime template: []const u8, args: anytype) !void {
|
||||
@setEvalBranchQuota(@intCast(u32, template.len * 6));
|
||||
@setEvalBranchQuota(@intCast(u32, template.len * 8));
|
||||
const tmpl = comptime parseTemplate(TokenIter{ .text = template }, .root);
|
||||
try executeTemplate(writer, tmpl.item, args, .{});
|
||||
}
|
||||
|
@ -42,6 +44,11 @@ fn executeStatement(writer: anytype, comptime stmt: Statement, args: anytype, ca
|
|||
);
|
||||
}
|
||||
},
|
||||
.if_statement => |if_stmt| {
|
||||
const condition = evaluateExpression(if_stmt.condition, args, captures);
|
||||
const subtemplate = if_stmt.subtemplate;
|
||||
if (condition) try executeTemplate(writer, subtemplate, args, captures);
|
||||
},
|
||||
else => @compileError("TODO"),
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +119,8 @@ fn addCapture(root: anytype, comptime name: []const u8, val: anytype) AddCapture
|
|||
|
||||
const TemplateType = enum {
|
||||
root,
|
||||
subtemplate,
|
||||
for_block,
|
||||
if_block,
|
||||
};
|
||||
|
||||
fn parseTemplate(comptime tokens: TokenIter, comptime template_type: TemplateType) ParseResult([]const TemplateItem) {
|
||||
|
@ -137,7 +145,9 @@ fn parseTemplate(comptime tokens: TokenIter, comptime template_type: TemplateTyp
|
|||
const result = parseExpressionOrStatement(iter, true);
|
||||
iter = result.new_iter;
|
||||
if (result.item == .end_for) {
|
||||
if (template_type == .subtemplate) break :parse_loop else @compileError("Unexpected end statement");
|
||||
if (template_type == .for_block) break :parse_loop else @compileError("Unexpected end statement");
|
||||
} else if (result.item == .end_if) {
|
||||
if (template_type == .if_block) break :parse_loop else @compileError("Unexpected end statement");
|
||||
}
|
||||
items = items ++ [_]TemplateItem{.{ .statement = result.item }};
|
||||
}
|
||||
|
@ -189,6 +199,13 @@ fn parseExpressionOrStatement(
|
|||
.item = .{ .for_loop = result.item },
|
||||
};
|
||||
},
|
||||
.@"if" => {
|
||||
const result = parseIfStatement(iter);
|
||||
return .{
|
||||
.new_iter = result.new_iter,
|
||||
.item = .{ .if_statement = result.item },
|
||||
};
|
||||
},
|
||||
|
||||
//else => @compileError("TODO"),
|
||||
}
|
||||
|
@ -202,6 +219,7 @@ fn parseExpressionOrStatement(
|
|||
|
||||
switch (keyword) {
|
||||
.@"for" => break .{ .end_for = {} },
|
||||
.@"if" => break .{ .end_if = {} },
|
||||
}
|
||||
},
|
||||
.period => {
|
||||
|
@ -283,9 +301,24 @@ fn parseForLoop(comptime tokens: TokenIter) ParseResult(ForLoop) {
|
|||
}
|
||||
iter = endStatement(iter);
|
||||
|
||||
const subtemplate = parseTemplate(iter, .subtemplate);
|
||||
const subtemplate = parseTemplate(iter, .for_block);
|
||||
|
||||
return .{ .new_iter = subtemplate.new_iter, .item = .{ .iterable = iterable.item, .subtemplate = subtemplate.item, .capture = capture } };
|
||||
return .{ .new_iter = subtemplate.new_iter, .item = .{
|
||||
.iterable = iterable.item,
|
||||
.subtemplate = subtemplate.item,
|
||||
.capture = capture,
|
||||
} };
|
||||
}
|
||||
}
|
||||
|
||||
fn parseIfStatement(comptime tokens: TokenIter) ParseResult(IfStatement) {
|
||||
comptime {
|
||||
const condition = parseExpressionOrStatement(tokens, false);
|
||||
var iter = endStatement(condition.new_iter);
|
||||
|
||||
const subtemplate = parseTemplate(iter, .if_block);
|
||||
|
||||
return .{ .new_iter = subtemplate.new_iter, .item = .{ .condition = condition.item, .subtemplate = subtemplate.item } };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,18 +372,27 @@ const ForLoop = struct {
|
|||
capture: []const u8,
|
||||
};
|
||||
|
||||
const IfStatement = struct {
|
||||
subtemplate: []const TemplateItem,
|
||||
condition: Expression,
|
||||
};
|
||||
|
||||
const Statement = union(enum) {
|
||||
expression: Expression,
|
||||
for_loop: ForLoop,
|
||||
end_for: void,
|
||||
if_statement: IfStatement,
|
||||
end_if: void,
|
||||
};
|
||||
|
||||
const Keyword = enum {
|
||||
@"for",
|
||||
@"if",
|
||||
};
|
||||
|
||||
const EndKeyword = enum {
|
||||
@"for",
|
||||
@"if",
|
||||
};
|
||||
|
||||
const Token = union(enum) {
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
<section>
|
||||
{#for .baz |$f|}{#for $f |$b|}{$b}:{/for}
|
||||
{/for}
|
||||
{#if .qux}qux!{/if}
|
||||
{#if .quxx}quxx!{/if}
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue