Further split parsing and execution

This commit is contained in:
jaina heartles 2022-11-15 22:35:27 -08:00
parent d24957b7a0
commit efb50a325b
1 changed files with 57 additions and 26 deletions

View File

@ -7,32 +7,15 @@ pub fn main() !void {
const logging = false;
pub fn execute(writer: anytype, comptime template: []const u8, args: anytype) !void {
@setEvalBranchQuota(@intCast(u32, template.len * 6));
comptime var iter = TokenIter{ .text = template };
inline while (comptime iter.next()) |token| {
if (logging) @compileLog(token);
switch (token) {
.text => |text| try writer.writeAll(text),
.open_bracket => {
const next = comptime iter.peek() orelse @compileError("Unexpected end of template");
if (next == .open_bracket) {
try writer.writeByte('{');
_ = comptime iter.next();
} else {
const result = comptime parseStatement(iter);
try executeStatement(writer, result.item, args);
iter = result.new_iter;
}
},
.close_bracket => {
const next = comptime iter.next() orelse @compileError("Unexpected end of template");
if (comptime next == .close_bracket) try writer.writeByte('}') else @compileError("Unpaired close bracket, did you mean \"}}\"?");
},
.whitespace => |wsp| try writer.writeAll(wsp),
.period => try writer.writeByte('.'),
.pound => try writer.writeByte('#'),
}
}
const items = comptime parseTemplate(template);
try executeTemplate(writer, items, args);
}
fn executeTemplate(writer: anytype, comptime items: []const TemplateItem, args: anytype) !void {
inline for (items) |it| switch (it) {
.text => |text| try writer.writeAll(text),
.statement => |stmt| try executeStatement(writer, stmt, args),
};
}
fn executeStatement(writer: anytype, comptime stmt: Statement, args: anytype) !void {
@ -54,6 +37,49 @@ fn argDeref(writer: anytype, comptime names: []const []const u8, arg: anytype) !
return argDeref(writer, names[1..], @field(arg, names[0]));
}
fn parseTemplate(comptime template: []const u8) []const TemplateItem {
comptime {
@setEvalBranchQuota(@intCast(u32, template.len * 6));
var iter = TokenIter{ .text = template };
var items: []const TemplateItem = &.{};
var current_text: []const u8 = "";
while (iter.next()) |token| {
if (logging) @compileLog(token);
switch (token) {
.whitespace, .text => |text| current_text = current_text ++ text,
.open_bracket => {
const next = iter.peek() orelse @compileError("Unexpected end of template");
if (next == .open_bracket) {
current_text = current_text ++ "{";
_ = iter.next();
} else {
if (current_text.len != 0) {
items = items ++ [_]TemplateItem{.{ .text = current_text }};
current_text = "";
}
const result = parseStatement(iter);
iter = result.new_iter;
items = items ++ [_]TemplateItem{.{ .statement = result.item }};
}
},
.close_bracket => {
const next = iter.next() orelse @compileError("Unexpected end of template");
if (next == .close_bracket) current_text = current_text ++ "}" else @compileError("Unpaired close bracket, did you mean \"}}\"?");
},
.period => current_text = current_text ++ ".",
.pound => current_text = current_text ++ "#",
}
}
if (current_text.len != 0) {
items = items ++ [_]TemplateItem{.{ .text = current_text }};
}
return items;
}
}
fn parseStatement(comptime tokens: TokenIter) ParseResult(Statement) {
comptime {
var iter = tokens;
@ -122,6 +148,11 @@ fn ParseResult(comptime T: type) type {
};
}
const TemplateItem = union(enum) {
text: []const u8,
statement: Statement,
};
const Expression = union(enum) {
arg_deref: []const []const u8,
};