diff options
| author | Anhgelus Morhtuuzh <william@herges.fr> | 2026-04-15 14:41:33 +0200 |
|---|---|---|
| committer | Anhgelus Morhtuuzh <william@herges.fr> | 2026-04-15 14:41:33 +0200 |
| commit | e053ba532f1e58bb54f286b950e3be7166ba3dcd (patch) | |
| tree | f71d1efdacfdd0599938d8e5175b2f0e9b887033 /src/lexer/lexer.zig | |
| parent | 4a423b2f637143ff0135045733e0428cc9560597 (diff) | |
feat(lexer): supports link and image
Diffstat (limited to 'src/lexer/lexer.zig')
| -rw-r--r-- | src/lexer/lexer.zig | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/src/lexer/lexer.zig b/src/lexer/lexer.zig index a29384e..b76cd50 100644 --- a/src/lexer/lexer.zig +++ b/src/lexer/lexer.zig @@ -30,14 +30,14 @@ pub const Lexer = struct { self.force_lit = true; current_kind = .literal; } else { - current_kind = self.getCurrentKind(rune, acc.items); + current_kind = self.getCurrentKind(current_kind, rune, acc.items); self.force_lit = false; try acc.appendSlice(alloc, rune); } // conds here to avoid creating complex condition in while const next_rune = self.iter.peek(1); if (next_rune.len > 0) { - if (self.getCurrentKind(next_rune, acc.items) != current_kind.?) { + if (self.getCurrentKind(current_kind, next_rune, acc.items) != current_kind.?) { if (!requiresSpace(current_kind.?)) break; if (std.mem.eql(u8, next_rune, " ")) { // consume next space @@ -55,13 +55,15 @@ pub const Lexer = struct { return lexed.Lexed.init(alloc, kind, acc); } - fn getCurrentKind(self: *Self, rune: []const u8, acc: []const u8) lexed.Kind { + fn getCurrentKind(self: *Self, before: ?lexed.Kind, rune: []const u8, acc: []const u8) lexed.Kind { if (self.force_lit) return .literal; if (std.mem.eql(u8, rune, ">")) return .quote; if (std.mem.eql(u8, rune, "\n")) return .delimiter; + if (std.mem.eql(u8, rune, "!")) return .image; if (is('#', 6, rune, acc)) return .title; if (is('`', 3, rune, acc)) return .code; if (is('$', 3, rune, acc)) return .math; + if (isIn(links, before, .link, rune, acc)) return .link; return .literal; } }; @@ -72,6 +74,21 @@ fn is(v: u8, maxLen: usize, rune: []const u8, acc: []const u8) bool { return std.mem.eql(u8, rune, &[_]u8{v}); } +const links = &[_][]const u8{ "[", "](", ")" }; + +fn isIn(ops: []const []const u8, before: ?lexed.Kind, now: lexed.Kind, rune: []const u8, p: []const u8) bool { + var acc = p; + if (before) |b| { + if (now != b) acc = &[_]u8{}; + } + for (ops) |op| { + const ln = acc.len + rune.len; + if (op.len >= ln and std.mem.eql(u8, acc, op[0..acc.len]) and std.mem.eql(u8, rune, op[acc.len..ln])) + return true; + } + return false; +} + fn requiresSpace(k: lexed.Kind) bool { return switch (k) { .title => true, @@ -98,7 +115,8 @@ test "lexer common" { var l = try Lexer.init("# hello world :)"); try doTest(alloc, &l, .title, "#"); - try doTest(alloc, &l, .literal, "hello world :)"); + try doTest(alloc, &l, .literal, "hello world :"); + try doTest(alloc, &l, .link, ")"); try expect(try l.next(alloc) == null); } |
