feat(parser): lay groundworks for parser

main
Jef Roosens 2024-03-07 14:57:01 +01:00
parent 4ba3195ea0
commit 35aae48a7f
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
8 changed files with 192 additions and 1 deletions

30
include/mrk/ast.h 100644
View File

@ -0,0 +1,30 @@
#ifndef MRK_AST
#define MRK_AST
#include <stdlib.h>
#include "mrk/common.h"
#define MRK_AST_NODE_ARGS 1
typedef enum mrk_ast_node_type {
mrk_ast_node_type_header = 0,
} mrk_ast_node_type;
typedef struct mrk_ast_node {
struct {
struct mrk_ast_node **arr;
size_t len;
} children;
mrk_ast_node_type type;
void *args[MRK_AST_NODE_ARGS];
} mrk_ast_node;
/**
* Initialize a new AST node struct.
*/
mrk_err mrk_ast_node_init(mrk_ast_node **out);
mrk_err mrk_ast_node_child_append(mrk_ast_node *parent, mrk_ast_node *child);
#endif

View File

@ -11,6 +11,22 @@
*out = temp; \
}
#define MRK_RES(x) \
{ \
mrk_err res = x; \
if (res != mrk_err_ok) \
return res; \
}
#define MRK_RES2(x, e) \
{ \
mrk_err res = x; \
if (res != mrk_err_ok) { \
e; \
return res; \
} \
}
typedef enum mrk_err {
mrk_err_ok = 0,
mrk_err_failed_alloc,

View File

@ -14,7 +14,8 @@ typedef enum mrk_lexer_err {
} mrk_lexer_err;
typedef enum mrk_token_type {
mrk_token_type_pounds = 0,
mrk_token_type_none = 0,
mrk_token_type_pounds,
mrk_token_type_backticks,
mrk_token_type_dashes,
mrk_token_type_underscores,

View File

@ -0,0 +1,19 @@
#ifndef MRK_PARSER
#define MRK_PARSER
#include "mrk/ast.h"
#include "mrk/common.h"
#include "mrk/lexer.h"
typedef struct mrk_parser mrk_parser;
/**
* Initialize a new parser struct.
*/
mrk_err mrk_parser_init(mrk_parser **out);
void mrk_parser_open(mrk_parser *parser, mrk_lexer *lexer);
mrk_err mrk_parser_parse(mrk_ast_node **out, mrk_parser *parser);
#endif

View File

@ -0,0 +1,37 @@
#ifndef MRK_PARSER_INTERNAL
#define MRK_PARSER_INTERNAL
#include "mrk/lexer_internal.h"
#include "mrk/parser.h"
#define MRK_PARSER_LOOKAHEAD_BUF_SIZE 4
struct mrk_parser {
mrk_lexer *lexer;
struct {
mrk_token buf[MRK_PARSER_LOOKAHEAD_BUF_SIZE];
size_t index;
} lookahead;
};
/**
* Returns true if all the data from the lexer has been processed.
*
* Because the parser might buffer parts of the results of the lexer, this is
* not equivalent to calling lexer done.
*/
bool mrk_parser_done(mrk_parser *parser);
/**
* Return the next token that would be consumed by a call to advance.
*/
mrk_token mrk_parser_peek(mrk_parser *parser);
/**
* Advance the processing stream by one token.
*/
void mrk_parser_advance(mrk_parser *parser);
mrk_err mrk_parser_parse_block(mrk_ast_node **out, mrk_parser *parser);
#endif

25
src/ast.c 100644
View File

@ -0,0 +1,25 @@
#include "mrk/ast.h"
mrk_err mrk_ast_node_init(mrk_ast_node **out) {
MRK_CALLOC(out, 1, sizeof(mrk_ast_node));
return mrk_err_ok;
}
mrk_err mrk_ast_node_child_append(mrk_ast_node *parent, mrk_ast_node *child) {
mrk_ast_node **children =
parent->children.len == 0
? malloc(sizeof(mrk_ast_node *))
: realloc(parent->children.arr,
sizeof(mrk_ast_node *) * (parent->children.len + 1));
if (children == NULL) {
return mrk_err_failed_alloc;
}
children[parent->children.len] = child;
parent->children.arr = children;
parent->children.len++;
return mrk_err_ok;
}

View File

@ -0,0 +1,29 @@
#include "mrk/parser_internal.h"
void mrk_parser_open(mrk_parser *parser, mrk_lexer *lexer) {
parser->lexer = lexer;
// Prefill lookahead buffer
for (size_t i = 0;
i < MRK_PARSER_LOOKAHEAD_BUF_SIZE && !mrk_lexer_done(lexer); i++) {
mrk_lexer_next(&parser->lookahead.buf[i], lexer);
}
}
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_lexer_done(parser->lexer)) {
mrk_ast_node *block_root;
MRK_RES(mrk_parser_parse_block(&block_root, parser));
MRK_RES(mrk_ast_node_child_append(root, block_root));
}
*out = root;
return mrk_err_ok;
}
mrk_err mrk_parser_parse_block(mrk_ast_node **out, mrk_parser *parser) {}

34
src/parser/util.c 100644
View File

@ -0,0 +1,34 @@
#include "mrk/parser_internal.h"
bool mrk_parser_done(mrk_parser *parser) {
return mrk_lexer_done(parser->lexer) &&
parser->lookahead.buf[parser->lookahead.index].type ==
mrk_token_type_none;
}
mrk_token mrk_parser_peek(mrk_parser *parser) {
mrk_token out;
if (mrk_parser_done(parser)) {
out.type = mrk_token_type_none;
} else {
out = parser->lookahead.buf[parser->lookahead.index];
}
return out;
}
void mrk_parser_advance(mrk_parser *parser) {
if (mrk_parser_done(parser)) {
return;
}
// Append new element of the lexer to the lookahead buffer
if (!mrk_lexer_done(parser->lexer)) {
mrk_lexer_next(&parser->lookahead.buf[parser->lookahead.index],
parser->lexer);
}
parser->lookahead.index =
(parser->lookahead.index + 1) % MRK_PARSER_LOOKAHEAD_BUF_SIZE;
}