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; \
|
||||
}
|
||||
|
||||
#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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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