feat(parser): lay groundworks for parser
parent
4ba3195ea0
commit
35aae48a7f
|
@ -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
|
|
@ -11,6 +11,22 @@
|
||||||
*out = temp; \
|
*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 {
|
typedef enum mrk_err {
|
||||||
mrk_err_ok = 0,
|
mrk_err_ok = 0,
|
||||||
mrk_err_failed_alloc,
|
mrk_err_failed_alloc,
|
||||||
|
|
|
@ -14,7 +14,8 @@ typedef enum mrk_lexer_err {
|
||||||
} mrk_lexer_err;
|
} mrk_lexer_err;
|
||||||
|
|
||||||
typedef enum mrk_token_type {
|
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_backticks,
|
||||||
mrk_token_type_dashes,
|
mrk_token_type_dashes,
|
||||||
mrk_token_type_underscores,
|
mrk_token_type_underscores,
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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) {}
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue