#include "mrk/ast.h" #include "test.h" #include "mrk/lexer.h" #include "mrk/parser_internal.h" #define LEXER_INIT() \ mrk_lexer *lxr; \ TEST_CHECK(mrk_lexer_init(&lxr) == mrk_err_ok) #define PARSER_INIT() \ mrk_parser *parser; \ TEST_CHECK(mrk_parser_init(&parser) == mrk_err_ok) #define PARSER_OPEN(buf) \ mrk_lexer *lxr; \ TEST_CHECK(mrk_lexer_init(&lxr) == mrk_err_ok); \ mrk_parser *parser; \ TEST_CHECK(mrk_parser_init(&parser) == mrk_err_ok); \ mrk_lexer_open(lxr, buf, 0); \ mrk_parser_open(parser, lxr) void test_parse_header() { const char *buf = "### hello world"; PARSER_OPEN(buf); mrk_ast_node *header; mrk_ast_node_init(&header); TEST_CHECK(mrk_parser_parse_header(header, parser) == mrk_err_ok); TEST_CHECK(header->type == mrk_ast_node_type_header); TEST_CHECK(header->d.header.depth == 3); TEST_CHECK(header->children.len == 1); mrk_ast_node *header_text = header->children.arr[0]; TEST_CHECK(header_text->type == mrk_ast_node_type_text); TEST_CHECK(header_text->d.text.start == 3); TEST_CHECK(header_text->d.text.end == 15); } void test_parse_link() { const char *buf = "[hello world](https://example.com)"; PARSER_OPEN(buf); mrk_ast_node *link; mrk_ast_node_init(&link); TEST_CHECK(mrk_parser_parse_link(link, parser) == mrk_err_ok); TEST_CHECK(link->type == mrk_ast_node_type_link); TEST_CHECK(link->d.link.url_start == 14); TEST_CHECK(link->d.link.url_end == 33); TEST_CHECK(link->children.len == 1); mrk_ast_node *link_text = link->children.arr[0]; TEST_CHECK(link_text->type == mrk_ast_node_type_text); TEST_CHECK(link_text->d.text.start == 1); TEST_CHECK(link_text->d.text.end == 12); } void test_parse_unordered_list() { const char *buf = "* element one\n* element two\n\n paragraph in element two"; PARSER_OPEN(buf); mrk_ast_node *list; mrk_ast_node_init(&list); TEST_CHECK(mrk_parser_parse_list(list, parser) == mrk_err_ok); TEST_CHECK(list->type == mrk_ast_node_type_list); TEST_CHECK(!list->d.list.ordered); TEST_CHECK(list->children.len == 2); mrk_ast_node *child = list->children.arr[0]; TEST_CHECK(child->type == mrk_ast_node_type_list_item); TEST_CHECK(!child->d.list_item.checkbox); TEST_CHECK(child->children.len == 1); mrk_ast_node *subchild = child->children.arr[0]; TEST_CHECK(subchild->type == mrk_ast_node_type_text); TEST_CHECK(subchild->d.text.start == 2); TEST_CHECK(subchild->d.text.end == 13); child = list->children.arr[1]; TEST_CHECK(child->type == mrk_ast_node_type_list_item); TEST_CHECK(!child->d.list_item.checkbox); TEST_CHECK(child->children.len == 2); subchild = child->children.arr[0]; TEST_CHECK(subchild->type == mrk_ast_node_type_text); TEST_CHECK(subchild->d.text.start == 16); TEST_CHECK(subchild->d.text.end == 27); subchild = child->children.arr[1]; TEST_CHECK(subchild->type == mrk_ast_node_type_paragraph); TEST_CHECK(subchild->children.len == 1); TEST_CHECK(subchild->children.arr[0]->type == mrk_ast_node_type_text); TEST_CHECK(subchild->children.arr[0]->d.text.start == 33); TEST_CHECK(subchild->children.arr[0]->d.text.end == 57); } void test_parse_code() { const char *buf = "`world [hello](link)`"; PARSER_OPEN(buf); mrk_ast_node *code; mrk_ast_node_init(&code); TEST_CHECK(mrk_parser_parse_code(code, parser) == mrk_err_ok); TEST_CHECK(code->type == mrk_ast_node_type_code); TEST_CHECK(code->children.len == 1); mrk_ast_node *child = code->children.arr[0]; TEST_CHECK(child->type == mrk_ast_node_type_text); TEST_CHECK(child->d.text.start == 1); TEST_MSG("start: %lu", child->d.text.start); TEST_CHECK(child->d.text.end == 20); TEST_MSG("end: %lu", child->d.text.end); } TEST_LIST = { { "parser header", test_parse_header }, { "parser link", test_parse_link }, { "parser unordered list", test_parse_unordered_list }, { "parser code", test_parse_code }, { NULL, NULL } };