aboutsummaryrefslogtreecommitdiff
path: root/src/paragraph.zig
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2026-04-18 18:45:16 +0200
committerAnhgelus Morhtuuzh <william@herges.fr>2026-04-18 18:45:16 +0200
commite8e9d31559e38173093f11d99721392e32e21d60 (patch)
treee4c7b8449b7b7f4383a83414b36cb3b7edf5a1b3 /src/paragraph.zig
parent389691f4d11bf86c8be75927a2fbc01cff9c7059 (diff)
feat(ast): parse paragraph
Diffstat (limited to 'src/paragraph.zig')
-rw-r--r--src/paragraph.zig59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/paragraph.zig b/src/paragraph.zig
new file mode 100644
index 0000000..75651f4
--- /dev/null
+++ b/src/paragraph.zig
@@ -0,0 +1,59 @@
+const std = @import("std");
+const Lexed = @import("lexer/Lexed.zig");
+const Lexer = @import("lexer/Lexer.zig");
+const Element = @import("dom/Element.zig");
+const Allocator = std.mem.Allocator;
+const ast = @import("ast.zig");
+const Error = ast.Error;
+
+pub fn parseParagraph(alloc: Allocator, l: *Lexer) Error!Element {
+ var el = try Element.init(alloc, .content, "p");
+ while (l.nextKind()) |kind| {
+ switch (kind) {
+ // because nextKind returns only an hint for the next rune
+ .weak_delimiter => {
+ var v = (try l.next(alloc)).?;
+ defer v.deinit();
+ if (v.kind == .strong_delimiter) return el;
+ const next = l.nextKind() orelse return el;
+ switch (next) {
+ .literal, .italic, .code, .bold => try el.appendContent(try Element.initLit(alloc, " ")),
+ else => return el,
+ }
+ },
+ else => try el.appendContent(try parseContent(alloc, l)),
+ }
+ }
+ return el;
+}
+
+pub fn parseContent(alloc: Allocator, l: *Lexer) Error!Element {
+ var content = Element.initEmpty(alloc);
+ const v = (try l.next(alloc)).?;
+ switch (v.kind) {
+ .literal => {
+ const el = try Element.initLitEscaped(alloc, v.content.items);
+ try content.appendContent(el);
+ },
+ .bold => try content.appendContent(try parseModifier(alloc, l, .bold, "b")),
+ .italic => try content.appendContent(try parseModifier(alloc, l, .italic, "em")),
+ .code => try content.appendContent(try parseModifier(alloc, l, .code, "code")),
+ else => return Error.InvalidSequence,
+ }
+ return content;
+}
+
+fn parseModifier(alloc: Allocator, l: *Lexer, knd: Lexed.Kind, tag: []const u8) Error!Element {
+ var el = try Element.init(alloc, .content, tag);
+ while (l.nextKind()) |it| {
+ if (it == knd) {
+ // consuming the finisher
+ var v = (try l.next(alloc)).?;
+ v.deinit();
+ break;
+ }
+ if (it.isDelimiter()) return Error.UnclosedModifier;
+ try el.appendContent(try parseContent(alloc, l));
+ }
+ return el;
+}