diff --git a/src/template/lib.zig b/src/template/lib.zig index 12adb46..d86c3a6 100644 --- a/src/template/lib.zig +++ b/src/template/lib.zig @@ -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) { diff --git a/src/template/test.tmp.html b/src/template/test.tmp.html index c5f26db..862b080 100644 --- a/src/template/test.tmp.html +++ b/src/template/test.tmp.html @@ -11,6 +11,8 @@
{#for .baz |$f|}{#for $f |$b|}{$b}:{/for} {/for} + {#if .qux}qux!{/if} + {#if .quxx}quxx!{/if}