diff options
| -rw-r--r-- | grammar.ebnf | 2 | ||||
| -rw-r--r-- | src/lexer/lexed.zig | 2 | ||||
| -rw-r--r-- | src/lexer/lexer.zig | 26 |
3 files changed, 25 insertions, 5 deletions
diff --git a/grammar.ebnf b/grammar.ebnf index d0259a1..664f68b 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -6,7 +6,7 @@ strong-delimiter = "\n\n", { "\n" }; (* blocks *) block = title | paragraph | quote | callout | code-block | math-block | image | footnotes; -title = ? #{1,6} ?, content; +title = ? #{1,6} ?, " ", content; paragraph = content, { weak-delimiter, content }; quote = ">", content, { weak-delimiter, ">", content }, [ paragraph ]; callout = ":::", [ ? [a-z]+ ? ], { delimiter, content }, weak-delimiter, ":::"; diff --git a/src/lexer/lexed.zig b/src/lexer/lexed.zig index a572c2a..59b6e31 100644 --- a/src/lexer/lexed.zig +++ b/src/lexer/lexed.zig @@ -13,6 +13,8 @@ pub const Kind = enum { bold, italic, ref, + list_ordored, + list_unordored, }; pub const Lexed = struct { 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); } |
