mrk/src/parser/parser.c

154 lines
4.1 KiB
C

#include "mrk/parser_internal.h"
#include <stdio.h>
mrk_err mrk_parser_init(mrk_parser **out) {
MRK_CALLOC(out, 1, sizeof(mrk_parser));
return mrk_err_ok;
}
void mrk_parser_open(mrk_parser *parser, mrk_lexer *lexer) {
parser->lexer = lexer;
// Prefill lookahead character
mrk_parser_advance(parser);
}
mrk_err mrk_parser_parse(mrk_ast_node **out, mrk_parser *parser) {
mrk_ast_node *root;
MRK_RES(mrk_ast_node_init(&root));
while (!mrk_parser_done(parser)) {
mrk_ast_node *child;
MRK_RES(mrk_ast_node_child_append(&child, root));
switch (mrk_parser_peek(parser).type) {
case mrk_token_type_header_start:
MRK_RES(mrk_parser_parse_header(child, parser));
break;
case mrk_token_type_text:
case mrk_token_type_left_bracket:
MRK_RES(mrk_parser_parse_paragraph(child, parser));
break;
}
}
*out = root;
return mrk_err_ok;
}
mrk_err mrk_parser_parse_header(mrk_ast_node *out, mrk_parser *parser) {
mrk_token header_token;
mrk_parser_eat(&header_token, parser, mrk_token_type_header_start);
out->type = mrk_ast_node_type_header;
out->d.header.depth = mrk_token_len(header_token);
// Parse subsections of header
while (!mrk_parser_done(parser)) {
mrk_ast_node *child;
switch (mrk_parser_peek(parser).type) {
case mrk_token_type_text:
MRK_RES(mrk_ast_node_child_append(&child, out));
MRK_RES(mrk_parser_parse_text(child, parser));
break;
// Newlines are interpreted as spaces
case mrk_token_type_newline:
MRK_RES(mrk_ast_node_child_append(&child, out));
child->type = mrk_ast_node_type_space;
mrk_parser_advance(parser);
break;
case mrk_token_type_left_bracket:
MRK_RES(mrk_ast_node_child_append(&child, out));
MRK_RES(mrk_parser_parse_link(child, parser));
break;
// Header definition ends at newline
case mrk_token_type_blank_line:
mrk_parser_advance(parser);
return mrk_err_ok;
}
}
return mrk_err_ok;
}
mrk_err mrk_parser_parse_text(mrk_ast_node *out, mrk_parser *parser) {
mrk_token text_token;
MRK_RES(mrk_parser_eat(&text_token, parser, mrk_token_type_text));
out->type = mrk_ast_node_type_text;
out->d.text.start = text_token.start;
out->d.text.end = text_token.end;
return mrk_err_ok;
}
mrk_err mrk_parser_parse_link(mrk_ast_node *out, mrk_parser *parser) {
out->type = mrk_ast_node_type_link;
MRK_RES(mrk_parser_eat(NULL, parser, mrk_token_type_left_bracket));
if (mrk_parser_done(parser)) {
parser->error.msg = "Unclosed brackets";
return mrk_err_invalid;
}
mrk_ast_node *child;
MRK_RES(mrk_ast_node_child_append(&child, out));
switch (mrk_parser_peek(parser).type) {
case mrk_token_type_text:
MRK_RES(mrk_parser_parse_text(child, parser));
break;
// TODO allow other types of text (e.g. cursive)
// TODO image links
default:
// TODO throw error
break;
}
MRK_RES(mrk_parser_eat(NULL, parser, mrk_token_type_right_bracket));
MRK_RES(mrk_parser_eat(NULL, parser, mrk_token_type_left_paren));
mrk_token url_token;
MRK_RES(mrk_parser_eat(&url_token, parser, mrk_token_type_text));
MRK_RES(mrk_parser_eat(NULL, parser, mrk_token_type_right_paren));
out->d.link.url_start = url_token.start;
out->d.link.url_end = url_token.end;
return mrk_err_ok;
}
mrk_err mrk_parser_parse_paragraph(mrk_ast_node *out, mrk_parser *parser) {
out->type = mrk_ast_node_type_paragraph;
while (!mrk_parser_done(parser)) {
mrk_ast_node *child;
switch (mrk_parser_peek(parser).type) {
case mrk_token_type_text:
MRK_RES(mrk_ast_node_child_append(&child, out));
MRK_RES(mrk_parser_parse_text(child, parser));
break;
case mrk_token_type_left_bracket:
MRK_RES(mrk_ast_node_child_append(&child, out));
MRK_RES(mrk_parser_parse_link(child, parser));
break;
case mrk_token_type_newline:
MRK_RES(mrk_ast_node_child_append(&child, out));
child->type = mrk_ast_node_type_space;
mrk_parser_advance(parser);
break;
case mrk_token_type_blank_line:
mrk_parser_advance(parser);
return mrk_err_ok;
}
}
return mrk_err_ok;
}