aboutsummaryrefslogtreecommitdiff
path: root/src/root.zig
diff options
context:
space:
mode:
authorGrace Yoder <grace_yoder@outlook.com>2026-07-17 19:54:15 -0600
committerGrace Yoder <grace_yoder@outlook.com>2026-07-17 21:47:26 -0600
commit02132764068aa51ac98628d988dff15255308df0 (patch)
tree24455db4fc2d6f2c8941499cd0f586eedc2302e2 /src/root.zig
feat: zig rewrite
Diffstat (limited to 'src/root.zig')
-rwxr-xr-xsrc/root.zig76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/root.zig b/src/root.zig
new file mode 100755
index 0000000..3ddfe78
--- /dev/null
+++ b/src/root.zig
@@ -0,0 +1,76 @@
+const std = @import("std");
+const Io = std.Io;
+const Allocator = std.mem.Allocator;
+const ArenaAllocator = std.heap.ArenaAllocator;
+const SplitIterator = std.mem.SplitIterator;
+const DelimiterType = std.mem.DelimiterType;
+const ArrayList = std.ArrayList;
+const StringArrayHashMap = std.StringArrayHashMapUnmanaged;
+
+pub const tags = @import("tags.zig");
+pub const utils = @import("utils.zig");
+
+pub const ParserFn =
+ fn (
+ arena: *ArenaAllocator,
+ io: Io,
+ state: *Parser,
+ reader: *Io.Reader,
+ writer: *Io.Writer,
+ attrs: *SplitIterator(u8, DelimiterType.scalar),
+ ) anyerror!void;
+
+pub const ParserTag = struct {
+ name: []const u8,
+ parse_fn: *const ParserFn,
+};
+
+pub const Parser = struct {
+ component_resolver: *const fn (alloc: *ArenaAllocator, io: Io, path: []const u8) anyerror!*Io.Reader,
+ exported_parts: StringArrayHashMap([]const u8),
+ tags: []const ParserTag,
+ tag_stack: ArrayList([]const u8),
+};
+
+pub fn parseTemplate(arena: *ArenaAllocator, io: Io, state: *Parser, reader: *Io.Reader, writer: *Io.Writer) !void {
+ outer: while (true) {
+ _ = reader.streamDelimiter(writer, '<') catch |err| {
+ if (err == Io.Reader.Error.EndOfStream) break else return err;
+ };
+ // consume '<'
+ _ = try reader.takeByte();
+ if (try reader.peekByte() == '/') {
+ // consume '/'
+ _ = try reader.takeByte();
+ const last_tag = state.tag_stack.getLastOrNull() orelse "";
+ // if reached closing tag, send execution back up the stack
+ if (std.mem.eql(u8, last_tag, try reader.peekDelimiterExclusive('>'))) {
+ // consume closing tag
+ _ = try reader.takeDelimiterInclusive('>');
+ return;
+ } else {
+ try writer.writeAll("</");
+ continue :outer;
+ }
+ }
+ const inside = reader.takeDelimiterExclusive('>') catch |err| {
+ if (err == error.StreamTooLong) {
+ try writer.writeByte('<');
+ break :outer;
+ } else return err;
+ };
+ var it = std.mem.splitScalar(u8, inside, ' ');
+ const tag_name = it.first();
+ for (state.tags) |tag| {
+ if (std.mem.eql(u8, tag.name, tag_name) == true) {
+ // consume '>'
+ _ = try reader.takeByte();
+ try tag.parse_fn(arena, io, state, reader, writer, &it);
+ continue :outer;
+ }
+ }
+
+ try writer.writeByte('<');
+ try writer.writeAll(inside);
+ }
+}