const std = @import("std"); const Allocator = std.mem.Allocator; const eql = std.mem.eql; const Token = @import("lexer/Token.zig"); const Lexer = @import("lexer/Lexer.zig"); const Element = @import("eval/Element.zig"); const testing = @import("testing.zig"); const doTest = testing.do; const doTestError = testing.doError; pub const Error = error{InvalidCodeBlock} || Allocator.Error; pub fn parse(alloc: Allocator, l: *Lexer) Error!Element { _ = l.next(); var beg = l.next() orelse return Error.InvalidCodeBlock; var data: ?[]const u8 = null; switch (beg.kind) { .literal => { data = beg.content; beg = l.next() orelse return Error.InvalidCodeBlock; if (!beg.kind.isDelimiter()) return Error.InvalidCodeBlock; }, else => if (!beg.kind.isDelimiter()) return Error.InvalidCodeBlock, } const code = try Element.Code.init(alloc); code.attribute = data; while (l.next()) |it| { if (it.kind == .code_block) return Error.InvalidCodeBlock; if (it.kind.isDelimiter()) { const next = l.peek() orelse return Error.InvalidCodeBlock; if (next.kind == .code_block) break; } try code.content.append(alloc, (try Element.Literal.init(alloc, it.content)).element()); // restore modifications done by the lexer if (it.kind.requiresSpace()) try code.content.append(alloc, (try Element.Literal.init(alloc, " ")).element()); } var end = l.next() orelse return Error.InvalidCodeBlock; if (end.kind != .code_block) return Error.InvalidCodeBlock; const el = try Element.Figure.init(alloc, code.element()); end = l.next() orelse return el.element(); if (!end.kind.isDelimiter()) return Error.InvalidCodeBlock; return el.element(); } test "code" { const alloc = std.testing.allocator; try doTest(parse, alloc, \\``` \\hey \\``` , "
hey
"); try doTest(parse, alloc, \\```td another \\hey \\``` , "
hey
"); // cannot test content with \n try doTestError(parse, alloc, "```", Error.InvalidCodeBlock); try doTestError(parse, alloc, \\``` \\hey , Error.InvalidCodeBlock); try doTestError(parse, alloc, \\``` \\hey``` , Error.InvalidCodeBlock); try doTestError(parse, alloc, \\``` \\hey \\``` nope , Error.InvalidCodeBlock); }