Add if statements to templating engine

This commit is contained in:
jaina heartles 2022-11-17 23:39:32 -08:00
parent 5bb9742ab9
commit c9af99d08f
2 changed files with 49 additions and 5 deletions

View file

@ -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) {

View file

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